7a320b0f by chenyunhao

更新常见问题答疑

1 parent 940afc33
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
22 "nprogress": "0.2.0", 22 "nprogress": "0.2.0",
23 "vue": "2.5.17", 23 "vue": "2.5.17",
24 "vue-router": "3.0.1", 24 "vue-router": "3.0.1",
25 "vuex": "3.0.1" 25 "vuex": "3.0.1",
26 "@wangeditor/editor": "^5.1.1",
27 "@wangeditor/editor-for-vue": "^1.0.2"
26 }, 28 },
27 "devDependencies": { 29 "devDependencies": {
28 "autoprefixer": "8.5.0", 30 "autoprefixer": "8.5.0",
...@@ -84,4 +86,4 @@ ...@@ -84,4 +86,4 @@
84 "last 2 versions", 86 "last 2 versions",
85 "not ie <= 8" 87 "not ie <= 8"
86 ] 88 ]
87 } 89 }
...\ No newline at end of file ...\ No newline at end of file
......
1 module.exports = { 1 module.exports = {
2 testListGet: '/xxx/xxx/list', 2 getArticleClassify: '/admin/articleApi/classify/list',
3 setArticleClassify: '/admin/articleApi/classify',
4
5 getArticleList: '/admin/articleApi/article/list',
6 setArticleList: '/admin/articleApi/article',
7 getArticleDetail: '/admin/articleApi/article',
8 setArticle: '/admin/articleApi/article/save',
9
10 getArticleDashboard: '/admin/articleApi/stat/dashboard',
11 getArticleViewRank: '/admin/articleApi/stat/viewRank',
12 exportArticleViewRank: '/admin/articleApi/stat/viewRank/export',
13 getArticleClassifyRank: '/admin/articleApi/stat/classifyRank',
14 exportArticleClassifyRank: '/admin/articleApi/stat/classifyRank/export',
15
16 getArticleKeywordList: '/admin/articleApi/keyword/list',
17 setArticleKeywordList: '/admin/articleApi/keyword',
18 getArticleKeywordStat: '/admin/articleApi/keyword/stat',
19
20 upload: "/common/upload",
21
3 exportTable: exportTable, 22 exportTable: exportTable,
4 } 23 }
5 24
......
1 import axios from 'axios';
2 // import router from './../router'
3 import router from '@/router/index'
4 import {
5 Message
6 } from 'element-ui'
7 import {
8 getToken,
9 setToken,
10 removeToken
11 } from '@/utils/auth'
12
13
14 // 可以使用
15 import {
16 MessageBox
17 } from 'element-ui'
18
19 /**
20 * 提示方法,自行处理
21 * 可以使用 MessageBox
22 *
23 * @param {*} data
24 */
25 let alreadyToast = false
26
27 function Toast(data) {
28 if (alreadyToast) {
29 return;
30 }
31 alreadyToast = true;
32 MessageBox.alert(data.message, '警告', {
33 confirmButtonText: '确定',
34 callback: action => {
35 alreadyToast = false;
36 // this.$message({
37 // type: 'info',
38 // message: `action: ${action}`
39 // })
40 }
41 })
42 }
43
44 // axios的默认url
45 // axios.defaults.baseURL = ""
46 let base = 'https://api.k.wxpai.cn/bizproxy/tianbaoServiceApi';
47
48 // 默认超时
49 axios.defaults.timeout = 60000;
50
51 // 响应拦截器
52 axios.interceptors.response.use(
53 response => {
54 if (response.status === 200) {
55 if (response.config.responseType == 'blob') {
56 return Promise.resolve(response)
57 } else if (response.data.code === 200) {
58 return Promise.resolve(response);
59 } else if (response.data.code == 404) {
60 Toast({
61 message: '登录过期,请重新登录',
62 duration: 1000,
63 forbidClick: true
64 });
65 removeToken();
66 setTimeout(() => {
67 router.replace({
68 path: '/login',
69 query: {
70 redirect: router.currentRoute.fullPath
71 }
72 });
73 }, 1000);
74 } else {
75 Message({
76 showClose: true,
77 message: response.data.errMsg,
78 type: 'error',
79 duration: 3000
80 })
81 return Promise.reject(response);
82 }
83 } else {
84 return Promise.reject(response);
85 }
86 },
87 // 服务器状态码不是200的情况
88 error => {
89 if (error.response.status) {
90 switch (error.response.status) {
91 // 401: 未登录
92 // 未登录则跳转登录页面,并携带当前页面的路径
93 // 在登录成功后返回当前页面,这一步需要在登录页操作。
94 case 401:
95 router.replace({
96 path: '/login',
97 query: {
98 redirect: router.currentRoute.fullPath
99 }
100 });
101 break;
102 case 404:
103 // Toast({
104 // message: '登录过期,请重新登录',
105 // duration: 1000,
106 // forbidClick: true
107 // });
108 // removeToken();
109 // setTimeout(() => {
110 // router.replace({
111 // path: '/login',
112 // query: {
113 // redirect: router.currentRoute.fullPath
114 // }
115 // });
116 // }, 1000);
117 break;
118 // 405请求不存在
119 case 405:
120 Toast({
121 message: '网络请求不存在',
122 duration: 1500,
123 forbidClick: true
124 });
125 break;
126 // 其他错误,直接抛出错误提示
127 default:
128 Toast({
129 message: error.response.data.errMsg,
130 duration: 1500,
131 forbidClick: true
132 });
133 }
134 return Promise.reject(error.response);
135 }
136 }
137 );
138
139
140 /**
141 * 分解参数
142 */
143 function analysisParams(params) {
144 let {
145 url,
146 data,
147 mode,
148 opt = Object.assign({}, params.opt),
149 sid = true,
150 config,
151 method
152 } = params;
153
154 if (opt.dec) {
155 data = makerypt(data);
156 }
157 let reqUrl = `${base}${url}`;
158 if (mode == "custom") {
159 reqUrl = `${url}`
160 }
161 let headers = {}
162 if (sid) {
163 // headers.sessionId = getToken();
164 headers.adminSessionId = getAdminToken();
165 }
166
167 // console.log({
168 // reqUrl,
169 // data,
170 // headers,
171 // opt,
172 // method,
173 // config
174 // });
175 return {
176 reqUrl,
177 data,
178 headers,
179 opt,
180 method,
181 config
182 }
183 }
184
185 /**
186 * 封装get方法
187 * @param {*} params
188 */
189 export const httpGet = params => {
190 params.method = 'get';
191 let {
192 reqUrl,
193 data,
194 headers,
195 opt,
196 method
197 } = analysisParams(params);
198 return axios.get(reqUrl, {
199 params: data,
200 headers,
201 opt
202 }).then(res => res.data.content);
203 }
204
205 /**
206 * 封装post方法
207 * mode为custom时,忽略baseUrl
208 * @param {*} params
209 */
210 export const httpPost = params => {
211 params.method = 'post';
212 let {
213 reqUrl,
214 data,
215 headers,
216 opt,
217 method
218 } = analysisParams(params);
219 return axios.post(reqUrl, data, {
220 headers,
221 opt
222 }).then(res => res.data.content);
223 }
224
225
226 export const httpDelete = params => {
227 params.method = 'delete';
228 let {
229 reqUrl,
230 data,
231 headers,
232 opt,
233 method
234 } = analysisParams(params);
235 // headers["Content-Type"] = "application/json"
236 return axios.delete(reqUrl, {
237 data,
238 headers,
239 opt
240 }).then(res => res.data.content);
241 }
242
243 /**
244 * 请求封装
245 * 默认 post 可通过 method设置为get
246 *
247 * @param {*} params
248 * @returns
249 */
250 export const request = params => {
251 let {
252 reqUrl,
253 data,
254 headers,
255 opt,
256 method
257 } = analysisParams(params);
258
259 if (method.toLowerCase() == "post") {
260 return axios.post(reqUrl, data, {
261 headers,
262 opt
263 }).then(res => res.data.content);
264 } else {
265 return axios.get(reqUrl, {
266 params: data,
267 headers,
268 opt
269 }).then(res => res.data.content);
270 }
271 }
272
273 /**
274 * 封装post方法
275 * @param {*} params
276 * data数据是 formdata格式
277 * 例如:
278 * this.file = file
279 let data = new FormData() //使用formData对象
280 data.append('path', '/pro/mzczcradmin/')
281 data.append('file', file.file)
282 */
283 export const httpFormdata = params => {
284 let {
285 reqUrl,
286 data,
287 headers,
288 opt,
289 method
290 } = analysisParams(params);
291 headers["Content-Type"] = "multipart/form-data";
292 return axios.post(reqUrl, data, {
293 headers
294 }).then(res => res.data.content);
295 }
296
297 export const downloadExcel = (params, fileName) => {
298 let {
299 reqUrl,
300 data,
301 headers,
302 config
303 } = analysisParams(params);
304 return axios({
305 method: 'get',
306 url: reqUrl,
307 params: data,
308 headers: headers,
309 responseType: 'blob',
310 ...config
311 }).then(res => {
312 let blob = new Blob([res.data], {
313 type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
314 })
315 let downloadElement = document.createElement('a')
316 let href = window.URL.createObjectURL(blob)
317 downloadElement.style.display = 'none'
318 downloadElement.href = href
319 downloadElement.download = fileName //下载后文件名
320 document.body.appendChild(downloadElement)
321 downloadElement.click() //点击下载
322 document.body.removeChild(downloadElement) //下载完成移除元素
323 window.URL.revokeObjectURL(href) //释放掉blob对象
324 }).catch(err => {
325 console.log('err', err)
326 Toast({
327 message: '下载失败,请重新下载'
328 })
329 })
330 }
331
332 function getAdminToken() {
333 try {
334 let token = getToken();
335 if (token != null && token != undefined) {
336 return token.adminSessionId;
337 }
338 return "";
339 } catch (e) {
340 console.error(e);
341 return "";
342 }
343 }
344
345 export function getHeaders() {
346 return {
347 'adminSessionId': getAdminToken(),
348 }
349 }
350
351 // 导出表格
352 export const buildExcelHeader = params => {
353 let {
354 reqUrl,
355 data,
356 headers
357 } = analysisParams(params);
358 let {
359 filename
360 } = params;
361 return axios({
362 method: 'get',
363 url: reqUrl,
364 params: data,
365 headers: headers,
366 responseType: 'blob'
367 // onDownloadProgress:?config.onDownloadProgress
368 }).then(res => {
369 let blob = new Blob([res.data], {
370 type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
371 })
372 let downloadElement = document.createElement('a')
373 let href = window.URL.createObjectURL(blob)
374 downloadElement.style.display = 'none'
375 downloadElement.href = href
376 downloadElement.download = filename //下载后文件名
377 document.body.appendChild(downloadElement)
378 downloadElement.click() //点击下载
379 document.body.removeChild(downloadElement) //下载完成移除元素
380 window.URL.revokeObjectURL(href) //释放掉blob对象
381 }).catch(err => {
382 console.log("err", err)
383 Toast({
384 message: '下载失败,请重新下载'
385 })
386 })
387 }
1 import request from '@/utils/request' 1 // import request from '@/utils/request'
2 2
3 export function login(username, password) { 3 export function login(username, password) {
4 return request({ 4 return request({
......
1 import request from '@/utils/request' 1 // import request from '@/utils/request'
2 2
3 export function getList(params) { 3 export function getList(params) {
4 return request({ 4 return request({
......
1 <template>
2 <div :class="{'hide' : hideUpload}">
3 <el-upload
4 :file-list="fileList"
5 :action="reqUrl"
6 :headers="headers"
7 :onSuccess="onSuccess"
8 :accept="isImg ? 'image/*' : ''"
9 list-type="picture-card"
10 :onPreview="onPreview"
11 :onRemove="onRemove"
12 :beforeUpload="beforeUpload"
13 :limit="limit || 1"
14 :data="extraData"
15 :disabled="disabled"
16 >
17 <i class="el-icon-plus"></i>
18 <div slot="tip" class="el-upload__tip">{{tips}}</div>
19 </el-upload>
20 <el-dialog :visible.sync="dialogVisible">
21 <img width="100%" :src="dialogImageUrl" alt />
22 </el-dialog>
23 <p v-if="sizeTips" class="tips">{{sizeTips}}</p>
24 </div>
25 </template>
26
27 <script>
28 /*
29 * value:当前上传的图片链接 String多图逗号隔开
30 * limit:当前最大上传数,默认为1
31 * isImg:true=限制上传类型为png或jpg,fales=不限制上传类型,默认为false
32 * maxFileSize:限制文件上传最大值
33 * subPath:图片上传目录
34 * disabled: 是否禁用上传F
35 */
36 export default {
37 name: "UploadImg",
38 props: [
39 "value",
40 "limit",
41 "isImg",
42 "maxFileSize",
43 "subPath",
44 "tip",
45 "disabled",
46 "sizeTips"
47 ],
48 data() {
49 return {
50 reqUrl: 'https://api.k.wxpai.cn/bizproxy/tianbaoServiceApi/' + app.api.upload,
51 headers: app.headers(),
52 dialogVisible: false,
53 hideUpload: false,
54 dialogImageUrl: "",
55 tips: "",
56 maxSize: 10 * 1024 * 1024,
57 fileList: [],
58 extraData: {} //上传额外参数
59 };
60 },
61 watch: {
62 value(newVal) {
63 this.initData();
64 }
65 },
66 created() {
67 this.initData();
68 },
69 methods: {
70 initData() {
71 if (this.value) {
72 this.fileList = [];
73 let _value = this.value.split(",");
74 for (let i = 0; i < _value.length; i++) {
75 let obj = {
76 url: _value[i],
77 uid: i
78 };
79 this.fileList.push(obj);
80 }
81 }
82 this.tips = this.tip;
83 if (this.subPath) {
84 this.extraData.subPath = this.subPath;
85 }
86 this.isMaxNumber();
87 // if (this.isImg && this.maxFileSize) {
88 // this.tips =
89 // "只能上传jpg/png文件,且文件不超过" + this.maxFileSize + "K";
90 // } else if (this.isImg) {
91 // this.tips = "只能上传jpg/png文件";
92 // } else if (this.maxFileSize > 0) {
93 // this.tips = "文件不超过" + this.maxFileSize + "K";
94 // }
95 },
96 onSuccess(res, file) {
97 let nowFileList = [];
98 if (res.code == 200) {
99 this.fileList.push({
100 url: res.content
101 });
102 this.isMaxNumber();
103 for (let i = 0; i < this.fileList.length; i++) {
104 nowFileList.push(this.fileList[i].url);
105 }
106 this.$emit("input", nowFileList.join(","));
107 } else {
108 this.$notify.error({
109 title: "错误",
110 message: res.errMsg
111 });
112 }
113 },
114 onPreview(file) {
115 this.dialogImageUrl = file.url;
116 this.dialogVisible = true;
117 },
118 beforeUpload(file) {
119 if (this.maxFileSize) {
120 const isSize = file.size / 1024 < this.maxFileSize;
121 if (!isSize) {
122 this.$message.error(
123 "上传图片大小不能超过 " + this.maxFileSize + "K!"
124 );
125 return false;
126 }
127 }
128
129 return true;
130 },
131 onRemove(file, fileList) {
132 let nowFileList = [];
133 for (let i = 0; i < this.fileList.length; i++) {
134 if (this.fileList[i].uid == file.uid) {
135 this.fileList.splice(i, 1);
136 for (let i = 0; i < this.fileList.length; i++) {
137 nowFileList.push(this.fileList[i].url);
138 }
139 this.isMaxNumber();
140 break;
141 }
142 }
143 this.$emit("input", nowFileList.join(","));
144 },
145 isMaxNumber() {
146 if (this.limit) {
147 this.hideUpload = this.limit <= this.fileList.length;
148 } else {
149 this.hideUpload = this.fileList.length > 0;
150 }
151 }
152 }
153 };
154 </script>
155
156 <style lang="scss" scoped>
157 .el-upload__tip {
158 // margin-top: -15px;
159 }
160 .hide /deep/.el-upload--picture-card {
161 display: none;
162 }
163 .tips {
164 margin: 0;
165 font-size: 12px;
166 line-height: 12px;
167 }
168 </style>
1 <template>
2 <div class="page" style="border: 1px solid #ccc;">
3 <Toolbar
4 style="border-bottom: 1px solid #ccc"
5 :editor="editor"
6 :defaultConfig="toolbarConfig"
7 :mode="mode"
8 />
9 <Editor
10 style="height: 500px; overflow-y: hidden;"
11 v-model="html"
12 :defaultConfig="editorConfig"
13 :mode="mode"
14 @onCreated="onCreated"
15 />
16 </div>
17 </template><script>
18 import Vue from "vue";
19 import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
20
21 export default Vue.extend({
22 props: ["value", "subPath"],
23 components: { Editor, Toolbar },
24 data() {
25 return {
26 editor: null,
27 html: "<p><br></p>",
28 toolbarConfig: {
29 excludeKeys: [
30 "insertLink",
31 "todo",
32 "fullScreen",
33 "fontFamily",
34 "lineHeight",
35 "insertTable",
36 "codeBlock"
37 ]
38 },
39 editorConfig: {
40 placeholder: "请输入内容...",
41 // autoFocus: false,
42
43 // 所有的菜单配置,都要在 MENU_CONF 属性下
44 MENU_CONF: {
45 uploadImage: {
46 fieldName: "file",
47 server:
48 "https://api.k.wxpai.cn/bizproxy/tianbaoServiceApi/" +
49 app.api.upload,
50 meta: {
51 subPath: this.subPath
52 },
53 customInsert(res, insertFn) {
54 console.log(res);
55 // res 即服务端的返回结果
56
57 // 从 res 中找到 url alt href ,然后插图图片
58 insertFn(res.content, "", "");
59 }
60 },
61
62 uploadVideo: {
63 fieldName: "file",
64 server:
65 "https://api.k.wxpai.cn/bizproxy/tianbaoServiceApi/" +
66 app.api.upload,
67 meta: {
68 subPath: this.subPath
69 },
70 customInsert(res, insertFn) {
71 console.log(res);
72 // res 即服务端的返回结果
73
74 // 从 res 中找到 url alt href ,然后插图图片
75 insertFn(res.content, "", "");
76 }
77 }
78 }
79 },
80 mode: "default" // or 'simple'
81 };
82 },
83 watch: {
84 html(newVal, oldVal) {
85 this.$emit("input", newVal);
86 }
87 },
88 methods: {
89 onCreated(editor) {
90 this.editor = Object.seal(editor); // 一定要用 Object.seal() ,否则会报错
91 },
92 onCreated(editor) {
93 this.editor = Object.seal(editor); // 【注意】一定要用 Object.seal() 否则会报错
94 editor.on("modalOrPanelShow", modalOrPanel => {});
95 // 可监听 `modalOrPanelShow` 和 `modalOrPanelHide` 自定义事件来设置样式、蒙层
96 // this.editor.on("modalOrPanelShow", modalOrPanel => {
97 // modalOrPanel.isShow = false;
98 // // modalOrPanel.$elem[0].style.display = "none";
99 // // if (modalOrPanel.type !== "modal") return;
100 // // const { $elem } = modalOrPanel; // modal element
101
102 // // 设置 modal 样式(定位、z-index)
103 // // 显示蒙层
104 // });
105 this.editor.on("modalOrPanelHide", () => {
106 // 隐藏蒙层
107 });
108 },
109 onOk() {
110 this.editor.restoreSelection();
111 SlateTransforms.setNodes(
112 this.editor,
113 { alt: this.alt, href: this.href },
114 { match: n => SlateElement.isElement(n) }
115 );
116 },
117 onChange(editor) {
118 console.log("onChange", editor.getHtml()); // onChange 时获取编辑器最新内容
119 // console.log(this.editor.getFragment());
120 }
121 },
122 mounted() {
123 setTimeout(() => {
124 this.html = this.value;
125 }, 500);
126 },
127 beforeDestroy() {
128 const editor = this.editor;
129 if (editor == null) return;
130 editor.destroy(); // 组件销毁时,及时销毁编辑器
131 }
132 });
133 </script>
134 <style src="@wangeditor/editor/dist/css/style.css"></style>
135 <style lang="scss" scoped>
136 </style>
...\ No newline at end of file ...\ No newline at end of file
...@@ -4,7 +4,6 @@ import 'normalize.css/normalize.css' // A modern alternative to CSS resets ...@@ -4,7 +4,6 @@ import 'normalize.css/normalize.css' // A modern alternative to CSS resets
4 4
5 import ElementUI from 'element-ui' 5 import ElementUI from 'element-ui'
6 import 'element-ui/lib/theme-chalk/index.css' 6 import 'element-ui/lib/theme-chalk/index.css'
7 import locale from 'element-ui/lib/locale/lang/en' // lang i18n
8 7
9 import '@/styles/index.scss' // global css 8 import '@/styles/index.scss' // global css
10 9
...@@ -13,7 +12,17 @@ import store from './store' ...@@ -13,7 +12,17 @@ import store from './store'
13 import router from './router' 12 import router from './router'
14 13
15 import '@/icons' // icon 14 import '@/icons' // icon
16 import '@/permission' // permission control 15 // import '@/permission' // permission control
16
17
18 import {
19 httpGet,
20 httpPost,
21 httpDelete,
22 httpFormdata,
23 getHeaders,
24 downloadExcel
25 } from '@/api/fetch-api-new.js'
17 26
18 27
19 /** 28 /**
...@@ -24,12 +33,26 @@ import '@/permission' // permission control ...@@ -24,12 +33,26 @@ import '@/permission' // permission control
24 * it will intercept your request, so you won't see the request in the network. 33 * it will intercept your request, so you won't see the request in the network.
25 * If you remove `../mock` it will automatically request easy-mock data. 34 * If you remove `../mock` it will automatically request easy-mock data.
26 */ 35 */
27 import '../mock' // simulation data 36 // import '../mock' // simulation data
28 37
29 Vue.use(ElementUI, { locale }) 38 Vue.use(ElementUI)
30 39
31 Vue.config.productionTip = false 40 Vue.config.productionTip = false
32 41
42
43 // 配置api
44 let api = require('@/api/api');
45 // 挂载全局app
46 app.api = api;
47 app.get = httpGet;
48 app.post = httpPost;
49 app.delete = httpDelete;
50 app.form = httpFormdata;
51 app.headers = getHeaders;
52 app.downloadExcel = downloadExcel;
53 app.router = router;
54 window.app = app;
55
33 new Vue({ 56 new Vue({
34 el: '#app', 57 el: '#app',
35 router, 58 router,
......
...@@ -114,8 +114,7 @@ export const constantRouterMap = [{ ...@@ -114,8 +114,7 @@ export const constantRouterMap = [{
114 title: '天宝计算器', 114 title: '天宝计算器',
115 icon: 'nested' 115 icon: 'nested'
116 }, 116 },
117 children: [ 117 children: [{
118 {
119 path: '/calculator/pvpage', 118 path: '/calculator/pvpage',
120 name: 'pvpage', 119 name: 'pvpage',
121 component: () => import('@/views/calculator/pvpage'), 120 component: () => import('@/views/calculator/pvpage'),
...@@ -159,8 +158,7 @@ export const constantRouterMap = [{ ...@@ -159,8 +158,7 @@ export const constantRouterMap = [{
159 title: '教育教学', 158 title: '教育教学',
160 icon: 'nested' 159 icon: 'nested'
161 }, 160 },
162 children: [ 161 children: [{
163 {
164 path: '/edu/live', 162 path: '/edu/live',
165 name: 'live', 163 name: 'live',
166 component: () => import('@/views/live/index'), 164 component: () => import('@/views/live/index'),
...@@ -253,6 +251,104 @@ export const constantRouterMap = [{ ...@@ -253,6 +251,104 @@ export const constantRouterMap = [{
253 ] 251 ]
254 }, 252 },
255 253
254
255
256 {
257 path: '/artice',
258 component: Layout,
259 redirect: '/artice/list',
260 name: 'artice',
261 meta: {
262 title: '常见问题答疑',
263 icon: 'nested'
264 },
265 children: [{
266 path: '/artice/list',
267 name: 'articleList',
268 component: () => import('@/views/Q&A/article/list'),
269 meta: {
270 title: '文章列表',
271 icon: ''
272 }
273 },
274 {
275 path: '/artice/detail',
276 name: 'articleDetail',
277 component: () => import('@/views/Q&A/article/detail'),
278 meta: {
279 title: '设置文章',
280 icon: ''
281 },
282 hidden: true
283 },
284 {
285 path: '/report/article',
286 name: 'reportArticle',
287 component: () => import('@/views/Q&A/report/article'),
288 meta: {
289 title: '文章统计',
290 icon: ''
291 }
292 },
293 {
294 path: '/artice/classify',
295 name: 'articeClassify',
296 component: () => import('@/views/Q&A/classify/list'),
297 meta: {
298 title: '文章分类',
299 icon: ''
300 }
301 },
302 {
303 path: '/artice/classify/detail',
304 name: 'articeClassifyDetail',
305 component: () => import('@/views/Q&A/classify/detail'),
306 meta: {
307 title: '设置分类',
308 icon: ''
309 },
310 hidden: true
311 },
312 {
313 path: '/report/classify',
314 name: 'reportClassify',
315 component: () => import('@/views/Q&A/report/classify'),
316 meta: {
317 title: '分类统计',
318 icon: ''
319 }
320 },
321 {
322 path: '/keyword/list',
323 name: 'keywordList',
324 component: () => import('@/views/Q&A/keyword/list'),
325 meta: {
326 title: '关键词',
327 icon: ''
328 }
329 },
330 {
331 path: '/keyword/detail',
332 name: 'keywordDetail',
333 component: () => import('@/views/Q&A/keyword/detail'),
334 meta: {
335 title: '设置关键词',
336 icon: ''
337 },
338 hidden: true
339 },
340 {
341 path: '/report/keyword',
342 name: 'reportKeyword',
343 component: () => import('@/views/Q&A/report/keyword'),
344 meta: {
345 title: '关键词统计',
346 icon: ''
347 }
348 },
349 ]
350 },
351
256 // { 352 // {
257 // path: '/live', 353 // path: '/live',
258 // component: Layout, 354 // component: Layout,
......
...@@ -4,6 +4,6 @@ const getters = { ...@@ -4,6 +4,6 @@ const getters = {
4 token: state => state.user.token, 4 token: state => state.user.token,
5 avatar: state => state.user.avatar, 5 avatar: state => state.user.avatar,
6 name: state => state.user.name, 6 name: state => state.user.name,
7 roles: state => state.user.roles 7 // roles: state => state.user.roles
8 } 8 }
9 export default getters 9 export default getters
......
1 import Vue from 'vue' 1 import Vue from 'vue'
2 import Vuex from 'vuex' 2 import Vuex from 'vuex'
3 import app from './modules/app' 3 import app from './modules/app'
4 import user from './modules/user' 4 // import user from './modules/user'
5 import getters from './getters' 5 import getters from './getters'
6 6
7 Vue.use(Vuex) 7 Vue.use(Vuex)
...@@ -9,7 +9,7 @@ Vue.use(Vuex) ...@@ -9,7 +9,7 @@ Vue.use(Vuex)
9 const store = new Vuex.Store({ 9 const store = new Vuex.Store({
10 modules: { 10 modules: {
11 app, 11 app,
12 user 12 // user
13 }, 13 },
14 getters 14 getters
15 }) 15 })
......
1 import { login, logout, getInfo } from '@/api/login' 1 import {
2 import { getToken, setToken, removeToken } from '@/utils/auth' 2 login,
3 logout,
4 getInfo
5 } from '@/api/login'
6 import {
7 getToken,
8 setToken,
9 removeToken
10 } from '@/utils/auth'
3 11
4 const user = { 12 const user = {
5 state: { 13 state: {
...@@ -26,22 +34,22 @@ const user = { ...@@ -26,22 +34,22 @@ const user = {
26 34
27 actions: { 35 actions: {
28 // 登录 36 // 登录
29 Login({ commit }, userInfo) { 37 Login({
38 commit
39 }, userInfo) {
30 const username = userInfo.username.trim() 40 const username = userInfo.username.trim()
31 return new Promise((resolve, reject) => { 41 return new Promise((resolve, reject) => {
32 login(username, userInfo.password).then(response => { 42 setToken('admin-token')
33 const data = response.content 43 commit('SET_TOKEN', 'admin-token')
34 setToken(data.token) 44 resolve()
35 commit('SET_TOKEN', data.token)
36 resolve()
37 }).catch(error => {
38 reject(error)
39 })
40 }) 45 })
41 }, 46 },
42 47
43 // 获取用户信息 48 // 获取用户信息
44 GetInfo({ commit, state }) { 49 GetInfo({
50 commit,
51 state
52 }) {
45 return new Promise((resolve, reject) => { 53 return new Promise((resolve, reject) => {
46 getInfo(state.token).then(response => { 54 getInfo(state.token).then(response => {
47 const data = response.content 55 const data = response.content
...@@ -60,7 +68,10 @@ const user = { ...@@ -60,7 +68,10 @@ const user = {
60 }, 68 },
61 69
62 // 登出 70 // 登出
63 LogOut({ commit, state }) { 71 LogOut({
72 commit,
73 state
74 }) {
64 return new Promise((resolve, reject) => { 75 return new Promise((resolve, reject) => {
65 logout(state.token).then(() => { 76 logout(state.token).then(() => {
66 commit('SET_TOKEN', '') 77 commit('SET_TOKEN', '')
...@@ -74,7 +85,9 @@ const user = { ...@@ -74,7 +85,9 @@ const user = {
74 }, 85 },
75 86
76 // 前端 登出 87 // 前端 登出
77 FedLogOut({ commit }) { 88 FedLogOut({
89 commit
90 }) {
78 return new Promise(resolve => { 91 return new Promise(resolve => {
79 commit('SET_TOKEN', '') 92 commit('SET_TOKEN', '')
80 removeToken() 93 removeToken()
......
...@@ -9,6 +9,11 @@ ...@@ -9,6 +9,11 @@
9 display: none; 9 display: none;
10 } 10 }
11 11
12 .dialog-footer{
13 display: flex;
14 justify-content: flex-end;
15 }
16
12 //暂时性解决diolag 问题 https://github.com/ElemeFE/element/issues/2461 17 //暂时性解决diolag 问题 https://github.com/ElemeFE/element/issues/2461
13 .el-dialog { 18 .el-dialog {
14 transform: none; 19 transform: none;
......
...@@ -76,3 +76,29 @@ a:hover { ...@@ -76,3 +76,29 @@ a:hover {
76 .app-container { 76 .app-container {
77 padding: 20px; 77 padding: 20px;
78 } 78 }
79
80 .tablePage {
81 padding: 30px;
82 }
83
84 .fixed-bottom {
85 background-color: #fefefe;
86 text-align: center;
87 padding: 15px !important;
88 text-align: right;
89 }
90
91
92 .editPage {
93 margin: 30px 20%;
94 padding: 30px;
95 box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.1);
96 }
97
98 .pointer {
99 cursor: pointer;
100 }
101
102 .el-date-editor .el-range-separator {
103 padding: 0;
104 }
......
1 import Cookies from 'js-cookie' 1 import Cookies from 'js-cookie'
2 2
3 const TokenKey = 'kd_admin_token' 3 const TokenKey = 'tianbao_admin_token'
4 4
5 export function getToken() { 5 export function getToken() {
6 return Cookies.get(TokenKey) 6 return Cookies.get(TokenKey)
......
...@@ -25,50 +25,25 @@ service.interceptors.request.use( ...@@ -25,50 +25,25 @@ service.interceptors.request.use(
25 ) 25 )
26 26
27 // response 拦截器 27 // response 拦截器
28 service.interceptors.response.use( 28 // service.interceptors.response.use(
29 response => { 29 // response => {
30 /** 30 // /**
31 * code为非20000是抛错 可结合自己业务进行修改 31 // * code为非20000是抛错 可结合自己业务进行修改
32 */ 32 // */
33 // 业务数据 33 // // 业务数据
34 const res = response.data 34 // const res = response.data
35 if (res.code !== 200) { 35 // console.log(response.data)
36 Message({ 36 // return response.data
37 message: res.message, 37 // },
38 type: 'error', 38 // error => {
39 duration: 5 * 1000 39 // console.log('err' + error) // for debug
40 }) 40 // Message({
41 41 // message: error.message,
42 // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了; 42 // type: 'error',
43 if (res.code === 50008 || res.code === 50012 || res.code === 50014) { 43 // duration: 5 * 1000
44 MessageBox.confirm( 44 // })
45 '你已被登出,可以取消继续留在该页面,或者重新登录', 45 // return Promise.reject(error)
46 '确定登出', 46 // }
47 { 47 // )
48 confirmButtonText: '重新登录',
49 cancelButtonText: '取消',
50 type: 'warning'
51 }
52 ).then(() => {
53 store.dispatch('FedLogOut').then(() => {
54 location.reload() // 为了重新实例化vue-router对象 避免bug
55 })
56 })
57 }
58 return Promise.reject('error')
59 } else {
60 return response.data
61 }
62 },
63 error => {
64 console.log('err' + error) // for debug
65 Message({
66 message: error.message,
67 type: 'error',
68 duration: 5 * 1000
69 })
70 return Promise.reject(error)
71 }
72 )
73 48
74 export default service 49 export default service
......
1 <template>
2 <div class="editPage">
3 <el-form
4 :model="editForm"
5 :loading="loading"
6 ref="editForm"
7 label-position="right"
8 label-width="auto"
9 style="padding-right: 30px"
10 v-loading="loading"
11 element-loading-text="操作中"
12 element-loading-spinner="el-icon-loading"
13 element-loading-background="rgba(255, 255, 255, 0.9)"
14 >
15 <el-form-item
16 label="所属分类"
17 prop="classifyCode"
18 :rules="{ required: true, message: '所属分类不能为空', trigger: 'change' }"
19 >
20 <el-select class="maxItem" v-model="editForm.classifyCode" placeholder="请选择所属分类">
21 <el-option
22 v-for="item in classifyList"
23 :key="item.classifyCode"
24 :label="item.classifyName"
25 :value="item.classifyCode"
26 ></el-option>
27 </el-select>
28 </el-form-item>
29
30 <el-form-item
31 label="标题"
32 prop="articleTitle"
33 :rules="{ required: true, message: '标题不能为空', trigger: 'blur' }"
34 >
35 <el-input v-model="editForm.articleTitle" placeholder="请输入标题"></el-input>
36 </el-form-item>
37
38 <el-form-item
39 label="内容"
40 prop="content"
41 :rules="{ required: true, message: '内容不能为空', trigger: 'blur' }"
42 >
43 <WangEditor v-model="editForm.content" :subPath="subPath" />
44 </el-form-item>
45
46 <el-form-item label="附件">
47 <el-upload
48 class="upload-demo"
49 :onSuccess="successFile"
50 :onRemove="removeFile"
51 :file-list="editForm.attachments"
52 drag
53 action="https://api.k.wxpai.cn/bizproxy/tianbaoServiceApi/common/upload"
54 multiple
55 :data="extraData"
56 accept="application/pdf"
57 >
58 <i class="el-icon-upload"></i>
59 <div class="el-upload__text">
60 将文件拖到此处,或
61 <em>点击上传</em>
62 </div>
63 <div class="el-upload__tip" slot="tip">*只能上传pdf文件</div>
64 </el-upload>
65 </el-form-item>
66
67 <el-form-item label="排序值">
68 <el-input-number v-model="editForm.orderId" :min="0"></el-input-number>
69 </el-form-item>
70 <el-form-item label="是否在线" prop="onlineStatus">
71 <el-switch
72 v-model="editForm.onlineStatus"
73 inactive-color="rgb(234,236,240)"
74 ></el-switch>
75 </el-form-item>
76 <el-form-item label="是否置顶" prop="inTop">
77 <el-switch
78 v-model="editForm.inTop"
79 inactive-color="rgb(234,236,240)"
80 ></el-switch>
81 </el-form-item>
82 </el-form>
83 <div slot="footer" class="dialog-footer" style="padding-right:30px">
84 <el-button @click="componentClose">取 消</el-button>
85 <el-button type="primary" @click="componentSubmit" :disabled="loading" :loading="loading">确定</el-button>
86 </div>
87 </div>
88 </template>
89
90
91 <script>
92 import UploadImg from "@/components/UploadImg/index.vue";
93 import WangEditor from "@/components/WangEditor/index.vue";
94
95 export default {
96 props: [],
97 components: {
98 UploadImg,
99 WangEditor
100 },
101 data() {
102 return {
103 loading: false,
104 subPath: "article",
105 editForm: {
106 articleCode: null,
107 classifyCode: null,
108 articleTitle: null,
109 articleThumb: 0,
110 author: null,
111 content: "",
112 createTime: 0,
113 orderId: 0,
114 onlineStatus: true,
115 inTop: false,
116 attachments: []
117 },
118 classifyList: [],
119 extraData: {
120 subPath: "articleFile"
121 }
122 };
123 },
124 mounted() {
125 this.initData();
126 },
127 methods: {
128 async initData() {
129 this.editForm.articleCode = this.$route.query.articleCode;
130 if (this.editForm.articleCode != null) {
131 this.getDetail();
132 }
133 this.getClassifyList();
134 },
135 getDetail() {
136 app
137 .get({
138 url: app.api.getArticleDetail,
139 data: {
140 articleCode: this.editForm.articleCode
141 }
142 })
143 .then(res => {
144 res.inTop = res.inTop == 1 ? true : false;
145 res.onlineStatus = res.onlineStatus == 1 ? true : false;
146
147 if (res.attachments) {
148 res.attachments = JSON.parse(res.attachments);
149 } else {
150 res.attachments = [];
151 }
152
153 this.editForm = res;
154 });
155 },
156 getClassifyList() {
157 app
158 .get({ url: app.api.getArticleClassify, data: null })
159 .then(res => {
160 this.classifyList = res.list;
161 })
162 .catch(e => {});
163 },
164
165 componentSubmit() {
166 this.$refs["editForm"].validate(valid => {
167 if (valid) {
168 if (this.loading) {
169 return;
170 }
171 this.loading = true;
172 let editForm = JSON.parse(JSON.stringify(this.editForm));
173 editForm.inTop = this.editForm.inTop ? 1 : 0;
174 editForm.onlineStatus = this.editForm.onlineStatus ? 1 : 0;
175 editForm.createTime = new Date(this.editForm.createTime).getTime();
176 if (this.editForm.attachments.length > 0) {
177 editForm.attachments = JSON.stringify(this.editForm.attachments);
178 } else {
179 editForm.attachments = "";
180 }
181
182 console.log("this.editForm", editForm);
183 app
184 .post({ url: app.api.setArticle, data: editForm })
185 .then(res => {
186 this.loading = false;
187 this.$notify({
188 title: "成功",
189 message: "操作成功",
190 type: "success"
191 });
192 this.$router.go(-1);
193 })
194 .catch(e => {
195 this.loading = false;
196 });
197 }
198 });
199 },
200 componentClose() {
201 this.$router.go(-1);
202 },
203
204 successFile(res, file) {
205 if (res.code == 200) {
206 this.editForm.attachments.push({
207 name: file.name,
208 path: res.content
209 });
210 } else {
211 this.$notify.error({
212 title: "错误",
213 message: res.errMsg
214 });
215 }
216 },
217
218 removeFile(file, fileList) {
219 this.editForm.attachments.forEach((item, index) => {
220 if (item.name == file.name) {
221 this.attachments.attachments.splice(index, 1);
222 }
223 });
224 }
225 }
226 };
227 </script>
228 <style lang="scss" scoped>
229 .tablePage {
230 margin: 0 auto;
231 }
232
233 .el-upload__tip {
234 color: rgb(190, 190, 190);
235 }
236 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <div class="tablePage">
3 <!-- 筛选参数 -->
4 <el-header>
5 <el-form :inline="true" style="display:flex">
6 <el-form-item style="flex-grow: 1">
7 <el-input @change="getList" v-model="queryForm.query" placeholder="请输入标题名称"></el-input>
8 </el-form-item>
9 <el-form-item>
10 <el-button @click="handleShowEdit(null)" type="primary" icon="el-icon-plus">新建</el-button>
11 </el-form-item>
12 </el-form>
13 </el-header>
14 <!-- 表格 -->
15 <el-container>
16 <el-table :data="list" :loading="loading">
17 <el-table-column type="index" min-width="50"></el-table-column>
18 <el-table-column
19 :show-overflow-tooltip="true"
20 label="标题"
21 prop="articleTitle"
22 min-width="200"
23 ></el-table-column>
24 <el-table-column label="排序值" prop="orderId" min-width="100"></el-table-column>
25 <el-table-column :show-overflow-tooltip="false" label="浏览次数" prop="viewNumber" width="130"></el-table-column>
26 <el-table-column label="状态">
27 <template slot-scope="scope">
28 <el-tag
29 v-if="scope.row.onlineStatus==1"
30 type="success"
31 class="pointer"
32 :class="{'not-allowed' : scope.row.sysList}"
33 @click="scope.row.sysList ? '' : handleChangeStatue(scope.row, 0)"
34 >在线</el-tag>
35 <el-tag
36 v-else
37 type="info"
38 class="pointer"
39 :class="{'not-allowed' : scope.row.sysList}"
40 @click="scope.row.sysList ? '' : handleChangeStatue(scope.row, 1)"
41 >下线</el-tag>
42 </template>
43 </el-table-column>
44 <el-table-column label="是否置顶" min-width="100">
45 <template slot-scope="scope">
46 <el-switch
47 @change="setList(scope.row)"
48 v-model="scope.row.inTop"
49 active-color="rgb(102,177,255)"
50 inactive-color="rgb(234,236,240)"
51 ></el-switch>
52 </template>
53 </el-table-column>
54 <el-table-column label="操作" min-width="100">
55 <template slot-scope="scope">
56 <el-button type="text" @click="handleShowEdit(scope.row.articleCode)">编辑</el-button>
57 <el-button type="text" @click="handleDelete(scope.row.articleCode)">删除</el-button>
58 </template>
59 </el-table-column>
60 </el-table>
61 </el-container>
62 <!-- 分页 -->
63 <el-footer class="fixed-bottom">
64 <el-pagination
65 background
66 layout="total, sizes, prev, pager, next, jumper"
67 :current-page="queryForm.page"
68 @size-change="handleSizeChange"
69 @current-change="handleCurrentChange"
70 :page-sizes="[10,20,30,50]"
71 :page-size="queryForm.size"
72 :total="total"
73 ></el-pagination>
74 </el-footer>
75 </div>
76 </template>
77
78 <script>
79 import { timestampFormat } from "@/utils/utils";
80
81 const getListApi = app.api.getArticleList;
82 const setListApi = app.api.setArticleList;
83
84 export default {
85 props: [],
86 components: {},
87 data() {
88 return {
89 queryForm: {
90 page: 1,
91 size: 10,
92 query: "",
93 onlineStatus: null,
94 messageType: null,
95 vipMark: null
96 }, //列表默认传参
97 list: [], //列表数据
98 total: 0, //列表总数
99 loading: true, //表格加载状态
100 keyword: "accountCode",
101
102 pojo: null,
103 showEdit: false,
104 showChangePwd: false
105 };
106 },
107 created() {
108 this.initData();
109 },
110 methods: {
111 timestampFormat,
112 // 初始化数据
113 async initData() {
114 this.getList();
115 },
116 // 获取列表
117 getList(resize) {
118 if (resize && resize != undefined) {
119 this.queryForm.page = 1;
120 }
121 this.loading = true;
122 app
123 .get({
124 url: getListApi,
125 data: this.queryForm
126 })
127 .then(res => {
128 this.loading = false;
129
130 res.list.forEach(item => {
131 item.onlineStatus = item.onlineStatus == 1 ? true : false;
132 item.inTop = item.inTop == 1 ? true : false;
133 });
134
135 this.list = res.list;
136 this.total = res.total;
137 })
138 .catch(err => {
139 this.loading = false;
140 });
141 },
142
143 // 更新内容
144 setList(item) {
145 let editForm = JSON.parse(JSON.stringify(item));
146 editForm.inTop = item.inTop ? 1 : 0;
147 editForm.onlineStatus = item.onlineStatus ? 1 : 0;
148
149 app
150 .post({
151 url: setListApi,
152 data: editForm
153 })
154 .then(res => {
155 this.$message({
156 message: "更新成功",
157 type: "success"
158 });
159 // this.getList();
160 })
161 .catch(err => {});
162 },
163
164 setOrderType(val) {
165 if (!val.order) {
166 this.queryForm.orderType = "";
167 this.getList(true);
168 return;
169 }
170 switch (val.prop) {
171 case "createAt":
172 if (val.order == "descending") {
173 this.queryForm.orderType = "id:desc";
174 } else {
175 this.queryForm.orderType = "id:asc";
176 }
177 this.getList(true);
178 break;
179 case "viewNumber":
180 if (val.order == "descending") {
181 this.queryForm.orderType = "viewNumber:desc";
182 } else {
183 this.queryForm.orderType = "viewNumber:asc";
184 }
185 this.getList(true);
186 break;
187
188 default:
189 break;
190 }
191 },
192
193 // 上下架
194 setOnlineStatus(item) {
195 item.onlineStatus = item.onlineStatus == 0 ? 1 : 0;
196 this.setList(item);
197 },
198
199 // 置顶
200 setOrderId(item) {
201 item.inTop = item.inTop == 1 ? 0 : 1;
202 this.setList(item);
203 },
204
205 // 切换页码大小
206 handleSizeChange(val) {
207 this.queryForm.size = val;
208 this.queryForm.page = 1;
209 this.initData();
210 },
211
212 // 切换页码
213 handleCurrentChange(val) {
214 this.queryForm.page = val;
215 this.initData();
216 },
217 handleShowEdit(articleCode) {
218 this.$router.push({
219 name: "articleDetail",
220 query: {
221 articleCode: articleCode
222 }
223 });
224 },
225 handleChangePwd(pojo) {
226 this.pojo = pojo;
227 this.showChangePwd = true;
228 },
229 handleDelete(articleCode) {
230 this.$confirm("删除后,不可恢复 是否继续?", "提示", {
231 confirmButtonText: "确定",
232 cancelButtonText: "取消",
233 type: "warning"
234 })
235 .then(() => {
236 this.loading = true;
237 app
238 .delete({
239 url: setListApi,
240 data: { articleCode }
241 })
242 .then(res => {
243 this.$message({
244 message: "更新成功",
245 type: "success"
246 });
247 this.getList();
248 })
249 .catch(err => {});
250 })
251 .catch(() => {
252 this.loading = true;
253 });
254 },
255 handleChangeStatue(row, status) {
256 let msg = status == 1 ? "是否上线当前文章?" : "是否下线当前文章?";
257 let data = JSON.parse(JSON.stringify(row));
258 data.onlineStatus = status;
259 data.inTop = data.inTop ? 1 : 0;
260 this.$confirm(msg, "提示", {
261 confirmButtonText: "确定",
262 cancelButtonText: "取消",
263 type: "warning"
264 })
265 .then(() => {
266 this.loading = true;
267 app.post({ url: setListApi, data }).then(res => {
268 this.getList();
269 this.$notify({
270 title: "成功",
271 message: "操作成功",
272 type: "success"
273 });
274 });
275 })
276 .catch(() => {
277 this.loading = true;
278 });
279 }
280 }
281 };
282 </script>
283
284 <style lang="scss" scoped>
285 /deep/ .el-dialog__wrapper {
286 overflow: hidden;
287 }
288 </style>
1 <template>
2 <div class="editPage">
3 <el-form
4 :model="editForm"
5 :loading="loading"
6 ref="editForm"
7 label-position="right"
8 label-width="auto"
9 style="padding-right:50px;"
10 v-loading="loading"
11 element-loading-text="操作中"
12 element-loading-spinner="el-icon-loading"
13 element-loading-background="rgba(255, 255, 255, 0.9)"
14 >
15 <el-form-item
16 label="名称"
17 prop="classifyName"
18 :rules="{ required: true, message: '名称不能为空', trigger: 'blur' }"
19 >
20 <el-input v-model="editForm.classifyName" placeholder="请输入名称"></el-input>
21 </el-form-item>
22
23 <el-form-item label="排序值">
24 <el-input-number v-model="editForm.orderId" :min="0"></el-input-number>
25 </el-form-item>
26
27 <el-form-item
28 label="是否在线"
29 prop="onlineStatus"
30 :rules="{ required: true, message: '请选择状态', trigger: 'blur' }"
31 >
32 <el-switch
33 v-model="editForm.onlineStatus"
34 inactive-color="rgb(234,236,240)"
35 ></el-switch>
36 </el-form-item>
37 </el-form>
38 <div slot="footer" class="dialog-footer" style="padding-right:30px">
39 <el-button @click="componentClose">取 消</el-button>
40 <el-button type="primary" @click="componentSubmit" :disabled="loading" :loading="loading">确定</el-button>
41 </div>
42 </div>
43 </template>
44
45
46 <script>
47 import UploadImg from "@/components/UploadImg/index.vue";
48
49 export default {
50 props: [],
51 components: { UploadImg },
52 data() {
53 return {
54 isLinkDialog: false,
55 searchLoading: false,
56 title: "轮播图",
57 submitUrl: "",
58 loading: false,
59 dialogVisiable: false,
60 editForm: {
61 classifyCode: "",
62 classifyIcon: "",
63 classifyHomePic: "",
64 classifyName: "",
65 onlineStatus: true,
66 onShow: false,
67 orderId: 0
68 },
69 // 连接值的候选项
70 valueCandidates: [],
71 getForm: {
72 query: null,
73 page: 0,
74 size: 10
75 },
76 candidatesEnd: false,
77 fetchUrl: "",
78 labelKey: "",
79 valueKey: ""
80 };
81 },
82 mounted() {
83 this.initData();
84 },
85 methods: {
86 async initData() {
87 this.submitUrl = app.api.setArticleClassify;
88 if (this.$route.query.pojo != "null") {
89 this.editForm = JSON.parse(this.$route.query.pojo);
90 this.editForm.onlineStatus = this.editForm.onlineStatus ? true : false;
91 this.editForm.onShow = this.editForm.onShow ? true : false;
92 }
93 this.dialogVisiable = true;
94 },
95 componentClose() {
96 this.$router.go(-1);
97 },
98 componentClosed() {
99 this.$emit("closed");
100 },
101 componentSubmit() {
102 this.$refs["editForm"].validate(valid => {
103 if (valid) {
104 if (this.loading) {
105 return;
106 }
107 this.loading = true;
108
109 let editForm = JSON.parse(JSON.stringify(this.editForm));
110 editForm.onlineStatus = this.editForm.onlineStatus ? 1 : 0;
111 editForm.onShow = this.editForm.onShow ? 1 : 0;
112
113 app
114 .post({
115 url: this.submitUrl,
116 data: editForm
117 })
118 .then(res => {
119 this.loading = false;
120 this.$notify({
121 title: "成功",
122 message: "操作成功",
123 type: "success"
124 });
125 this.$router.go(-1);
126 })
127 .catch(e => {
128 this.loading = false;
129 });
130 }
131 });
132 }
133 }
134 };
135 </script>
136
137 <style lang="scss" scoped>
138 .commoditySelect {
139 width: 100%;
140 max-width: auto;
141 }
142 .tablePage {
143 margin: 0 auto;
144 }
145 </style>
1 <template>
2 <div class="tablePage">
3 <!-- 筛选参数 -->
4 <el-header>
5 <el-form :inline="true" style="display:flex">
6 <el-form-item style="flex-grow: 1"></el-form-item>
7 <el-form-item>
8 <el-button @click="handleShowEdit(null)" type="primary" icon="el-icon-plus">新建</el-button>
9 </el-form-item>
10 </el-form>
11 </el-header>
12 <!-- 表格 -->
13
14 <el-container>
15 <el-table :data="list" :loading="loading">
16 <el-table-column label="名称" prop="classifyName"></el-table-column>
17 <!-- <el-table-column label="图标" min-width="100">
18 <template slot-scope="scope">
19 <el-image style="width: 50px; height: 50px" :src="scope.row.classifyIcon"></el-image>
20 </template>
21 </el-table-column>
22 <el-table-column label="主分类图标" min-width="100">
23 <template slot-scope="scope">
24 <el-image style="width: 50px; height: 50px" :src="scope.row.classifyHomePic"></el-image>
25 </template>
26 </el-table-column>-->
27
28 <el-table-column label="状态">
29 <template slot-scope="scope">
30 <el-tag
31 v-if="scope.row.onlineStatus==1"
32 type="success"
33 class="pointer"
34 :class="{'not-allowed' : scope.row.sysList}"
35 @click="scope.row.sysList ? '' : handleChangeStatue(scope.row, 0)"
36 >在线</el-tag>
37 <el-tag
38 v-else
39 type="info"
40 class="pointer"
41 :class="{'not-allowed' : scope.row.sysList}"
42 @click="scope.row.sysList ? '' : handleChangeStatue(scope.row, 1)"
43 >下线</el-tag>
44 </template>
45 </el-table-column>
46 <el-table-column label="排序" prop="orderId"></el-table-column>
47 <el-table-column label="操作">
48 <template slot-scope="scope">
49 <el-button type="text" @click="handleShowEdit(scope.row)">编辑</el-button>
50 <el-button
51 type="text"
52 @click="handleDelete(scope.row)"
53 :disabled="scope.row.sysList ? true : false"
54 >删除</el-button>
55 </template>
56 </el-table-column>
57 </el-table>
58 </el-container>
59 <!-- 分页 -->
60 <el-footer class="fixed-bottom">
61 <el-pagination
62 background
63 layout="total, sizes, prev, pager, next, jumper"
64 :current-page="queryForm.page"
65 @size-change="handleSizeChange"
66 @current-change="handleCurrentChange"
67 :page-sizes="[10,20,30,50]"
68 :page-size="queryForm.size"
69 :total="total"
70 ></el-pagination>
71 </el-footer>
72 </div>
73 </template>
74
75 <script>
76 // 列表路径
77 const listUrl = app.api.getArticleClassify;
78 // 提交路径
79 const postUrl = app.api.setArticleClassify;
80 // 唯一标识
81 const primaryCodeName = "classifyCode";
82
83 export default {
84 components: {},
85 data() {
86 return {
87 postUrl,
88 queryForm: {
89 page: 1,
90 size: 10
91 }, //列表默认传参
92 list: [], //列表数据
93 total: 0, //列表总数
94 loading: true, //表格加载状态
95
96 classifyCode: "",
97 relationsArticleCodes: [],
98
99 isShowRelations: false,
100 articlesList: [],
101
102 transferProps: {
103 key: "memberCode",
104 label: "name"
105 }
106 };
107 },
108 created() {
109 this.initData();
110 },
111 methods: {
112 // 初始化数据
113 initData(resize) {
114 if (resize && resize != undefined) {
115 this.queryForm.page = 1;
116 }
117
118 this.getList();
119 },
120
121 // 获取列表
122 getList() {
123 this.loading = true;
124 app
125 .get({
126 url: listUrl,
127 data: this.queryForm
128 })
129 .then(res => {
130 this.loading = false;
131 this.list = res.list;
132 this.total = res.total;
133 })
134 .catch(err => {
135 this.loading = false;
136 });
137 },
138
139 // 切换页码大小
140 handleSizeChange(val) {
141 this.queryForm.size = val;
142 this.queryForm.page = 1;
143 this.initData();
144 },
145
146 // 切换页码
147 handleCurrentChange(val) {
148 this.queryForm.page = val;
149 this.initData();
150 },
151
152 handleShowEdit(pojo) {
153 this.$router.push({
154 name: "articeClassifyDetail",
155 query: {
156 pojo: JSON.stringify(pojo)
157 }
158 });
159 },
160
161 handleShowRelation(classifyCode) {
162 this.relationsArticleCodes = [];
163 this.classifyCode = classifyCode;
164 this.getArticleRelativeArticles(classifyCode);
165 },
166
167 handleDelete(pojo) {
168 this.$confirm("删除后,不可恢复 是否继续?", "提示", {
169 confirmButtonText: "确定",
170 cancelButtonText: "取消",
171 type: "warning"
172 })
173 .then(() => {
174 let data = {};
175 data[primaryCodeName] = pojo[primaryCodeName];
176 this.loading = true;
177 app
178 .delete({
179 url: postUrl,
180 data
181 })
182 .then(res => {
183 this.getList();
184 this.$notify({
185 title: "成功",
186 message: "删除成功",
187 type: "success"
188 });
189 });
190 })
191 .catch(() => {
192 this.loading = true;
193 });
194 },
195 handleChangeStatue(row, status) {
196 let msg = status == 1 ? "是否上线当前分类?" : "是否下线当前分类?";
197 let data = JSON.parse(JSON.stringify(row));
198 data.onlineStatus = status;
199 this.$confirm(msg, "提示", {
200 confirmButtonText: "确定",
201 cancelButtonText: "取消",
202 type: "warning"
203 })
204 .then(() => {
205 this.loading = true;
206 app.post({ url: postUrl, data }).then(res => {
207 this.getList();
208 this.$notify({
209 title: "成功",
210 message: "操作成功",
211 type: "success"
212 });
213 });
214 })
215 .catch(() => {
216 this.loading = true;
217 });
218 },
219 handleChangeShow(row, status) {
220 let msg = status == 1 ? "是否显示当前分类?" : "是否隐藏当前分类?";
221 let data = JSON.parse(JSON.stringify(row));
222 data.onShow = status;
223 this.$confirm(msg, "提示", {
224 confirmButtonText: "确定",
225 cancelButtonText: "取消",
226 type: "warning"
227 })
228 .then(() => {
229 this.loading = true;
230 app.post({ url: postUrl, data }).then(res => {
231 this.getList();
232 this.$notify({
233 title: "成功",
234 message: "操作成功",
235 type: "success"
236 });
237 });
238 })
239 .catch(() => {
240 this.loading = true;
241 });
242 }
243 }
244 };
245 </script>
246
247 <style scoped>
248 .transfer {
249 margin: 0 auto;
250 }
251 .not-allowed {
252 cursor: not-allowed;
253 }
254 </style>
1 <template>
2 <div class="editPage">
3 <el-form
4 :model="editForm"
5 :loading="loading"
6 ref="editForm"
7 label-position="right"
8 label-width="auto"
9 style="padding-right:50px;"
10 v-loading="loading"
11 element-loading-text="操作中"
12 element-loading-spinner="el-icon-loading"
13 element-loading-background="rgba(255, 255, 255, 0.9)"
14 >
15 <el-form-item
16 label="关键词"
17 prop="keyword"
18 :rules="{ required: true, message: '关键词不能为空', trigger: 'blur' }"
19 >
20 <el-input v-model="editForm.keyword" placeholder="请输入关键词"></el-input>
21 </el-form-item>
22
23 <el-form-item label="排序值">
24 <el-input-number v-model="editForm.orderId" :min="0"></el-input-number>
25 </el-form-item>
26
27 <el-form-item
28 label="是否在线"
29 prop="onlineStatus"
30 :rules="{ required: true, message: '请选择状态', trigger: 'blur' }"
31 >
32 <el-switch
33 v-model="editForm.onlineStatus"
34 inactive-color="rgb(234,236,240)"
35 ></el-switch>
36 </el-form-item>
37 </el-form>
38 <div slot="footer" class="dialog-footer" style="padding-right:30px">
39 <el-button @click="componentClose">取 消</el-button>
40 <el-button type="primary" @click="componentSubmit" :disabled="loading" :loading="loading">确定</el-button>
41 </div>
42 </div>
43 </template>
44
45
46 <script>
47 import UploadImg from "@/components/UploadImg/index.vue";
48
49 export default {
50 props: [],
51 components: { UploadImg },
52 data() {
53 return {
54 isLinkDialog: false,
55 searchLoading: false,
56 title: "轮播图",
57 submitUrl: "",
58 loading: false,
59 dialogVisiable: false,
60 editForm: {
61 primaryCode: "",
62 keyword: "",
63 onlineStatus: true,
64 orderId: 0
65 },
66 // 连接值的候选项
67 valueCandidates: [],
68 getForm: {
69 query: null,
70 page: 0,
71 size: 10
72 },
73 candidatesEnd: false,
74 fetchUrl: "",
75 labelKey: "",
76 valueKey: ""
77 };
78 },
79 mounted() {
80 this.initData();
81 },
82 methods: {
83 async initData() {
84 this.submitUrl = app.api.setArticleKeywordList;
85 if (this.$route.query.pojo != "null") {
86 this.editForm = JSON.parse(this.$route.query.pojo);
87 this.editForm.onlineStatus = this.editForm.onlineStatus ? true : false;
88 this.editForm.onShow = this.editForm.onShow ? true : false;
89 }
90 this.dialogVisiable = true;
91 },
92 componentClose() {
93 this.$router.go(-1);
94 },
95 componentClosed() {
96 this.$emit("closed");
97 },
98 componentSubmit() {
99 this.$refs["editForm"].validate(valid => {
100 if (valid) {
101 if (this.loading) {
102 return;
103 }
104 this.loading = true;
105
106 let editForm = JSON.parse(JSON.stringify(this.editForm));
107 editForm.onlineStatus = this.editForm.onlineStatus ? 1 : 0;
108 editForm.onShow = this.editForm.onShow ? 1 : 0;
109
110 app
111 .post({
112 url: this.submitUrl,
113 data: editForm
114 })
115 .then(res => {
116 this.loading = false;
117 this.$notify({
118 title: "成功",
119 message: "操作成功",
120 type: "success"
121 });
122 this.$router.go(-1);
123 })
124 .catch(e => {
125 this.loading = false;
126 });
127 }
128 });
129 }
130 }
131 };
132 </script>
133
134 <style lang="scss" scoped>
135 .commoditySelect {
136 width: 100%;
137 max-width: auto;
138 }
139 .tablePage {
140 margin: 0 auto;
141 }
142 </style>
1 <template>
2 <div class="tablePage">
3 <!-- 筛选参数 -->
4 <el-header>
5 <el-form :inline="true" style="display:flex">
6 <el-form-item style="flex-grow: 1"></el-form-item>
7 <el-form-item>
8 <el-button @click="handleShowEdit(null)" type="primary" icon="el-icon-plus">新建</el-button>
9 </el-form-item>
10 </el-form>
11 </el-header>
12 <!-- 表格 -->
13
14 <el-container>
15 <el-table :data="list" :loading="loading">
16 <el-table-column label="关键词" prop="keyword"></el-table-column>
17
18 <el-table-column label="状态">
19 <template slot-scope="scope">
20 <el-tag
21 v-if="scope.row.onlineStatus==1"
22 type="success"
23 class="pointer"
24 :class="{'not-allowed' : scope.row.sysList}"
25 @click="scope.row.sysList ? '' : handleChangeStatue(scope.row, 0)"
26 >在线</el-tag>
27 <el-tag
28 v-else
29 type="info"
30 class="pointer"
31 :class="{'not-allowed' : scope.row.sysList}"
32 @click="scope.row.sysList ? '' : handleChangeStatue(scope.row, 1)"
33 >下线</el-tag>
34 </template>
35 </el-table-column>
36 <el-table-column label="排序" prop="orderId"></el-table-column>
37 <el-table-column label="操作">
38 <template slot-scope="scope">
39 <el-button type="text" @click="handleShowEdit(scope.row)">编辑</el-button>
40 <el-button
41 type="text"
42 @click="handleDelete(scope.row)"
43 :disabled="scope.row.sysList ? true : false"
44 >删除</el-button>
45 </template>
46 </el-table-column>
47 </el-table>
48 </el-container>
49 <!-- 分页 -->
50 <el-footer class="fixed-bottom">
51 <el-pagination
52 background
53 layout="total, sizes, prev, pager, next, jumper"
54 :current-page="queryForm.page"
55 @size-change="handleSizeChange"
56 @current-change="handleCurrentChange"
57 :page-sizes="[10,20,30,50]"
58 :page-size="queryForm.size"
59 :total="total"
60 ></el-pagination>
61 </el-footer>
62 </div>
63 </template>
64
65 <script>
66 // 列表路径
67 const listUrl = app.api.getArticleKeywordList;
68 // 提交路径
69 const postUrl = app.api.setArticleKeywordList;
70 // 唯一标识
71 const primaryCodeName = "primaryCode";
72
73 export default {
74 components: {},
75 data() {
76 return {
77 postUrl,
78 queryForm: {
79 page: 1,
80 size: 10
81 }, //列表默认传参
82 list: [], //列表数据
83 total: 0, //列表总数
84 loading: true, //表格加载状态
85
86 classifyCode: "",
87 relationsArticleCodes: [],
88
89 isShowRelations: false,
90 articlesList: [],
91
92 transferProps: {
93 key: "memberCode",
94 label: "name"
95 }
96 };
97 },
98 created() {
99 this.initData();
100 },
101 methods: {
102 // 初始化数据
103 initData(resize) {
104 if (resize && resize != undefined) {
105 this.queryForm.page = 1;
106 }
107
108 this.getList();
109 },
110
111 // 获取列表
112 getList() {
113 this.loading = true;
114 app
115 .get({
116 url: listUrl,
117 data: this.queryForm
118 })
119 .then(res => {
120 this.loading = false;
121 this.list = res.list;
122 this.total = res.total;
123 })
124 .catch(err => {
125 this.loading = false;
126 });
127 },
128
129 // 切换页码大小
130 handleSizeChange(val) {
131 this.queryForm.size = val;
132 this.queryForm.page = 1;
133 this.initData();
134 },
135
136 // 切换页码
137 handleCurrentChange(val) {
138 this.queryForm.page = val;
139 this.initData();
140 },
141
142 handleShowEdit(pojo) {
143 this.$router.push({
144 name: "keywordDetail",
145 query: {
146 pojo: JSON.stringify(pojo)
147 }
148 });
149 },
150
151 handleShowRelation(classifyCode) {
152 this.relationsArticleCodes = [];
153 this.classifyCode = classifyCode;
154 this.getArticleRelativeArticles(classifyCode);
155 },
156
157 handleDelete(pojo) {
158 this.$confirm("删除后,不可恢复 是否继续?", "提示", {
159 confirmButtonText: "确定",
160 cancelButtonText: "取消",
161 type: "warning"
162 })
163 .then(() => {
164 let data = {};
165 data[primaryCodeName] = pojo[primaryCodeName];
166 this.loading = true;
167 app
168 .delete({
169 url: postUrl,
170 data
171 })
172 .then(res => {
173 this.getList();
174 this.$notify({
175 title: "成功",
176 message: "删除成功",
177 type: "success"
178 });
179 });
180 })
181 .catch(() => {
182 this.loading = true;
183 });
184 },
185 handleChangeStatue(row, status) {
186 let msg = status == 1 ? "是否上线当前分类?" : "是否下线当前分类?";
187 let data = JSON.parse(JSON.stringify(row));
188 data.onlineStatus = status;
189 this.$confirm(msg, "提示", {
190 confirmButtonText: "确定",
191 cancelButtonText: "取消",
192 type: "warning"
193 })
194 .then(() => {
195 this.loading = true;
196 app.post({ url: postUrl, data }).then(res => {
197 this.getList();
198 this.$notify({
199 title: "成功",
200 message: "操作成功",
201 type: "success"
202 });
203 });
204 })
205 .catch(() => {
206 this.loading = true;
207 });
208 },
209 handleChangeShow(row, status) {
210 let msg = status == 1 ? "是否显示当前分类?" : "是否隐藏当前分类?";
211 let data = JSON.parse(JSON.stringify(row));
212 data.onShow = status;
213 this.$confirm(msg, "提示", {
214 confirmButtonText: "确定",
215 cancelButtonText: "取消",
216 type: "warning"
217 })
218 .then(() => {
219 this.loading = true;
220 app.post({ url: postUrl, data }).then(res => {
221 this.getList();
222 this.$notify({
223 title: "成功",
224 message: "操作成功",
225 type: "success"
226 });
227 });
228 })
229 .catch(() => {
230 this.loading = true;
231 });
232 }
233 }
234 };
235 </script>
236
237 <style scoped>
238 .transfer {
239 margin: 0 auto;
240 }
241 .not-allowed {
242 cursor: not-allowed;
243 }
244 </style>
1 <template>
2 <div class="tablePage">
3 <!-- 筛选参数 -->
4 <el-header>
5 <el-form :inline="true" style="display:flex">
6 <el-form-item style="flex-grow: 1">
7 <el-date-picker
8 v-model="date"
9 @change="setData"
10 type="daterange"
11 align="right"
12 unlink-panels
13 range-separator="至"
14 start-placeholder="开始日期"
15 end-placeholder="结束日期"
16 :picker-options="pickerOptions"
17 ></el-date-picker>
18 </el-form-item>
19
20 <el-form-item>
21 <el-button @click="exportList()" type="primary">
22 <i class="el-icon-download"></i>导出明细
23 </el-button>
24 </el-form-item>
25 </el-form>
26 </el-header>
27
28 <div class="dataBoxList">
29 <div class="dataBox">
30 <h5 class="tit">整体报告</h5>
31 <div class="dataList">
32 <div class="item">
33 <label>浏览次数</label>
34 <h5>{{dashboardInfo.viewNumber}}</h5>
35 </div>
36 <div class="item">
37 <label>浏览人数</label>
38 <h5>{{dashboardInfo.viewPerson}}</h5>
39 </div>
40 <div class="item">
41 <label>分享次数</label>
42 <h5>{{dashboardInfo.shareNumber}}</h5>
43 </div>
44 </div>
45 </div>
46
47 <!-- 表格 -->
48 <el-container>
49 <el-table :data="list" :loading="loading">
50 <el-table-column
51 label="标题"
52 prop="articleTitle"
53 min-width="300"
54 :show-overflow-tooltip="true"
55 ></el-table-column>
56 <el-table-column label="分类" prop="classifyName"></el-table-column>
57 <el-table-column label="标签" prop="tagName"></el-table-column>
58 <el-table-column label="浏览次数" prop="viewNumber"></el-table-column>
59 <el-table-column label="浏览人数" prop="viewPerson"></el-table-column>
60 <el-table-column label="分享次数" prop="shareNumber"></el-table-column>
61 </el-table>
62 </el-container>
63 <!-- 分页 -->
64 <!-- <el-footer class="fixed-bottom">
65 <el-pagination
66 background
67 layout="total, sizes, prev, pager, next, jumper"
68 :current-page="dashboardForm.page"
69 @size-change="handleSizeChange"
70 @current-change="handleCurrentChange"
71 :page-sizes="[10,20,30,50]"
72 :page-size="dashboardForm.size"
73 :total="total"
74 ></el-pagination>
75 </el-footer>-->
76 </div>
77 </div>
78 </template>
79
80 <script>
81 import { mapGetters } from "vuex";
82 import { timestampFormat } from "@/utils/utils";
83 import { buildExcelHeader } from "@/api/fetch-api-new.js";
84 export default {
85 name: "Dashboard",
86 data() {
87 return {
88 date: [],
89 pickerOptions: {
90 shortcuts: [
91 {
92 text: "最近一周",
93 onClick(picker) {
94 const end = new Date();
95 const start = new Date();
96 start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
97 picker.$emit("pick", [start, end]);
98 }
99 },
100 {
101 text: "最近一个月",
102 onClick(picker) {
103 const end = new Date();
104 const start = new Date();
105 start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
106 picker.$emit("pick", [start, end]);
107 }
108 },
109 {
110 text: "最近三个月",
111 onClick(picker) {
112 const end = new Date();
113 const start = new Date();
114 start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
115 picker.$emit("pick", [start, end]);
116 }
117 }
118 ]
119 },
120
121 dashboardForm: {
122 dateRange: "",
123 page: 1,
124 size: 9999
125 },
126
127 dashboardInfo: { viewNumber: 0, shareNumber: 0, viewPerson: 0 },
128
129 list: [], //列表数据
130 total: 0, //列表总数
131 loading: true //表格加载状态
132 };
133 },
134 computed: {
135 startDate() {
136 let date = this.date;
137 let result = (date && date[0]) || "";
138 if (result) {
139 result = date[0].getTime();
140 }
141 return result;
142 },
143
144 endDate() {
145 let date = this.date;
146 let result = (date && date[1]) || "";
147 if (result) {
148 result = date[1].getTime();
149 }
150 return result;
151 }
152 },
153 methods: {
154 initData() {
155 const end = new Date();
156 const start = new Date();
157 start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
158 this.date = [start, end];
159
160 this.setData();
161 },
162
163 getMemberDashboard(resize) {
164 app
165 .get({
166 url: app.api.getArticleDashboard,
167 data: this.dashboardForm
168 })
169 .then(res => {
170 this.dashboardInfo = res;
171 })
172 .catch(err => {});
173 },
174
175 getList(resize) {
176 if (resize && resize != undefined) {
177 this.dashboardForm.page = 1;
178 }
179 this.loading = true;
180 app
181 .get({
182 url: app.api.getArticleViewRank,
183 data: this.dashboardForm
184 })
185 .then(res => {
186 this.loading = false;
187 this.list = res;
188 })
189 .catch(err => {
190 this.loading = false;
191 });
192 },
193
194 setData() {
195 this.dashboardForm.dateRange =
196 timestampFormat(this.startDate, "yyyy-MM-dd") +
197 "," +
198 timestampFormat(this.endDate, "yyyy-MM-dd");
199 this.getMemberDashboard();
200 this.getList();
201 },
202
203 // 切换页码大小
204 handleSizeChange(val) {
205 this.queryForm.size = val;
206 this.queryForm.page = 1;
207 this.initData();
208 },
209
210 // 切换页码
211 handleCurrentChange(val) {
212 this.queryForm.page = val;
213 this.initData();
214 },
215
216 //导出,下载表格
217 exportList() {
218 let fileName =
219 "资料库明细" + timestampFormat(new Date().getTime()) + ".xlsx";
220
221 buildExcelHeader({
222 url: app.api.exportArticleViewRank,
223 data: this.dashboardForm,
224 filename: fileName
225 });
226 }
227 },
228 mounted() {},
229 created() {
230 this.initData();
231 }
232 };
233 </script>
234
235 <style lang="scss" scoped>
236 .stat-container {
237 color: #1a1b1c;
238 font-weight: 400;
239 position: relative;
240 max-width: 1100px;
241 margin: 0 auto;
242 padding: 30px;
243 margin-top: 5px;
244 background-color: white;
245 .userInfo {
246 display: flex;
247 align-items: center;
248 span {
249 font-size: 40px;
250 margin-left: 30px;
251 }
252 }
253 .btn {
254 margin-top: 30px;
255 }
256 .formBox {
257 width: 500px;
258 background-color: white;
259 padding: 20px;
260 border-radius: 10px;
261 margin-top: 30px;
262 .footerBtn {
263 text-align: right;
264 }
265 }
266 }
267
268 h5 {
269 margin: 0;
270 }
271 .dataBoxList {
272 display: flex;
273 flex-wrap: wrap;
274 justify-content: space-between;
275 }
276 .dataBox {
277 width: 100%;
278 min-height: 240px;
279 background-color: rgb(242, 242, 242);
280 overflow: hidden;
281 margin-bottom: 30px;
282 .tit {
283 font-size: 22px;
284 margin: 30px;
285 }
286
287 .dataList {
288 display: flex;
289 justify-content: center;
290 margin-top: 60px;
291 .item {
292 width: 250px;
293 text-align: center;
294 label {
295 font-size: 16px;
296 }
297 h5 {
298 font-size: 40px;
299 margin: 20px 0;
300 }
301 }
302 }
303
304 .chartList {
305 width: 98%;
306 display: flex;
307 margin: 30px 0;
308 margin-left: 1%;
309 .chare {
310 width: 100%;
311 height: 400px;
312 }
313 }
314 }
315
316 .fixed-bottom {
317 width: 100%;
318 text-align: right;
319 }
320
321 .el-header {
322 padding: 0;
323 }
324 </style>
1 <template>
2 <div class="tablePage">
3 <!-- 筛选参数 -->
4 <el-header>
5 <el-form :inline="true" style="display:flex">
6 <el-form-item style="flex-grow: 1">
7 <el-date-picker
8 v-model="date"
9 @change="setData"
10 type="daterange"
11 align="right"
12 unlink-panels
13 range-separator="至"
14 start-placeholder="开始日期"
15 end-placeholder="结束日期"
16 :picker-options="pickerOptions"
17 ></el-date-picker>
18 </el-form-item>
19
20 <el-form-item>
21 <el-button @click="exportList()" type="primary">
22 <i class="el-icon-download"></i>导出明细
23 </el-button>
24 </el-form-item>
25 </el-form>
26 </el-header>
27
28 <!-- 表格 -->
29 <el-container>
30 <el-table :data="list" :loading="loading">
31 <el-table-column label="分类名称" prop="classifyName"></el-table-column>
32 <el-table-column label="浏览次数" prop="viewNumber"></el-table-column>
33 <el-table-column label="浏览人数" prop="viewPerson"></el-table-column>
34 </el-table>
35 </el-container>
36 <!-- 分页 -->
37 <!-- <el-footer class="fixed-bottom">
38 <el-pagination
39 background
40 layout="total, sizes, prev, pager, next, jumper"
41 :current-page="dashboardForm.page"
42 @size-change="handleSizeChange"
43 @current-change="handleCurrentChange"
44 :page-sizes="[10,20,30,50]"
45 :page-size="dashboardForm.size"
46 :total="total"
47 ></el-pagination>
48 </el-footer>-->
49 </div>
50 </template>
51
52 <script>
53 import { mapGetters } from "vuex";
54 import { timestampFormat } from "@/utils/utils";
55 import { buildExcelHeader } from "@/api/fetch-api-new.js";
56 export default {
57 name: "Dashboard",
58 data() {
59 return {
60 date: [],
61 pickerOptions: {
62 shortcuts: [
63 {
64 text: "最近一周",
65 onClick(picker) {
66 const end = new Date();
67 const start = new Date();
68 start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
69 picker.$emit("pick", [start, end]);
70 }
71 },
72 {
73 text: "最近一个月",
74 onClick(picker) {
75 const end = new Date();
76 const start = new Date();
77 start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
78 picker.$emit("pick", [start, end]);
79 }
80 },
81 {
82 text: "最近三个月",
83 onClick(picker) {
84 const end = new Date();
85 const start = new Date();
86 start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
87 picker.$emit("pick", [start, end]);
88 }
89 }
90 ]
91 },
92
93 dashboardForm: {
94 dateRange: "",
95 page: 1,
96 size: 9999
97 },
98
99 dashboardInfo: {},
100
101 list: [], //列表数据
102 total: 0, //列表总数
103 loading: true //表格加载状态
104 };
105 },
106 computed: {
107 startDate() {
108 let date = this.date;
109 let result = (date && date[0]) || "";
110 if (result) {
111 result = date[0].getTime();
112 }
113 return result;
114 },
115
116 endDate() {
117 let date = this.date;
118 let result = (date && date[1]) || "";
119 if (result) {
120 result = date[1].getTime();
121 }
122 return result;
123 }
124 },
125 methods: {
126 initData() {
127 const end = new Date();
128 const start = new Date();
129 start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
130 this.date = [start, end];
131
132 this.setData();
133 },
134
135 getList(resize) {
136 if (resize && resize != undefined) {
137 this.dashboardForm.page = 1;
138 }
139 this.loading = true;
140 app
141 .get({
142 url: app.api.getArticleClassifyRank,
143 data: this.dashboardForm
144 })
145 .then(res => {
146 this.loading = false;
147 this.list = res;
148 })
149 .catch(err => {
150 this.loading = false;
151 });
152 },
153
154 setData() {
155 this.dashboardForm.dateRange =
156 timestampFormat(this.startDate, "yyyy-MM-dd") +
157 "," +
158 timestampFormat(this.endDate, "yyyy-MM-dd");
159 this.getList();
160 },
161
162 // 切换页码大小
163 handleSizeChange(val) {
164 this.queryForm.size = val;
165 this.queryForm.page = 1;
166 this.initData();
167 },
168
169 // 切换页码
170 handleCurrentChange(val) {
171 this.queryForm.page = val;
172 this.initData();
173 },
174
175 //导出,下载表格
176 exportList() {
177 let fileName =
178 "分类明细" + timestampFormat(new Date().getTime()) + ".xlsx";
179
180 buildExcelHeader({
181 url: app.api.exportArticleClassifyRank,
182 data: this.dashboardForm,
183 filename: fileName
184 });
185 }
186 },
187 mounted() {},
188 created() {
189 this.initData();
190 }
191 };
192 </script>
193
194 <style lang="scss" scoped>
195 .stat-container {
196 color: #1a1b1c;
197 font-weight: 400;
198 position: relative;
199 max-width: 1100px;
200 margin: 0 auto;
201 padding: 30px;
202 margin-top: 5px;
203 background-color: white;
204 .userInfo {
205 display: flex;
206 align-items: center;
207 span {
208 font-size: 40px;
209 margin-left: 30px;
210 }
211 }
212 .btn {
213 margin-top: 30px;
214 }
215 .formBox {
216 width: 500px;
217 background-color: white;
218 padding: 20px;
219 border-radius: 10px;
220 margin-top: 30px;
221 .footerBtn {
222 text-align: right;
223 }
224 }
225 }
226
227 h5 {
228 margin: 0;
229 }
230 .dataBoxList {
231 display: flex;
232 flex-wrap: wrap;
233 justify-content: space-between;
234 }
235 .dataBox {
236 width: 100%;
237 min-height: 240px;
238 background-color: rgb(242, 242, 242);
239 overflow: hidden;
240 margin-bottom: 30px;
241 .tit {
242 font-size: 22px;
243 margin: 30px;
244 }
245
246 .dataList {
247 display: flex;
248 justify-content: center;
249 margin-top: 60px;
250 .item {
251 width: 250px;
252 text-align: center;
253 label {
254 font-size: 16px;
255 }
256 h5 {
257 font-size: 40px;
258 margin: 20px 0;
259 }
260 }
261 }
262
263 .chartList {
264 width: 98%;
265 display: flex;
266 margin: 30px 0;
267 margin-left: 1%;
268 .chare {
269 width: 100%;
270 height: 400px;
271 }
272 }
273 }
274
275 .fixed-bottom {
276 width: 100%;
277 text-align: right;
278 }
279
280 .el-header {
281 padding: 0;
282 }
283 </style>
1 <template>
2 <div class="tablePage">
3 <!-- 筛选参数 -->
4 <el-header>
5 <el-form :inline="true" style="display:flex">
6 <el-form-item style="flex-grow: 1">
7 <el-date-picker
8 v-model="date"
9 @change="setData"
10 type="daterange"
11 align="right"
12 unlink-panels
13 range-separator="至"
14 start-placeholder="开始日期"
15 end-placeholder="结束日期"
16 :picker-options="pickerOptions"
17 ></el-date-picker>
18 </el-form-item>
19
20 <!-- <el-form-item>
21 <el-button @click="exportList()" type="primary">
22 <i class="el-icon-download"></i>导出明细
23 </el-button>
24 </el-form-item> -->
25 </el-form>
26 </el-header>
27
28 <!-- 表格 -->
29 <el-container>
30 <el-table :data="list" :loading="loading">
31 <el-table-column label="关键词" prop="word"></el-table-column>
32 <el-table-column label="搜索次数" prop="times"></el-table-column>
33 <el-table-column label="搜索匹配文章数" prop="match"></el-table-column>
34 </el-table>
35 </el-container>
36 <!-- 分页 -->
37 <!-- <el-footer class="fixed-bottom">
38 <el-pagination
39 background
40 layout="total, sizes, prev, pager, next, jumper"
41 :current-page="dashboardForm.page"
42 @size-change="handleSizeChange"
43 @current-change="handleCurrentChange"
44 :page-sizes="[10,20,30,50]"
45 :page-size="dashboardForm.size"
46 :total="total"
47 ></el-pagination>
48 </el-footer>-->
49 </div>
50 </template>
51
52 <script>
53 import { mapGetters } from "vuex";
54 import { timestampFormat } from "@/utils/utils";
55 import { buildExcelHeader } from "@/api/fetch-api-new.js";
56 export default {
57 name: "Dashboard",
58 data() {
59 return {
60 date: [],
61 pickerOptions: {
62 shortcuts: [
63 {
64 text: "最近一周",
65 onClick(picker) {
66 const end = new Date();
67 const start = new Date();
68 start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
69 picker.$emit("pick", [start, end]);
70 }
71 },
72 {
73 text: "最近一个月",
74 onClick(picker) {
75 const end = new Date();
76 const start = new Date();
77 start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
78 picker.$emit("pick", [start, end]);
79 }
80 },
81 {
82 text: "最近三个月",
83 onClick(picker) {
84 const end = new Date();
85 const start = new Date();
86 start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
87 picker.$emit("pick", [start, end]);
88 }
89 }
90 ]
91 },
92
93 dashboardForm: {
94 dateRange: "",
95 page: 1,
96 size: 9999
97 },
98
99 dashboardInfo: {},
100
101 list: [], //列表数据
102 total: 0, //列表总数
103 loading: true //表格加载状态
104 };
105 },
106 computed: {
107 startDate() {
108 let date = this.date;
109 let result = (date && date[0]) || "";
110 if (result) {
111 result = date[0].getTime();
112 }
113 return result;
114 },
115
116 endDate() {
117 let date = this.date;
118 let result = (date && date[1]) || "";
119 if (result) {
120 result = date[1].getTime();
121 }
122 return result;
123 }
124 },
125 methods: {
126 initData() {
127 const end = new Date();
128 const start = new Date();
129 start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
130 this.date = [start, end];
131
132 this.setData();
133 },
134
135 getList(resize) {
136 if (resize && resize != undefined) {
137 this.dashboardForm.page = 1;
138 }
139 this.loading = true;
140 app
141 .get({
142 url: app.api.getArticleKeywordStat,
143 data: this.dashboardForm
144 })
145 .then(res => {
146 this.loading = false;
147 this.list = res;
148 })
149 .catch(err => {
150 this.loading = false;
151 });
152 },
153
154 setData() {
155 this.dashboardForm.dateRange =
156 timestampFormat(this.startDate, "yyyy-MM-dd") +
157 "," +
158 timestampFormat(this.endDate, "yyyy-MM-dd");
159 this.getList();
160 },
161
162 // 切换页码大小
163 handleSizeChange(val) {
164 this.queryForm.size = val;
165 this.queryForm.page = 1;
166 this.initData();
167 },
168
169 // 切换页码
170 handleCurrentChange(val) {
171 this.queryForm.page = val;
172 this.initData();
173 },
174
175 //导出,下载表格
176 exportList() {
177 let fileName =
178 "分类明细" + timestampFormat(new Date().getTime()) + ".xlsx";
179
180 buildExcelHeader({
181 url: app.api.exportArticleClassifyRank,
182 data: this.dashboardForm,
183 filename: fileName
184 });
185 }
186 },
187 mounted() {},
188 created() {
189 this.initData();
190 }
191 };
192 </script>
193
194 <style lang="scss" scoped>
195 .stat-container {
196 color: #1a1b1c;
197 font-weight: 400;
198 position: relative;
199 max-width: 1100px;
200 margin: 0 auto;
201 padding: 30px;
202 margin-top: 5px;
203 background-color: white;
204 .userInfo {
205 display: flex;
206 align-items: center;
207 span {
208 font-size: 40px;
209 margin-left: 30px;
210 }
211 }
212 .btn {
213 margin-top: 30px;
214 }
215 .formBox {
216 width: 500px;
217 background-color: white;
218 padding: 20px;
219 border-radius: 10px;
220 margin-top: 30px;
221 .footerBtn {
222 text-align: right;
223 }
224 }
225 }
226
227 h5 {
228 margin: 0;
229 }
230 .dataBoxList {
231 display: flex;
232 flex-wrap: wrap;
233 justify-content: space-between;
234 }
235 .dataBox {
236 width: 100%;
237 min-height: 240px;
238 background-color: rgb(242, 242, 242);
239 overflow: hidden;
240 margin-bottom: 30px;
241 .tit {
242 font-size: 22px;
243 margin: 30px;
244 }
245
246 .dataList {
247 display: flex;
248 justify-content: center;
249 margin-top: 60px;
250 .item {
251 width: 250px;
252 text-align: center;
253 label {
254 font-size: 16px;
255 }
256 h5 {
257 font-size: 40px;
258 margin: 20px 0;
259 }
260 }
261 }
262
263 .chartList {
264 width: 98%;
265 display: flex;
266 margin: 30px 0;
267 margin-left: 1%;
268 .chare {
269 width: 100%;
270 height: 400px;
271 }
272 }
273 }
274
275 .fixed-bottom {
276 width: 100%;
277 text-align: right;
278 }
279
280 .el-header {
281 padding: 0;
282 }
283 </style>
1 <template> 1 <template>
2 <div class="navbar"> 2 <div class="navbar">
3 <hamburger :toggle-click="toggleSideBar" :is-active="sidebar.opened" class="hamburger-container"/> 3 <hamburger
4 :toggle-click="toggleSideBar"
5 :is-active="sidebar.opened"
6 class="hamburger-container"
7 />
4 <breadcrumb /> 8 <breadcrumb />
5 <el-dropdown class="avatar-container" trigger="click"> 9 <el-dropdown class="avatar-container" trigger="click">
6 <div class="avatar-wrapper"> 10 <div class="avatar-wrapper">
7 <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar"> 11 <img :src="require('@/assets/user/user.jpg')" class="user-avatar" />
8 <i class="el-icon-caret-bottom"/> 12 <i class="el-icon-caret-bottom" />
9 </div> 13 </div>
10 <el-dropdown-menu slot="dropdown" class="user-dropdown"> 14 <el-dropdown-menu slot="dropdown" class="user-dropdown">
11 <router-link class="inlineBlock" to="/"> 15 <router-link class="inlineBlock" to="/">
12 <el-dropdown-item> 16 <el-dropdown-item>Home</el-dropdown-item>
13 Home
14 </el-dropdown-item>
15 </router-link> 17 </router-link>
16 <el-dropdown-item divided> 18 <el-dropdown-item divided>
17 <span style="display:block;" @click="logout">LogOut</span> 19 <span style="display:block;" @click="logout">LogOut</span>
...@@ -22,9 +24,9 @@ ...@@ -22,9 +24,9 @@
22 </template> 24 </template>
23 25
24 <script> 26 <script>
25 import { mapGetters } from 'vuex' 27 import { mapGetters } from "vuex";
26 import Breadcrumb from '@/components/Breadcrumb' 28 import Breadcrumb from "@/components/Breadcrumb";
27 import Hamburger from '@/components/Hamburger' 29 import Hamburger from "@/components/Hamburger";
28 30
29 export default { 31 export default {
30 components: { 32 components: {
...@@ -32,29 +34,27 @@ export default { ...@@ -32,29 +34,27 @@ export default {
32 Hamburger 34 Hamburger
33 }, 35 },
34 computed: { 36 computed: {
35 ...mapGetters([ 37 ...mapGetters(["sidebar", "avatar"])
36 'sidebar',
37 'avatar'
38 ])
39 }, 38 },
40 methods: { 39 methods: {
41 toggleSideBar() { 40 toggleSideBar() {
42 this.$store.dispatch('ToggleSideBar') 41 this.$store.dispatch("ToggleSideBar");
43 }, 42 },
44 logout() { 43 logout() {
45 this.$store.dispatch('LogOut').then(() => { 44 // this.$store.dispatch('LogOut').then(() => {
46 location.reload() // 为了重新实例化vue-router对象 避免bug 45 // location.reload() // 为了重新实例化vue-router对象 避免bug
47 }) 46 // })
47 this.$router.push({ path: "/login" });
48 } 48 }
49 } 49 }
50 } 50 };
51 </script> 51 </script>
52 52
53 <style rel="stylesheet/scss" lang="scss" scoped> 53 <style rel="stylesheet/scss" lang="scss" scoped>
54 .navbar { 54 .navbar {
55 height: 50px; 55 height: 50px;
56 line-height: 50px; 56 line-height: 50px;
57 box-shadow: 0 1px 3px 0 rgba(0,0,0,.12), 0 0 3px 0 rgba(0,0,0,.04); 57 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
58 .hamburger-container { 58 .hamburger-container {
59 line-height: 58px; 59 line-height: 58px;
60 height: 50px; 60 height: 50px;
......