From 2d97ba6a723a7dc086e95859654e2b2b4168cb7d Mon Sep 17 00:00:00 2001 From: H0nGzA1 <2505811377@qq.com> Date: Sun, 23 Oct 2022 18:34:49 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(=E6=96=B0=E5=A2=9E=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=EF=BC=9A=E8=AE=BE=E7=BD=AE=E9=BB=98=E8=AE=A4=E4=B8=BB=E9=A2=98?= =?UTF-8?q?):=20=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8D=E4=BA=86websocket?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E5=9C=B0=E5=9D=80=E9=94=99=E8=AF=AF=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=8C=E7=94=A8=E6=88=B7=E5=A4=B4=E5=83=8F=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E9=94=99=E8=AF=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/application/settings.py | 3 +- web/.env | 3 +- web/.env.development | 1 + web/.env.preview | 2 + web/.env.production | 2 + web/.env.test | 1 + web/src/api/websocket.js | 101 ++++----- .../components/header-user/userinfo.vue | 192 +++++++++--------- web/src/libs/util.js | 104 ++++++---- web/src/main.js | 75 +++---- web/src/setting.js | 82 ++++---- .../store/modules/d2admin/modules/account.js | 118 ++++++----- .../store/modules/d2admin/modules/theme.js | 73 ++++--- web/yarn.lock | 34 ++++ 14 files changed, 431 insertions(+), 360 deletions(-) diff --git a/backend/application/settings.py b/backend/application/settings.py index c8ce5e9..096ed2f 100644 --- a/backend/application/settings.py +++ b/backend/application/settings.py @@ -148,7 +148,8 @@ STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static"), ] -MEDIA_ROOT = "media" # 项目下的目录 +# MEDIA_ROOT = "media" # 项目下的目录 +MEDIA_ROOT = os.path.join(BASE_DIR, 'media/') MEDIA_URL = "/media/" # 跟STATIC_URL类似,指定用户可以通过这个url找到文件 # 收集静态文件,必须将 MEDIA_ROOT,STATICFILES_DIRS先注释 diff --git a/web/.env b/web/.env index af33066..ed4d7df 100644 --- a/web/.env +++ b/web/.env @@ -3,7 +3,8 @@ # 页面 title 前缀 VUE_APP_TITLE=D2Admin -# 网络请求公用地址 +# 网络请求公用地址,如果打包之后多一层去掉/api + VUE_APP_API=/api/ # 仓库地址 diff --git a/web/.env.development b/web/.env.development index 2b35a9a..3018dab 100644 --- a/web/.env.development +++ b/web/.env.development @@ -7,3 +7,4 @@ VUE_APP_PM_ENABLED = true # 后端接口地址及端口(域名) VUE_APP_API = "http://127.0.0.1:8000" +VUE_APP_WEB_SOCKET_URL = 'ws://127.0.0.1:8000' \ No newline at end of file diff --git a/web/.env.preview b/web/.env.preview index 1855d20..d47a373 100644 --- a/web/.env.preview +++ b/web/.env.preview @@ -13,3 +13,5 @@ VUE_APP_SCOURCE_LINK=FALSE VUE_APP_PUBLIC_PATH=/ # 启用权限管理 VUE_APP_PM_ENABLED = true + +VUE_APP_WEB_SOCKET_URL = 'ws://127.0.0.1:8000' \ No newline at end of file diff --git a/web/.env.production b/web/.env.production index 8b3fa56..878aa43 100644 --- a/web/.env.production +++ b/web/.env.production @@ -13,3 +13,5 @@ VUE_APP_SCOURCE_LINK=FALSE VUE_APP_PUBLIC_PATH=/ # 启用权限管理 VUE_APP_PM_ENABLED = true + +VUE_APP_WEB_SOCKET_URL = 'ws://127.0.0.1:8000' \ No newline at end of file diff --git a/web/.env.test b/web/.env.test index 4c25089..6797e5d 100644 --- a/web/.env.test +++ b/web/.env.test @@ -7,3 +7,4 @@ VUE_APP_PM_ENABLED = true # 后端接口地址及端口(域名) VUE_APP_API = "http://127.0.0.1:8000/" +VUE_APP_WEB_SOCKET_URL = 'ws://127.0.0.1:8000' \ No newline at end of file diff --git a/web/src/api/websocket.js b/web/src/api/websocket.js index a06bdfc..81bbe15 100644 --- a/web/src/api/websocket.js +++ b/web/src/api/websocket.js @@ -1,70 +1,73 @@ -import ElementUI from 'element-ui' -import util from '@/libs/util' -function initWebSocket (e) { - const token = util.cookies.get('token') +import ElementUI from "element-ui"; +import util from "@/libs/util"; +function initWebSocket(e) { + const token = util.cookies.get("token"); if (token) { - const wsUri = 'ws://127.0.0.1:8000/?auth=' + token - this.socket = new WebSocket(wsUri)// 这里面的this都指向vue - this.socket.onerror = webSocketOnError - this.socket.onmessage = webSocketOnMessage - this.socket.onclose = closeWebsocket + // console.log(object); + const wsUri = util.webSocketURL() + "/?auth=" + token; + this.socket = new WebSocket(wsUri); // 这里面的this都指向vue + this.socket.onerror = webSocketOnError; + this.socket.onmessage = webSocketOnMessage; + this.socket.onclose = closeWebsocket; } } -function webSocketOnError (e) { +function webSocketOnError(e) { ElementUI.Notification({ - title: '', - message: 'WebSocket连接发生错误' + JSON.stringify(e), - type: 'error', - position: 'bottom-right', - duration: 3000 - }) + title: "", + message: "WebSocket连接发生错误" + JSON.stringify(e), + type: "error", + position: "bottom-right", + duration: 3000, + }); } -function webSocketOnMessage (e) { - const data = JSON.parse(e.data) - if (data.contentType === 'INFO') { +function webSocketOnMessage(e) { + const data = JSON.parse(e.data); + if (data.contentType === "INFO") { ElementUI.Notification({ - title: 'websocket', + title: "websocket", message: data.content, - type: 'success', - position: 'bottom-right', - duration: 3000 - }) - } else if (data.contentType === 'ERROR') { + type: "success", + position: "bottom-right", + duration: 3000, + }); + } else if (data.contentType === "ERROR") { ElementUI.Notification({ - title: '', + title: "", message: data.content, - type: 'error', - position: 'bottom-right', - duration: 0 - }) - } else if (data.contentType === 'TEXT') { + type: "error", + position: "bottom-right", + duration: 0, + }); + } else if (data.contentType === "TEXT") { ElementUI.Notification({ - title: '温馨提示', + title: "温馨提示", message: data.content, - type: 'success', - position: 'bottom-right', - duration: 0 - }) + type: "success", + position: "bottom-right", + duration: 0, + }); } else { - console.log(data.content) + console.log(data.content); } } // 关闭websiocket -function closeWebsocket () { - console.log('连接已关闭...') - close() +function closeWebsocket() { + console.log("连接已关闭..."); + close(); } -function close () { - this.socket.close() // 关闭 websocket +function close() { + this.socket.close(); // 关闭 websocket this.socket.onclose = function (e) { - console.log(e)// 监听关闭事件 - console.log('关闭') - } + console.log(e); // 监听关闭事件 + console.log("关闭"); + }; } -function webSocketSend (message) { - this.socket.send(JSON.stringify(message)) +function webSocketSend(message) { + this.socket.send(JSON.stringify(message)); } export default { - initWebSocket, close, webSocketSend -} + initWebSocket, + close, + webSocketSend, +}; diff --git a/web/src/layout/header-aside/components/header-user/userinfo.vue b/web/src/layout/header-aside/components/header-user/userinfo.vue index a761f9c..4e35cd3 100644 --- a/web/src/layout/header-aside/components/header-user/userinfo.vue +++ b/web/src/layout/header-aside/components/header-user/userinfo.vue @@ -123,175 +123,177 @@ diff --git a/web/src/libs/util.js b/web/src/libs/util.js index 9d0abd1..5a9e3c8 100644 --- a/web/src/libs/util.js +++ b/web/src/libs/util.js @@ -1,82 +1,102 @@ -import cookies from './util.cookies' -import db from './util.db' -import log from './util.log' -import dayjs from 'dayjs' -import filterParams from './util.params' +import cookies from "./util.cookies"; +import db from "./util.db"; +import log from "./util.log"; +import dayjs from "dayjs"; +import filterParams from "./util.params"; const util = { cookies, db, log, - filterParams -} + filterParams, +}; /** * @description 更新标题 * @param {String} titleText 标题 */ util.title = function (titleText) { - const processTitle = process.env.VUE_APP_TITLE || 'D2Admin' - window.document.title = `${processTitle}${titleText ? ` | ${titleText}` : ''}` -} + const processTitle = process.env.VUE_APP_TITLE || "D2Admin"; + window.document.title = `${processTitle}${ + titleText ? ` | ${titleText}` : "" + }`; +}; /** * @description 打开新页面 * @param {String} url 地址 */ util.open = function (url) { - var a = document.createElement('a') - a.setAttribute('href', url) - a.setAttribute('target', '_blank') - a.setAttribute('id', 'd2admin-link-temp') - document.body.appendChild(a) - a.click() - document.body.removeChild(document.getElementById('d2admin-link-temp')) -} + var a = document.createElement("a"); + a.setAttribute("href", url); + a.setAttribute("target", "_blank"); + a.setAttribute("id", "d2admin-link-temp"); + document.body.appendChild(a); + a.click(); + document.body.removeChild(document.getElementById("d2admin-link-temp")); +}; /** * @description 校验是否为租户模式。租户模式把域名替换成 域名 加端口 */ util.baseURL = function () { - var baseURL = process.env.VUE_APP_API - if (window.pluginsAll && window.pluginsAll.indexOf('dvadmin-tenant-web') !== -1) { + var baseURL = process.env.VUE_APP_API; + if ( + window.pluginsAll && + window.pluginsAll.indexOf("dvadmin-tenant-web") !== -1 + ) { // document.domain - var host = baseURL.split('/')[2] - var prot = host.split(':')[1] || 80 - host = document.domain + ':' + prot - baseURL = baseURL.split('/')[0] + '//' + baseURL.split('/')[1] + host + '/' + (baseURL.split('/')[3] || '') + var host = baseURL.split("/")[2]; + var prot = host.split(":")[1] || 80; + host = document.domain + ":" + prot; + baseURL = + baseURL.split("/")[0] + + "//" + + baseURL.split("/")[1] + + host + + "/" + + (baseURL.split("/")[3] || ""); } - if (!baseURL.endsWith('/')) { - baseURL += '/' + if (!baseURL.endsWith("/")) { + baseURL += "/"; } - return baseURL -} + return baseURL; +}; +/* + * 获取websocket地址 + */ +util.webSocketURL = function () { + return process.env.VUE_APP_WEB_SOCKET_URL; +}; + /** * 自动生成ID */ util.autoCreateCode = function () { - return dayjs().format('YYYYMMDDHHmmssms') + Math.round(Math.random() * 80 + 20) -} + return ( + dayjs().format("YYYYMMDDHHmmssms") + Math.round(Math.random() * 80 + 20) + ); +}; /** * 自动生成短 ID */ util.autoShortCreateCode = function () { - var Num = '' + var Num = ""; for (var i = 0; i < 4; i++) { - Num += Math.floor(Math.random() * 10) + Num += Math.floor(Math.random() * 10); } - return dayjs().format('YYMMDD') + Num -} + return dayjs().format("YYMMDD") + Num; +}; /** * 生产随机字符串 */ util.randomString = function (e) { - e = e || 32 - var t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' - var a = t.length - var n = '' - for (let i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a)) - return n -} + e = e || 32; + var t = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"; + var a = t.length; + var n = ""; + for (let i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a)); + return n; +}; -export default util +export default util; diff --git a/web/src/main.js b/web/src/main.js index 33df0fa..c9c1cc8 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -7,52 +7,51 @@ * @文件介绍: */ // Vue -import Vue from 'vue' -import i18n from './i18n' -import App from './App' +import Vue from "vue"; +import i18n from "./i18n"; +import App from "./App"; // 核心插件 -import d2Admin from '@/plugin/d2admin' +import d2Admin from "@/plugin/d2admin"; // store -import store from '@/store/index' +import store from "@/store/index"; // 菜单和路由设置 -import router from './router' -import { menuHeader } from '@/menu' +import router from "./router"; +import { menuHeader } from "@/menu"; // 按钮权限 -import '@/plugin/permission' // 加载permission +import "@/plugin/permission"; // 加载permission // d2-crud-plus 安装与初始化 -import './install' +import "./install"; // 配置vxe-table -import 'xe-utils' -import VXETable from 'vxe-table' -import 'vxe-table/lib/style.css' +import "xe-utils"; +import VXETable from "vxe-table"; +import "vxe-table/lib/style.css"; // md5加密 -import md5 from 'js-md5' +import md5 from "js-md5"; // websocket -import websocket from '@/api/websocket' +import websocket from "@/api/websocket"; // 核心插件 -Vue.use(d2Admin) -Vue.use(VXETable) -Vue.prototype.$md5 = md5 -Vue.prototype.$websocket = websocket +Vue.use(d2Admin); +Vue.use(VXETable); +Vue.prototype.$md5 = md5; +Vue.prototype.$websocket = websocket; new Vue({ router, store, i18n, - render: h => h(App), - beforeCreate () { + render: (h) => h(App), + beforeCreate() { // 初始化配置 - this.$store.dispatch('d2admin/settings/load') - this.$store.dispatch('d2admin/dictionary/load') + this.$store.dispatch("d2admin/settings/load"); + this.$store.dispatch("d2admin/dictionary/load"); }, - created () { - + created() { // 处理路由 得到每一级的路由设置 // this.$store.commit('d2admin/page/init', frameInRoutes) // 设置顶栏菜单 @@ -62,28 +61,30 @@ new Vue({ // 初始化菜单搜索功能 // this.$store.commit('d2admin/search/init', menuAside) }, - mounted () { + mounted() { // 展示系统信息 - this.$store.commit('d2admin/releases/versionShow') + this.$store.commit("d2admin/releases/versionShow"); // 用户登录后从数据库加载一系列的设置 - this.$store.dispatch('d2admin/account/load') + this.$store.dispatch("d2admin/account/load"); // 获取并记录用户 UA - this.$store.commit('d2admin/ua/get') + this.$store.commit("d2admin/ua/get"); // 初始化全屏监听 - this.$store.dispatch('d2admin/fullscreen/listen') + this.$store.dispatch("d2admin/fullscreen/listen"); }, watch: { // 检测路由变化切换侧边栏内容 - '$route.matched': { - handler (matched) { + "$route.matched": { + handler(matched) { if (matched.length > 0) { - const _side = menuHeader.filter(menu => menu.path === matched[0].path) + const _side = menuHeader.filter( + (menu) => menu.path === matched[0].path + ); if (_side.length > 0) { - this.$store.commit('d2admin/menu/asideSet', _side[0].children) + this.$store.commit("d2admin/menu/asideSet", _side[0].children); } } }, - immediate: true - } - } -}).$mount('#app') + immediate: true, + }, + }, +}).$mount("#app"); diff --git a/web/src/setting.js b/web/src/setting.js index 7c9296f..d2237a8 100644 --- a/web/src/setting.js +++ b/web/src/setting.js @@ -3,76 +3,78 @@ export default { // 支持快捷键 例如 ctrl+shift+s hotkey: { search: { - open: 's', - close: 'esc' - } + open: "s", + close: "esc", + }, }, // 侧边栏默认配置 menu: { asideCollapse: false, - asideTransition: true + asideTransition: true, }, // 在读取持久化数据失败时默认页面 page: { opened: [ { - name: 'index', - fullPath: '/index', + name: "index", + fullPath: "/index", meta: { - title: '控制台', - auth: false - } - } - ] + title: "控制台", + auth: false, + }, + }, + ], }, // 菜单搜索 search: { - enable: true + enable: true, }, // 注册的主题 theme: { list: [ { - title: 'd2admin 经典', - name: 'd2', - preview: 'image/theme/d2/preview@2x.png' + title: "d2admin 经典", + name: "d2", + preview: "image/theme/d2/preview@2x.png", }, { - title: 'Chester', - name: 'chester', - preview: 'image/theme/chester/preview@2x.jpg' + title: "Chester", + name: "chester", + preview: "image/theme/chester/preview@2x.jpg", }, { - title: 'Element', - name: 'element', - preview: 'image/theme/element/preview@2x.jpg' + title: "Element", + name: "element", + preview: "image/theme/element/preview@2x.jpg", }, { - title: '紫罗兰', - name: 'violet', - preview: 'image/theme/violet/preview@2x.jpg' + title: "紫罗兰", + name: "violet", + preview: "image/theme/violet/preview@2x.jpg", }, { - title: '简约线条', - name: 'line', - backgroundImage: 'image/theme/line/bg.jpg', - preview: 'image/theme/line/preview@2x.jpg' + title: "简约线条", + name: "line", + backgroundImage: "image/theme/line/bg.jpg", + preview: "image/theme/line/preview@2x.jpg", }, { - title: '流星', - name: 'star', - backgroundImage: 'image/theme/star/bg.jpg', - preview: 'image/theme/star/preview@2x.jpg' + title: "流星", + name: "star", + backgroundImage: "image/theme/star/bg.jpg", + preview: "image/theme/star/preview@2x.jpg", }, { - title: 'Tomorrow Night Blue (vsCode)', - name: 'tomorrow-night-blue', - preview: 'image/theme/tomorrow-night-blue/preview@2x.jpg' - } - ] + title: "Tomorrow Night Blue (vsCode)", + name: "tomorrow-night-blue", + preview: "image/theme/tomorrow-night-blue/preview@2x.jpg", + }, + ], }, // 是否默认开启页面切换动画 transition: { - active: true - } -} + active: true, + }, + // 设置默认主题 + defaultTheme: "d2", +}; diff --git a/web/src/store/modules/d2admin/modules/account.js b/web/src/store/modules/d2admin/modules/account.js index e3f0d79..7e4c85a 100644 --- a/web/src/store/modules/d2admin/modules/account.js +++ b/web/src/store/modules/d2admin/modules/account.js @@ -6,11 +6,11 @@ * 联系Qq:1638245306 * @文件介绍: 登录和登出 */ -import { Message, MessageBox } from 'element-ui' -import util from '@/libs/util.js' -import router from '@/router' -import store from '@/store/index' -import { SYS_USER_LOGIN, SYS_USER_LOGOUT } from '@/views/system/login/api' +import { Message, MessageBox } from "element-ui"; +import util from "@/libs/util.js"; +import router from "@/router"; +import store from "@/store/index"; +import { SYS_USER_LOGIN, SYS_USER_LOGOUT } from "@/views/system/login/api"; export default { namespaced: true, @@ -22,95 +22,101 @@ export default { * @param {Object} payload password {String} 密码 * @param {Object} payload route {Object} 登录成功后定向的路由对象 任何 vue-router 支持的格式 */ - async login ({ dispatch }, { - username = '', - password = '', - captcha = '', - captchaKey = '' - } = {}) { + async login( + { dispatch }, + { username = "", password = "", captcha = "", captchaKey = "" } = {} + ) { let res = await SYS_USER_LOGIN({ username, password, captcha, - captchaKey - }) + captchaKey, + }); // 设置 cookie 一定要存 uuid 和 token 两个 cookie // 整个系统依赖这两个数据进行校验和存储 // uuid 是用户身份唯一标识 用户注册的时候确定 并且不可改变 不可重复 // token 代表用户当前登录状态 建议在网络请求中携带 token // 如有必要 token 需要定时更新,默认保存一天 - res = res.data - util.cookies.set('uuid', res.userId) - util.cookies.set('token', res.access) - util.cookies.set('refresh', res.refresh) + res = res.data; + util.cookies.set("uuid", res.userId); + util.cookies.set("token", res.access); + util.cookies.set("refresh", res.refresh); // 设置 vuex 用户信息 - await dispatch('d2admin/user/set', { name: res.name, user_id: res.userId, avatar: res.avatar }, { root: true }) + await dispatch( + "d2admin/user/set", + { name: res.name, user_id: res.userId, avatar: res.avatar }, + { root: true } + ); // 用户登录后从持久化数据加载一系列的设置 - await dispatch('load') + await dispatch("load"); }, /** * @description 注销用户并返回登录页面 * @param {Object} context * @param {Object} payload confirm {Boolean} 是否需要确认 */ - logout ({ commit, dispatch }, { confirm = false } = {}) { + logout({ commit, dispatch }, { confirm = false } = {}) { /** * @description 注销 */ - async function logout () { - await SYS_USER_LOGOUT({ refresh: util.cookies.get('refresh') }).then(() => { - // 删除cookie - util.cookies.remove('token') - util.cookies.remove('uuid') - util.cookies.remove('refresh') - }) + async function logout() { + await SYS_USER_LOGOUT({ refresh: util.cookies.get("refresh") }).then( + () => { + // 删除cookie + util.cookies.remove("token"); + util.cookies.remove("uuid"); + util.cookies.remove("refresh"); + } + ); // 清空 vuex 用户信息 - await dispatch('d2admin/user/set', {}, { root: true }) - store.commit('d2admin/menu/asideSet', []) // 设置侧边栏菜单 - store.commit('d2admin/search/init', []) // 设置搜索 - sessionStorage.removeItem('menuData') + await dispatch("d2admin/user/set", {}, { root: true }); + store.commit("d2admin/menu/asideSet", []); // 设置侧边栏菜单 + store.commit("d2admin/search/init", []); // 设置搜索 + sessionStorage.removeItem("menuData"); - store.dispatch('d2admin/db/databaseClear') + store.dispatch("d2admin/db/databaseClear"); // 跳转路由 - router.push({ name: 'login' }) - router.go(0) + router.push({ name: "login" }); + router.go(0); } // 判断是否需要确认 if (confirm) { - commit('d2admin/gray/set', true, { root: true }) - MessageBox.confirm('确定要注销当前用户吗', '注销用户', { type: 'warning' }) + commit("d2admin/gray/set", true, { root: true }); + MessageBox.confirm("确定要注销当前用户吗", "注销用户", { + type: "warning", + }) .then(() => { - commit('d2admin/gray/set', false, { root: true }) - logout() + commit("d2admin/gray/set", false, { root: true }); + logout(); }) .catch(() => { - commit('d2admin/gray/set', false, { root: true }) - Message({ message: '取消注销操作' }) - }) + commit("d2admin/gray/set", false, { root: true }); + Message({ message: "取消注销操作" }); + }); } else { - logout() + logout(); } }, /** - * @description 用户登录后从持久化数据加载一系列的设置 - * @param {Object} context - */ - async load ({ dispatch }) { + * @description 用户登录后从持久化数据加载一系列的设置 + * @param {Object} context + */ + async load({ dispatch }) { // 加载用户名 - await dispatch('d2admin/user/load', null, { root: true }) + await dispatch("d2admin/user/load", null, { root: true }); // 加载主题 - await dispatch('d2admin/theme/load', null, { root: true }) + await dispatch("d2admin/theme/load", null, { root: true }); // 加载页面过渡效果设置 - await dispatch('d2admin/transition/load', null, { root: true }) + await dispatch("d2admin/transition/load", null, { root: true }); // 持久化数据加载上次退出时的多页列表 - await dispatch('d2admin/page/openedLoad', null, { root: true }) + await dispatch("d2admin/page/openedLoad", null, { root: true }); // 持久化数据加载侧边栏配置 - await dispatch('d2admin/menu/asideLoad', null, { root: true }) + await dispatch("d2admin/menu/asideLoad", null, { root: true }); // 持久化数据加载全局尺寸 - await dispatch('d2admin/size/load', null, { root: true }) + await dispatch("d2admin/size/load", null, { root: true }); // 持久化数据加载颜色设置 - await dispatch('d2admin/color/load', null, { root: true }) - } - } -} + await dispatch("d2admin/color/load", null, { root: true }); + }, + }, +}; diff --git a/web/src/store/modules/d2admin/modules/theme.js b/web/src/store/modules/d2admin/modules/theme.js index 755db07..854cd81 100644 --- a/web/src/store/modules/d2admin/modules/theme.js +++ b/web/src/store/modules/d2admin/modules/theme.js @@ -1,76 +1,71 @@ -import { get } from 'lodash' -import setting from '@/setting.js' +import { get } from "lodash"; +import setting from "@/setting.js"; export default { namespaced: true, state: { // 主题 - list: get(setting, 'theme.list', []), + list: get(setting, "theme.list", []), // 现在激活的主题 这应该是一个名字 不是对象 - activeName: get(setting, 'theme.list[0].name', 'd2') + activeName: get(setting, "theme.list[0].name", "d2"), }, getters: { /** * @description 返回当前的主题信息 不是一个名字 而是当前激活主题的所有数据 * @param {Object} state state */ - activeSetting (state) { - return state.list.find(theme => theme.name === state.activeName) - } + activeSetting(state) { + return state.list.find((theme) => theme.name === state.activeName); + }, }, actions: { /** * @description 激活一个主题 * @param {String} themeValue 需要激活的主题名称 */ - async set ({ state, commit, dispatch }, themeName) { + async set({ state, commit, dispatch }, themeName) { // 检查这个主题在主题列表里是否存在 - state.activeName = state.list.find(e => e.name === themeName) ? themeName : state.list[0].name + state.activeName = state.list.find((e) => e.name === themeName) + ? themeName + : setting.defaultTheme; // 将 vuex 中的主题应用到 dom - commit('dom') + commit("dom"); // 持久化 - await dispatch('d2admin/db/set', { - dbName: 'sys', - path: 'theme.activeName', - value: state.activeName, - user: true - }, { root: true }) + await dispatch( + "d2admin/db/set", + { + dbName: "sys", + path: "theme.activeName", + value: state.activeName, + user: true, + }, + { root: true } + ); }, /** * @description 从持久化数据加载主题设置 * @param {Object} context */ - async load ({ state, commit, dispatch }) { + async load({ state, commit, dispatch }) { // store 赋值 - const activeName = await dispatch('d2admin/db/get', { - dbName: 'sys', - path: 'theme.activeName', - defaultValue: state.list[0].name, - user: true - }, { root: true }) + const activeName = setting.defaultTheme; // 检查这个主题在主题列表里是否存在 - if (state.list.find(e => e.name === activeName)) { - state.activeName = activeName + if (state.list.find((e) => e.name === activeName)) { + state.activeName = activeName; } else { - state.activeName = state.list[0].name + state.activeName = setting.defaultTheme; // 持久化 - await dispatch('d2admin/db/set', { - dbName: 'sys', - path: 'theme.activeName', - value: state.activeName, - user: true - }, { root: true }) } // 将 vuex 中的主题应用到 dom - commit('dom') - } + commit("dom"); + }, }, mutations: { /** * @description 将 vuex 中的主题应用到 dom * @param {Object} state state */ - dom (state) { - document.body.className = `theme-${state.activeName}` - } - } -} + dom(state) { + document.body.className = `theme-${state.activeName}`; + }, + }, +}; diff --git a/web/yarn.lock b/web/yarn.lock index 6a840e9..70111f6 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -903,6 +903,13 @@ core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" +"@babel/runtime@^7.10.5", "@babel/runtime@^7.7.2": + version "7.19.4" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.4.tgz#a42f814502ee467d55b38dd1c256f53a7b885c78" + integrity sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/runtime@^7.11.0", "@babel/runtime@^7.11.2", "@babel/runtime@^7.8.4": version "7.17.9" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72" @@ -6156,6 +6163,13 @@ import-from@^2.1.0: dependencies: resolve-from "^3.0.0" +import-html-entry@^1.14.0: + version "1.14.0" + resolved "https://registry.npmjs.org/import-html-entry/-/import-html-entry-1.14.0.tgz#9a05928373bb7e9362cd8dd428a82387a87524ff" + integrity sha512-CQQMV+2rxHCLMSXsajV1cjT1g6xi3ujMAPnGwR96xHaN5/JEVIOUGkM7LDRn73dk8E8NaHmOf3rvPPExPPe1xw== + dependencies: + "@babel/runtime" "^7.7.2" + import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" @@ -9295,6 +9309,16 @@ q@^1.1.2: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= +qiankun@^2.7.2: + version "2.8.3" + resolved "https://registry.npmjs.org/qiankun/-/qiankun-2.8.3.tgz#752326bf655b710844362ee691a5f332160cd53c" + integrity sha512-bq09dwm29NybhoG8UI8z6fdY5weaQ2l1CTxZcnVIbWLVzpzNyoebnnBTGMuZyRsoSY3gflO96RC2jK7ARiOGvA== + dependencies: + "@babel/runtime" "^7.10.5" + import-html-entry "^1.14.0" + lodash "^4.17.11" + single-spa "^5.9.2" + qiniu-js@^2.5.4: version "2.5.5" resolved "https://registry.yarnpkg.com/qiniu-js/-/qiniu-js-2.5.5.tgz#77d295f222620f9377d6148f3f757d189a1e4977" @@ -10059,6 +10083,11 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +single-spa@^5.9.2: + version "5.9.4" + resolved "https://registry.npmjs.org/single-spa/-/single-spa-5.9.4.tgz#2a995b0784867a3f60ceb458de295ee67f045077" + integrity sha512-QkEoh0AzGuU82qnbUUk0ydF78QbU5wMKqKKJn7uUQfBiOYlRQEfIOpLM4m23Sab+kTOLI1kbYhYeiQ7fX5KVVw== + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -11340,6 +11369,11 @@ vue-i18n@^8.15.1, vue-i18n@^8.17.0: resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-8.27.1.tgz#fe660f6c14793ae404d6a715875d772594a3324f" integrity sha512-lWrGm4F25qReJ7XxSnFVb2h3PfW54ldnM4C+YLBGGJ75+Myt/kj4hHSTKqsyDLamvNYpvINMicSOdW+7yuqgIQ== +vue-infinite-scroll@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/vue-infinite-scroll/-/vue-infinite-scroll-2.0.2.tgz#ca37a91fe92ee0ad3b74acf8682c00917144b711" + integrity sha512-n+YghR059YmciANGJh9SsNWRi1YZEBVlODtmnb/12zI+4R72QZSWd+EuZ5mW6auEo/yaJXgxzwsuhvALVnm73A== + vue-jest@^3.0.5: version "3.0.7" resolved "https://registry.yarnpkg.com/vue-jest/-/vue-jest-3.0.7.tgz#a6d29758a5cb4d750f5d1242212be39be4296a33" From 6471575461b846e78d7f9d164eb51353497ad36a Mon Sep 17 00:00:00 2001 From: H0nGzA1 <2505811377@qq.com> Date: Sun, 23 Oct 2022 11:05:42 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20back?= =?UTF-8?q?end/application/settings.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/application/settings.py | 382 -------------------------------- 1 file changed, 382 deletions(-) delete mode 100644 backend/application/settings.py diff --git a/backend/application/settings.py b/backend/application/settings.py deleted file mode 100644 index 096ed2f..0000000 --- a/backend/application/settings.py +++ /dev/null @@ -1,382 +0,0 @@ -""" -Django settings for application project. - -Generated by 'django-admin startproject' using Django 3.2.3. - -For more information on this file, see -https://docs.djangoproject.com/en/3.2/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/3.2/ref/settings/ -""" - -import os -import sys -from pathlib import Path - -# Build paths inside the project like this: BASE_DIR / 'subdir'. -BASE_DIR = Path(__file__).resolve().parent.parent - -# ================================================= # -# ******************** 动态配置 ******************** # -# ================================================= # - -from conf.env import * - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "django-insecure--z8%exyzt7e_%i@1+#1mm=%lb5=^fx_57=1@a+_y7bg5-w%)sm" -# 初始化plugins插件路径到环境变量中 -PLUGINS_PATH = os.path.join(BASE_DIR, "plugins") -sys.path.insert(0, os.path.join(PLUGINS_PATH)) - -[ - sys.path.insert(0, os.path.join(PLUGINS_PATH, ele)) - for ele in os.listdir(PLUGINS_PATH) - if os.path.isdir(os.path.join(PLUGINS_PATH, ele)) and not ele.startswith("__") -] - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = locals().get("DEBUG", True) -ALLOWED_HOSTS = locals().get("ALLOWED_HOSTS", ["*"]) - -# Application definition - -INSTALLED_APPS = [ - "django.contrib.auth", - "django.contrib.contenttypes", - "django.contrib.sessions", - "django.contrib.messages", - "django.contrib.staticfiles", - "django_comment_migrate", - "rest_framework", - "django_filters", - "corsheaders", # 注册跨域app - "dvadmin.system", - "drf_yasg", - "captcha", -] - -MIDDLEWARE = [ - "django.middleware.security.SecurityMiddleware", - "whitenoise.middleware.WhiteNoiseMiddleware", - "django.contrib.sessions.middleware.SessionMiddleware", - "corsheaders.middleware.CorsMiddleware", # 跨域中间件 - "django.middleware.common.CommonMiddleware", - "django.middleware.csrf.CsrfViewMiddleware", - "django.contrib.auth.middleware.AuthenticationMiddleware", - "django.contrib.messages.middleware.MessageMiddleware", - "django.middleware.clickjacking.XFrameOptionsMiddleware", - "dvadmin.utils.middleware.ApiLoggingMiddleware", -] - -ROOT_URLCONF = "application.urls" - -TEMPLATES = [ - { - "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [os.path.join(BASE_DIR, "templates")], - "APP_DIRS": True, - "OPTIONS": { - "context_processors": [ - "django.template.context_processors.debug", - "django.template.context_processors.request", - "django.contrib.auth.context_processors.auth", - "django.contrib.messages.context_processors.messages", - ], - }, - }, -] - -WSGI_APPLICATION = "application.wsgi.application" - -# Database -# https://docs.djangoproject.com/en/3.2/ref/settings/#databases - -DATABASES = { - "default": { - "ENGINE": DATABASE_ENGINE, - "NAME": DATABASE_NAME, - "USER": DATABASE_USER, - "PASSWORD": DATABASE_PASSWORD, - "HOST": DATABASE_HOST, - "PORT": DATABASE_PORT, - } -} -AUTH_USER_MODEL = "system.Users" -USERNAME_FIELD = "username" - -# Password validation -# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators - -AUTH_PASSWORD_VALIDATORS = [ - { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", - }, - { - "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", - }, -] - -# Internationalization -# https://docs.djangoproject.com/en/3.2/topics/i18n/ - -LANGUAGE_CODE = "zh-hans" - -TIME_ZONE = "Asia/Shanghai" - -USE_I18N = True - -USE_L10N = True - -USE_TZ = False - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/3.2/howto/static-files/ - -STATIC_URL = "/static/" -# # 设置django的静态文件目录 -STATICFILES_DIRS = [ - os.path.join(BASE_DIR, "static"), -] - -# MEDIA_ROOT = "media" # 项目下的目录 -MEDIA_ROOT = os.path.join(BASE_DIR, 'media/') -MEDIA_URL = "/media/" # 跟STATIC_URL类似,指定用户可以通过这个url找到文件 - -# 收集静态文件,必须将 MEDIA_ROOT,STATICFILES_DIRS先注释 -# python manage.py collectstatic -# STATIC_ROOT=os.path.join(BASE_DIR,'static') - -# ================================================= # -# ******************* 跨域的配置 ******************* # -# ================================================= # - -# 全部允许配置 -CORS_ORIGIN_ALLOW_ALL = True -# 允许cookie -CORS_ALLOW_CREDENTIALS = True # 指明在跨域访问中,后端是否支持对cookie的操作 - -# ================================================= # -# ********************* 日志配置 ******************* # -# ================================================= # - -# log 配置部分BEGIN # -SERVER_LOGS_FILE = os.path.join(BASE_DIR, "logs", "server.log") -ERROR_LOGS_FILE = os.path.join(BASE_DIR, "logs", "error.log") -if not os.path.exists(os.path.join(BASE_DIR, "logs")): - os.makedirs(os.path.join(BASE_DIR, "logs")) - -# 格式:[2020-04-22 23:33:01][micoservice.apps.ready():16] [INFO] 这是一条日志: -# 格式:[日期][模块.函数名称():行号] [级别] 信息 -STANDARD_LOG_FORMAT = ( - "[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s" -) -CONSOLE_LOG_FORMAT = ( - "[%(asctime)s][%(name)s.%(funcName)s():%(lineno)d] [%(levelname)s] %(message)s" -) - -LOGGING = { - "version": 1, - "disable_existing_loggers": False, - "formatters": { - "standard": {"format": STANDARD_LOG_FORMAT}, - "console": { - "format": CONSOLE_LOG_FORMAT, - "datefmt": "%Y-%m-%d %H:%M:%S", - }, - "file": { - "format": CONSOLE_LOG_FORMAT, - "datefmt": "%Y-%m-%d %H:%M:%S", - }, - }, - "handlers": { - "file": { - "level": "INFO", - "class": "logging.handlers.RotatingFileHandler", - "filename": SERVER_LOGS_FILE, - "maxBytes": 1024 * 1024 * 100, # 100 MB - "backupCount": 5, # 最多备份5个 - "formatter": "standard", - "encoding": "utf-8", - }, - "error": { - "level": "ERROR", - "class": "logging.handlers.RotatingFileHandler", - "filename": ERROR_LOGS_FILE, - "maxBytes": 1024 * 1024 * 100, # 100 MB - "backupCount": 3, # 最多备份3个 - "formatter": "standard", - "encoding": "utf-8", - }, - "console": { - "level": "INFO", - "class": "logging.StreamHandler", - "formatter": "console", - }, - }, - "loggers": { - # default日志 - "": { - "handlers": ["console", "error", "file"], - "level": "INFO", - }, - "django": { - "handlers": ["console", "error", "file"], - "level": "INFO", - "propagate": False, - }, - "scripts": { - "handlers": ["console", "error", "file"], - "level": "INFO", - "propagate": False, - }, - # 数据库相关日志 - "django.db.backends": { - "handlers": [], - "propagate": True, - "level": "INFO", - }, - }, -} - -# ================================================= # -# *************** REST_FRAMEWORK配置 *************** # -# ================================================= # - -REST_FRAMEWORK = { - "DATETIME_FORMAT": "%Y-%m-%d %H:%M:%S", # 日期时间格式配置 - "DATE_FORMAT": "%Y-%m-%d", - "DEFAULT_FILTER_BACKENDS": ( - # 'django_filters.rest_framework.DjangoFilterBackend', - "dvadmin.utils.filters.CustomDjangoFilterBackend", - "rest_framework.filters.SearchFilter", - "rest_framework.filters.OrderingFilter", - ), - "DEFAULT_PAGINATION_CLASS": "dvadmin.utils.pagination.CustomPagination", # 自定义分页 - "DEFAULT_AUTHENTICATION_CLASSES": ( - "rest_framework_simplejwt.authentication.JWTAuthentication", - "rest_framework.authentication.SessionAuthentication", - ), - "DEFAULT_PERMISSION_CLASSES": [ - "rest_framework.permissions.IsAuthenticated", # 只有经过身份认证确定用户身份才能访问 - # 'rest_framework.permissions.IsAdminUser', # is_staff=True才能访问 —— 管理员(员工)权限 - # 'rest_framework.permissions.AllowAny', # 允许所有 - # 'rest_framework.permissions.IsAuthenticatedOrReadOnly', # 有身份 或者 只读访问(self.list,self.retrieve) - ], - "EXCEPTION_HANDLER": "dvadmin.utils.exception.CustomExceptionHandler", # 自定义的异常处理 -} -# ================================================= # -# ******************** 登录方式配置 ******************** # -# ================================================= # - -AUTHENTICATION_BACKENDS = ["dvadmin.utils.backends.CustomBackend"] -# ================================================= # -# ****************** simplejwt配置 ***************** # -# ================================================= # -from datetime import timedelta - -SIMPLE_JWT = { - # token有效时长 - "ACCESS_TOKEN_LIFETIME": timedelta(minutes=120), - # token刷新后的有效时间 - "REFRESH_TOKEN_LIFETIME": timedelta(days=1), - # 设置前缀 - "AUTH_HEADER_TYPES": ("JWT",), - "ROTATE_REFRESH_TOKENS": True, -} - -# ====================================# -# ****************swagger************# -# ====================================# -SWAGGER_SETTINGS = { - # 基础样式 - "SECURITY_DEFINITIONS": {"basic": {"type": "basic"}}, - # 如果需要登录才能够查看接口文档, 登录的链接使用restframework自带的. - "LOGIN_URL": "apiLogin/", - # 'LOGIN_URL': 'rest_framework:login', - "LOGOUT_URL": "rest_framework:logout", - # 'DOC_EXPANSION': None, - # 'SHOW_REQUEST_HEADERS':True, - # 'USE_SESSION_AUTH': True, - # 'DOC_EXPANSION': 'list', - # 接口文档中方法列表以首字母升序排列 - "APIS_SORTER": "alpha", - # 如果支持json提交, 则接口文档中包含json输入框 - "JSON_EDITOR": True, - # 方法列表字母排序 - "OPERATIONS_SORTER": "alpha", - "VALIDATOR_URL": None, - "AUTO_SCHEMA_TYPE": 2, # 分组根据url层级分,0、1 或 2 层 - "DEFAULT_AUTO_SCHEMA_CLASS": "dvadmin.utils.swagger.CustomSwaggerAutoSchema", -} - -# ================================================= # -# **************** 验证码配置 ******************* # -# ================================================= # -CAPTCHA_IMAGE_SIZE = (160, 60) # 设置 captcha 图片大小 -CAPTCHA_LENGTH = 4 # 字符个数 -CAPTCHA_TIMEOUT = 1 # 超时(minutes) -CAPTCHA_OUTPUT_FORMAT = "%(image)s %(text_field)s %(hidden_field)s " -CAPTCHA_FONT_SIZE = 40 # 字体大小 -CAPTCHA_FOREGROUND_COLOR = "#64DAAA" # 前景色 -CAPTCHA_BACKGROUND_COLOR = "#F5F7F4" # 背景色 -CAPTCHA_NOISE_FUNCTIONS = ( - "captcha.helpers.noise_arcs", # 线 - # "captcha.helpers.noise_dots", # 点 -) -# CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge' #字母验证码 -CAPTCHA_CHALLENGE_FUNCT = "captcha.helpers.math_challenge" # 加减乘除验证码 - -# ================================================= # -# ******************** 其他配置 ******************** # -# ================================================= # - -DEFAULT_AUTO_FIELD = "django.db.models.AutoField" -API_LOG_ENABLE = True -# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE'] -API_LOG_METHODS = ["POST", "UPDATE", "DELETE", "PUT"] # ['POST', 'DELETE'] -API_MODEL_MAP = { - "/token/": "登录模块", - "/api/login/": "登录模块", - "/api/plugins_market/plugins/": "插件市场", -} - -DJANGO_CELERY_BEAT_TZ_AWARE = False -CELERY_TIMEZONE = "Asia/Shanghai" # celery 时区问题 -# 静态页面压缩 -STATICFILES_STORAGE = "whitenoise.storage.CompressedStaticFilesStorage" - -ALL_MODELS_OBJECTS = [] # 所有app models 对象 - -# 初始化需要执行的列表,用来初始化后执行 -INITIALIZE_LIST = [] -INITIALIZE_RESET_LIST = [] -# 表前缀 -TABLE_PREFIX = locals().get('TABLE_PREFIX', "") -# 系统配置 -SYSTEM_CONFIG = {} -# 字典配置 -DICTIONARY_CONFIG = {} - -# ================================================= # -# ******************** 插件配置 ******************** # -# ================================================= # -# 租户共享app -TENANT_SHARED_APPS = [] -# 插件 urlpatterns -PLUGINS_URL_PATTERNS = [] -# ********** 一键导入插件配置开始 ********** -# 例如: -# from dvadmin_upgrade_center.settings import * # 升级中心 -# from dvadmin_celery.settings import * # celery 异步任务 -# ... -# ********** 一键导入插件配置结束 **********