更新常见问题答疑
Showing
29 changed files
with
3144 additions
and
95 deletions
| ... | @@ -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 | ... | ... |
src/api/fetch-api-new.js
0 → 100644
| 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 | } |
src/assets/user/user.jpg
0 → 100644
3.93 KB
src/components/UploadImg/index.vue
0 → 100644
| 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> |
src/components/WangEditor/index.vue
0 → 100644
| 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 | } | ... | ... |
| ... | @@ -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 | ... | ... |
src/utils/utils.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/views/Q&A/article/detail.vue
0 → 100644
| 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 |
src/views/Q&A/article/list.vue
0 → 100644
| 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> |
src/views/Q&A/classify/detail.vue
0 → 100644
| 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> |
src/views/Q&A/classify/list.vue
0 → 100644
| 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> |
src/views/Q&A/keyword/detail.vue
0 → 100644
| 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> |
src/views/Q&A/keyword/list.vue
0 → 100644
| 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> |
src/views/Q&A/report/article.vue
0 → 100644
| 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> |
src/views/Q&A/report/classify.vue
0 → 100644
| 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> |
src/views/Q&A/report/keyword.vue
0 → 100644
| 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; | ... | ... |
This diff is collapsed.
Click to expand it.
-
Please register or sign in to post a comment