From 988daf03dd31dbe85d57299442ceb9c80d2a6290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Mon, 18 Mar 2024 14:28:25 +0800 Subject: [PATCH 01/30] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E8=A1=A8=E7=9A=84key=E5=80=BC=E5=A4=A7?= =?UTF-8?q?=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py index 6767877..0e29403 100644 --- a/backend/dvadmin/system/models.py +++ b/backend/dvadmin/system/models.py @@ -485,7 +485,7 @@ class SystemConfig(CoreModel): help_text="父级", ) title = models.CharField(max_length=50, verbose_name="标题", help_text="标题") - key = models.CharField(max_length=20, verbose_name="键", help_text="键", db_index=True) + key = models.CharField(max_length=100, verbose_name="键", help_text="键", db_index=True) value = models.JSONField(max_length=100, verbose_name="值", help_text="值", null=True, blank=True) sort = models.IntegerField(default=0, verbose_name="排序", help_text="排序", blank=True) status = models.BooleanField(default=True, verbose_name="启用状态", help_text="启用状态") From edf45c08d1cc4c54695e858ebfe9cac22527d323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Mon, 18 Mar 2024 18:18:44 +0800 Subject: [PATCH 02/30] =?UTF-8?q?feat:=20fast-crud=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/package.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/web/package.json b/web/package.json index 956d682..f6528f4 100644 --- a/web/package.json +++ b/web/package.json @@ -10,10 +10,11 @@ }, "dependencies": { "@element-plus/icons-vue": "^2.0.10", - "@fast-crud/fast-crud": "^1.19.2", - "@fast-crud/fast-extends": "^1.19.2", - "@fast-crud/ui-element": "^1.19.2", - "@fast-crud/ui-interface": "^1.19.2", + "@fast-crud/fast-crud": "^1.20.1", + "@fast-crud/fast-extends": "^1.20.1", + "@fast-crud/ui-element": "^1.20.1", + "@fast-crud/ui-interface": "^1.20.1", + "@iconify/vue": "^4.1.1", "@types/lodash": "^4.14.202", "@vitejs/plugin-vue-jsx": "^3.0.0", "@wangeditor/editor": "^5.1.23", @@ -22,7 +23,7 @@ "axios": "^1.2.1", "countup.js": "^2.3.2", "cropperjs": "^1.5.13", - "e-icon-picker": "^2.1.1", + "e-icon-picker": "^2.1.0", "echarts": "^5.4.1", "echarts-gl": "^2.0.9", "echarts-wordcloud": "^2.1.0", From 2cfd8f07988835177892d8ea73ee0cc264402d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Mon, 18 Mar 2024 21:21:19 +0800 Subject: [PATCH 03/30] =?UTF-8?q?feat:=20=E5=89=8D=E7=AB=AFlodash=E5=8C=85?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=88=90lodash-es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/package.json | 3 ++- web/src/layout/logo/index.vue | 2 +- web/src/views/system/login/index.vue | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/web/package.json b/web/package.json index f6528f4..ac89be4 100644 --- a/web/package.json +++ b/web/package.json @@ -23,7 +23,7 @@ "axios": "^1.2.1", "countup.js": "^2.3.2", "cropperjs": "^1.5.13", - "e-icon-picker": "^2.1.0", + "e-icon-picker": "^2.2.0", "echarts": "^5.4.1", "echarts-gl": "^2.0.9", "echarts-wordcloud": "^2.1.0", @@ -33,6 +33,7 @@ "js-cookie": "^3.0.1", "js-table2excel": "^1.0.3", "jsplumb": "^2.15.6", + "lodash-es": "^4.17.21", "mitt": "^3.0.0", "nprogress": "^0.2.0", "pinia": "^2.0.28", diff --git a/web/src/layout/logo/index.vue b/web/src/layout/logo/index.vue index 99bf7da..1a656bb 100644 --- a/web/src/layout/logo/index.vue +++ b/web/src/layout/logo/index.vue @@ -14,7 +14,7 @@ import { storeToRefs } from 'pinia'; import { useThemeConfig } from '/@/stores/themeConfig'; import logoMini from '/@/assets/logo-mini.svg'; import { SystemConfigStore } from "/@/stores/systemConfig"; -import _ from "lodash"; +import _ from "lodash-es"; // 定义变量内容 const storesThemeConfig = useThemeConfig(); const { themeConfig } = storeToRefs(storesThemeConfig); diff --git a/web/src/views/system/login/index.vue b/web/src/views/system/login/index.vue index 7915b64..bb442bf 100644 --- a/web/src/views/system/login/index.vue +++ b/web/src/views/system/login/index.vue @@ -79,7 +79,7 @@ import { getBaseURL } from "/@/utils/baseUrl"; const Account = defineAsyncComponent(() => import('/@/views/system/login/component/account.vue')); const Mobile = defineAsyncComponent(() => import('/@/views/system/login/component/mobile.vue')); const Scan = defineAsyncComponent(() => import('/@/views/system/login/component/scan.vue')); -import _ from "lodash"; +import _ from "lodash-es"; // 定义变量内容 const storesThemeConfig = useThemeConfig(); From 5bd57232d8cc584dd96bbdad54f31c8839f08d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Mon, 18 Mar 2024 21:22:22 +0800 Subject: [PATCH 04/30] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96docker=E9=83=A8?= =?UTF-8?q?=E7=BD=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/conf/env.example.py | 4 +++- docker-compose.yml | 4 ++-- docker_env/django/Dockerfile | 2 +- docker_env/mysql/conf.d/my.cnf | 6 +++--- init.sh | 31 +++++++++++++++++++++++++++++++ 5 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 init.sh diff --git a/backend/conf/env.example.py b/backend/conf/env.example.py index bf015db..3d1db25 100644 --- a/backend/conf/env.example.py +++ b/backend/conf/env.example.py @@ -21,13 +21,15 @@ DATABASE_PORT = 3306 # # 数据库用户名 DATABASE_USER = "root" # # 数据库密码 -DATABASE_PASSWORD = "DVADMIN3" +DATABASE_PASSWORD = 'DVADMIN3' # 表前缀 TABLE_PREFIX = "dvadmin_" # ================================================= # # ******** redis配置,无redis 可不进行配置 ******** # # ================================================= # +REDIS_DB = 1 +CELERY_BROKER_DB = 3 REDIS_PASSWORD = 'DVADMIN3' REDIS_HOST = '127.0.0.1' REDIS_URL = f'redis://:{REDIS_PASSWORD or ""}@{REDIS_HOST}:6379' diff --git a/docker-compose.yml b/docker-compose.yml index c08a0ef..70f9271 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -50,7 +50,7 @@ services: ports: - "3306:3306" environment: - MYSQL_ROOT_PASSWORD: "DVADMIN3" + MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD} MYSQL_DATABASE: "django-vue3-admin" TZ: Asia/Shanghai command: @@ -101,7 +101,7 @@ services: - "6379:6379" sysctls: # 设置容器中的内核参数 - net.core.somaxconn=1024 - command: /bin/sh -c "echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf && redis-server /etc/redis/redis.conf --appendonly yes --requirepass DVADMIN3" # 指定配置文件并开启持久化 + command: /bin/sh -c "echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf && redis-server /etc/redis/redis.conf --appendonly yes --requirepass ${MYSQL_PASSWORD}" # 指定配置文件并开启持久化 privileged: true # 使用该参数,container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限 networks: network: diff --git a/docker_env/django/Dockerfile b/docker_env/django/Dockerfile index 7acd383..427ed0c 100644 --- a/docker_env/django/Dockerfile +++ b/docker_env/django/Dockerfile @@ -3,7 +3,7 @@ WORKDIR /backend COPY ./backend/ . RUN ls ./conf/ RUN awk 'BEGIN { cmd="cp -i ./conf/env.example.py ./conf/env.py "; print "n" |cmd; }' -RUN sed -i "s|DATABASE_HOST = "127.0.0.1"|DATABASE_HOST = '177.10.0.1'|g" ./conf/env.py +RUN sed -i "s|DATABASE_HOST = '127.0.0.1'|DATABASE_HOST = '177.10.0.1'|g" ./conf/env.py RUN sed -i "s|REDIS_HOST = '127.0.0.1'|REDIS_HOST = '177.10.0.1'|g" ./conf/env.py RUN python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ -r requirements.txt CMD ["/backend/docker_start.sh"] diff --git a/docker_env/mysql/conf.d/my.cnf b/docker_env/mysql/conf.d/my.cnf index b9525ed..469af8b 100644 --- a/docker_env/mysql/conf.d/my.cnf +++ b/docker_env/mysql/conf.d/my.cnf @@ -1,7 +1,7 @@ [mysql] #设置mysql客户端默认字符集 default-character-set=utf8 -socket=/var/run/mysql/mysql.sock +socket=/var/lib/mysql/mysql.sock [mysqld] @@ -9,7 +9,7 @@ socket=/var/run/mysql/mysql.sock #mysql5.7以后的不兼容问题处理 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES datadir=/var/lib/mysql -socket=/var/run/mysql/mysql.sock +socket=/var/lib/mysql/mysql.sock # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 @@ -30,4 +30,4 @@ default-time_zone='+8:00' [mysqld_safe] log-error=/var/log/mariadb/mariadb.log -pid-file=/var/run/mariadb/mariadb.pid +pid-file=/var/lib/mariadb/mariadb.pid diff --git a/init.sh b/init.sh new file mode 100644 index 0000000..8c377ed --- /dev/null +++ b/init.sh @@ -0,0 +1,31 @@ +#!/bin/bash +ENV_FILE=".env" +# 检查 .env 文件是否存在 +if [ -f "$ENV_FILE" ]; then + echo "$ENV_FILE 文件已存在。" +else + # 生成MYSQL随机密码 + MYSQL_PASSWORD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 18) + echo "MYSQL_PASSWORD=$MYSQL_PASSWORD" >> "$ENV_FILE" + echo "MYSQL随机密码已生成并写入 $ENV_FILE 文件。" + # 生成REDIS随机密码 + REDIS_PASSWORD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 12) + # 将密码写入 .env 文件 + echo "REDIS_PASSWORD=$REDIS_PASSWORD" >> "$ENV_FILE" + echo "REDIS随机密码已生成并写入 $ENV_FILE 文件。" + + awk 'BEGIN { cmd="cp -i ./backend/conf/env.example.py ./backend/conf/env.py "; print "n" |cmd; }' + sed -i "s|DATABASE_HOST = '127.0.0.1'|DATABASE_HOST = '177.10.0.13'|g" ./backend/conf/env.py + sed -i "s|REDIS_HOST = '127.0.0.1'|REDIS_HOST = '177.10.0.15'|g" ./backend/conf/env.py + sed -i "s|DATABASE_PASSWORD = 'DVADMIN3'|DATABASE_PASSWORD = '$MYSQL_PASSWORD'|g" ./backend/conf/env.py + sed -i "s|REDIS_PASSWORD = 'DVADMIN3'|REDIS_PASSWORD = '$REDIS_PASSWORD'|g" ./backend/conf/env.py + echo "初始化密码创建成功" +fi + +docker-compose up -d +docker exec dvadmin3-django python manage.py makemigrations +docker exec dvadmin3-django python manage.py migrate +docker exec dvadmin3-django python manage.py init +echo "欢迎使用dvadmin3项目" +echo "登录地址:http://ip:8080" +echo "如访问不到,请检查防火墙配置" From 93cdd46e64c85d91390c8c41351bfe144ca20e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Mon, 18 Mar 2024 22:17:00 +0800 Subject: [PATCH 05/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG:=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E9=A1=B5=E9=9D=A2=E7=BC=93=E5=AD=98=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/views/system/demo/crud.tsx | 373 +++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 web/src/views/system/demo/crud.tsx diff --git a/web/src/views/system/demo/crud.tsx b/web/src/views/system/demo/crud.tsx new file mode 100644 index 0000000..cb6d0ac --- /dev/null +++ b/web/src/views/system/demo/crud.tsx @@ -0,0 +1,373 @@ +import * as api from './api'; +import { + UserPageQuery, + AddReq, + DelReq, + EditReq, + CreateCrudOptionsProps, + CreateCrudOptionsRet, + dict +} from '@fast-crud/fast-crud'; +import {commonCrudConfig} from "/@/utils/commonCrud"; +import {computed,shallowRef} from "vue"; +import dvaSelect from "/@/components/dvaSelect/index.vue"; +export const createCrudOptions = function ({ + crudExpose, + isEcharts, + initChart + }: CreateCrudOptionsProps): CreateCrudOptionsRet { + const pageRequest = async (query: UserPageQuery) => { + return await api.GetList(query); + }; + const editRequest = async ({form, row}: EditReq) => { + form.id = row.id; + return await api.UpdateObj(form); + }; + const delRequest = async ({row}: DelReq) => { + return await api.DelObj(row.id); + }; + const addRequest = async ({form}: AddReq) => { + return await api.AddObj(form); + }; + return { + crudOptions: { + request: { + pageRequest, + addRequest, + editRequest, + delRequest, + }, + actionbar: { + buttons: { + add: { + show: true, + }, + showEcharts: { + type: 'warning', + text: computed(() => { + return isEcharts.value ? '隐藏图表' : '显示图表' + }), + click: () => { + isEcharts.value = !isEcharts.value; + } + } + }, + }, + rowHandle: { + fixed: 'right', + width: 100, + buttons: { + view: { + type: 'text', + }, + edit: { + show: false, + }, + remove: { + show: false, + }, + }, + }, + columns: { + _index: { + title: '序号', + form: {show: false}, + column: { + //type: 'index', + align: 'center', + width: '70px', + columnSetDisabled: true, //禁止在列设置中选择 + formatter: (context) => { + //计算序号,你可以自定义计算规则,此处为翻页累加 + let index = context.index ?? 1; + let pagination = crudExpose!.crudBinding.value.pagination; + return ((pagination!.currentPage ?? 1) - 1) * pagination!.pageSize + index + 1; + }, + }, + }, + search: { + title: '关键词', + column: { + show: false, + }, + search: { + show: true, + component: { + props: { + clearable: true, + }, + placeholder: '请输入关键词', + }, + }, + form: { + show: false, + component: { + props: { + clearable: true, + }, + }, + }, + }, + username: { + title: '测试自定义组件', + dict:dict({ + url:'/api/system/role/', + label:'name', + value:'id' + }), + form: { + component: { + //局部引用子表格,要用shallowRef包裹 + name: shallowRef(dvaSelect), + } + } + }, + // username: { + // title: '登录用户名', + // search: { + // disabled: false, + // }, + // type: 'input', + // column: { + // minWidth: 120, + // }, + // form: { + // disabled: true, + // component: { + // placeholder: '请输入登录用户名', + // }, + // }, + // }, + ip: { + title: '登录ip', + search: { + disabled: false, + }, + type: 'input', + column: { + minWidth: 120, + }, + form: { + disabled: true, + component: { + placeholder: '请输入登录ip', + }, + }, + }, + isp: { + title: '运营商', + search: { + disabled: true, + }, + disabled: true, + type: 'input', + column: { + minWidth: 120, + }, + form: { + component: { + placeholder: '请输入运营商', + }, + }, + }, + continent: { + title: '大州', + type: 'input', + column: { + minWidth: 90, + }, + form: { + disabled: true, + component: { + placeholder: '请输入大州', + }, + }, + component: {props: {color: 'auto'}}, // 自动染色 + }, + country: { + title: '国家', + type: 'input', + column: { + minWidth: 90, + }, + form: { + component: { + placeholder: '请输入国家', + }, + }, + component: {props: {color: 'auto'}}, // 自动染色 + }, + province: { + title: '省份', + type: 'input', + column: { + minWidth: 80, + }, + form: { + component: { + placeholder: '请输入省份', + }, + }, + component: {props: {color: 'auto'}}, // 自动染色 + }, + city: { + title: '城市', + type: 'input', + column: { + minWidth: 80, + }, + form: { + component: { + placeholder: '请输入城市', + }, + }, + component: {props: {color: 'auto'}}, // 自动染色 + }, + district: { + title: '县区', + key: '', + type: 'input', + column: { + minWidth: 80, + }, + form: { + component: { + placeholder: '请输入县区', + }, + }, + component: {props: {color: 'auto'}}, // 自动染色 + }, + area_code: { + title: '区域代码', + type: 'input', + column: { + minWidth: 90, + }, + form: { + component: { + placeholder: '请输入区域代码', + }, + }, + component: {props: {color: 'auto'}}, // 自动染色 + }, + country_english: { + title: '英文全称', + type: 'input', + column: { + minWidth: 120, + }, + form: { + component: { + placeholder: '请输入英文全称', + }, + }, + component: {props: {color: 'auto'}}, // 自动染色 + }, + country_code: { + title: '简称', + type: 'input', + column: { + minWidth: 100, + }, + form: { + component: { + placeholder: '请输入简称', + }, + }, + component: {props: {color: 'auto'}}, // 自动染色 + }, + longitude: { + title: '经度', + type: 'input', + disabled: true, + column: { + minWidth: 100, + }, + form: { + component: { + placeholder: '请输入经度', + }, + }, + component: {props: {color: 'auto'}}, // 自动染色 + }, + latitude: { + title: '纬度', + type: 'input', + disabled: true, + column: { + minWidth: 100, + }, + form: { + component: { + placeholder: '请输入纬度', + }, + }, + component: {props: {color: 'auto'}}, // 自动染色 + }, + login_type: { + title: '登录类型', + type: 'dict-select', + search: { + disabled: false, + }, + dict: dict({ + data: [ + {label: '普通登录', value: 1}, + {label: '微信扫码登录', value: 2}, + ], + }), + column: { + minWidth: 120, + }, + form: { + component: { + placeholder: '请选择登录类型', + }, + }, + }, + os: { + title: '操作系统', + type: 'input', + column: { + minWidth: 120, + }, + form: { + component: { + placeholder: '请输入操作系统', + }, + }, + }, + browser: { + title: '浏览器名', + type: 'input', + column: { + minWidth: 120, + }, + form: { + component: { + placeholder: '请输入浏览器名', + }, + }, + }, + agent: { + title: 'agent信息', + disabled: true, + type: 'input', + column: { + minWidth: 120, + }, + form: { + component: { + placeholder: '请输入agent信息', + }, + }, + }, + ...commonCrudConfig({ + create_datetime: { + search: true + } + }) + }, + }, + }; +}; From 18b44e2aa46a0b42bd402003e4db9c54fe0eb97b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Mon, 18 Mar 2024 22:21:58 +0800 Subject: [PATCH 06/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG:=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E9=A1=B5=E9=9D=A2=E7=BC=93=E5=AD=98=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dvadmin_form_flow/install-render.js | 46 ++++++++++++ .../plugins/dvadmin_form_flow/install.js | 73 +++++++++++++++++++ .../plugins/dvadmin_form_flow/src/index.ts | 29 ++++++++ web/src/views/system/demo/api.ts | 41 +++++++++++ web/vite.config.ts | 1 + 5 files changed, 190 insertions(+) create mode 100644 web/src/views/plugins/dvadmin_form_flow/install-render.js create mode 100644 web/src/views/plugins/dvadmin_form_flow/install.js create mode 100644 web/src/views/plugins/dvadmin_form_flow/src/index.ts create mode 100644 web/src/views/system/demo/api.ts diff --git a/web/src/views/plugins/dvadmin_form_flow/install-render.js b/web/src/views/plugins/dvadmin_form_flow/install-render.js new file mode 100644 index 0000000..bd79ece --- /dev/null +++ b/web/src/views/plugins/dvadmin_form_flow/install-render.js @@ -0,0 +1,46 @@ +import axios from 'axios' + +import VFormRender from '@/components/form-render/index.vue' +import ContainerItems from '@/components/form-render/container-item/index' + +import {registerIcon} from '@/utils/el-icons' +import 'virtual:svg-icons-register' +import '@/iconfont/iconfont.css' + +import { installI18n } from '@/utils/i18n' +import { loadExtension } from '@/extension/extension-loader' + +VFormRender.install = function (app) { + installI18n(app) + loadExtension(app) + + app.use(ContainerItems) + registerIcon(app) + app.component(VFormRender.name, VFormRender) +} + +const components = [ + VFormRender +] + +const install = (app) => { + installI18n(app) + loadExtension(app) + + app.use(ContainerItems) + registerIcon(app) + components.forEach(component => { + app.component(component.name, component) + }) + + window.axios = axios +} + +if (typeof window !== 'undefined' && window.Vue) { /* scriptʽʱֵaxios */ + //window.axios = axios +} + +export default { + install, + VFormRender +} diff --git a/web/src/views/plugins/dvadmin_form_flow/install.js b/web/src/views/plugins/dvadmin_form_flow/install.js new file mode 100644 index 0000000..02154d4 --- /dev/null +++ b/web/src/views/plugins/dvadmin_form_flow/install.js @@ -0,0 +1,73 @@ +import axios from 'axios' + +import VFormDesigner from '@/components/form-designer/index.vue' +import VFormRender from '@/components/form-render/index.vue' + +import Draggable from '@/../lib/vuedraggable/dist/vuedraggable.umd.js' +import {registerIcon} from '@/utils/el-icons' +import 'virtual:svg-icons-register' +import '@/iconfont/iconfont.css' + +import ContainerWidgets from '@/components/form-designer/form-widget/container-widget/index' +import ContainerItems from '@/components/form-render/container-item/index' + +import { addDirective } from '@/utils/directive' +import { installI18n } from '@/utils/i18n' +import { loadExtension } from '@/extension/extension-loader' + + +VFormDesigner.install = function (app) { + addDirective(app) + installI18n(app) + loadExtension(app) + + app.use(ContainerWidgets) + app.use(ContainerItems) + + registerIcon(app) + app.component('draggable', Draggable) + app.component(VFormDesigner.name, VFormDesigner) +} + +VFormRender.install = function (app) { + installI18n(app) + loadExtension(app) + + app.use(ContainerItems) + + registerIcon(app) + app.component(VFormRender.name, VFormRender) +} + +const components = [ + VFormDesigner, + VFormRender +] + +const install = (app) => { + addDirective(app) + installI18n(app) + loadExtension(app) + + app.use(ContainerWidgets) + app.use(ContainerItems) + + registerIcon(app) + app.component('draggable', Draggable) + + components.forEach(component => { + app.component(component.name, component) + }) + + window.axios = axios +} + +if (typeof window !== 'undefined' && window.Vue) { /* scriptʽʱֵaxios */ + //window.axios = axios +} + +export default { + install, + VFormDesigner, + VFormRender +} diff --git a/web/src/views/plugins/dvadmin_form_flow/src/index.ts b/web/src/views/plugins/dvadmin_form_flow/src/index.ts new file mode 100644 index 0000000..c57cc05 --- /dev/null +++ b/web/src/views/plugins/dvadmin_form_flow/src/index.ts @@ -0,0 +1,29 @@ +// +import DVAFormDesigner from './components/DVAFormDesigner.vue' + +// 浽һ +const components = [ + DVAFormDesigner +] + +// install +const install = function (Vue) { + + if (install.installed) return + install.installed = true + // бעȫ + components.map(component => { + Vue.component(component.name, component) //component.name ˴ʹõvueļе name + }) +} + +if (typeof window !== 'undefined' && window.Vue) { + install(window.Vue) +} + +export default { + // Ķ߱һ install + install, + // б + ...components +} diff --git a/web/src/views/system/demo/api.ts b/web/src/views/system/demo/api.ts new file mode 100644 index 0000000..defefc4 --- /dev/null +++ b/web/src/views/system/demo/api.ts @@ -0,0 +1,41 @@ +import { request } from '/@/utils/service'; +import { UserPageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud'; + +export const apiPrefix = '/api/system/login_log/'; +export function GetList(query: UserPageQuery) { + return request({ + url: apiPrefix, + method: 'get', + params: query, + }); +} +export function GetObj(id: InfoReq) { + return request({ + url: apiPrefix + id, + method: 'get', + }); +} + +export function AddObj(obj: AddReq) { + return request({ + url: apiPrefix, + method: 'post', + data: obj, + }); +} + +export function UpdateObj(obj: EditReq) { + return request({ + url: apiPrefix + obj.id + '/', + method: 'put', + data: obj, + }); +} + +export function DelObj(id: DelReq) { + return request({ + url: apiPrefix + id + '/', + method: 'delete', + data: { id }, + }); +} diff --git a/web/vite.config.ts b/web/vite.config.ts index 02c966a..e9c24b3 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -12,6 +12,7 @@ const alias: Record = { '/@': pathResolve('./src/'), '@views': pathResolve('./src/views'), 'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js', + '@dvaformflow':pathResolve('./src/viwes/plugins/dvaadmin_form_flow/src/') }; const viteConfig = defineConfig((mode: ConfigEnv) => { From cdf3d7cab829612698ae7411ede0ebc2f735223e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Sat, 30 Mar 2024 21:41:59 +0800 Subject: [PATCH 07/30] =?UTF-8?q?=E9=83=A8=E7=BD=B2=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 1 + docker_env/nginx/my.conf | 20 +++++++++++++++++++- docker_env/web/Dockerfile | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 70f9271..e38806e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,7 @@ services: TZ: Asia/Shanghai volumes: - ./docker_env/nginx/my.conf:/etc/nginx/conf.d/my.conf + - ./backend/media:/backend/media expose: - "8080" restart: always diff --git a/docker_env/nginx/my.conf b/docker_env/nginx/my.conf index e1db0b7..178d979 100644 --- a/docker_env/nginx/my.conf +++ b/docker_env/nginx/my.conf @@ -29,5 +29,23 @@ server { real_ip_header X-Forwarded-For; rewrite ^/api/(.*)$ /$1 break; #重写 proxy_pass http://177.10.0.12:8000/; # 设置代理服务器的协议和地址 - } + } + location /media { + alias /backend/media; + expires 7d; + gzip on; + gzip_min_length 1k; + gzip_comp_level 2; + gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; + gzip_vary on; + } + location /api/media { + alias /backend/media; + expires 7d; + gzip on; + gzip_min_length 1k; + gzip_comp_level 2; + gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; + gzip_vary on; + } } diff --git a/docker_env/web/Dockerfile b/docker_env/web/Dockerfile index 9d465d1..dc0cdb8 100644 --- a/docker_env/web/Dockerfile +++ b/docker_env/web/Dockerfile @@ -1,7 +1,7 @@ FROM registry.cn-zhangjiakou.aliyuncs.com/dvadmin-pro/dvadmin3-base-web:16.19-alpine WORKDIR /web/ COPY web/. . -RUN yarn install --registry=https://registry.npm.taobao.org +RUN yarn install --registry=https://registry.npmmirror.com RUN yarn build FROM nginx:alpine From b60489369733aaa7479bafdc45f094335e2e92e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Sat, 30 Mar 2024 21:45:08 +0800 Subject: [PATCH 08/30] =?UTF-8?q?redis=20=E9=BB=98=E8=AE=A4=E5=AF=86?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index e38806e..7d3f35d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -102,7 +102,7 @@ services: - "6379:6379" sysctls: # 设置容器中的内核参数 - net.core.somaxconn=1024 - command: /bin/sh -c "echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf && redis-server /etc/redis/redis.conf --appendonly yes --requirepass ${MYSQL_PASSWORD}" # 指定配置文件并开启持久化 + command: /bin/sh -c "echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf && redis-server /etc/redis/redis.conf --appendonly yes --requirepass ${REDIS_PASSWORD}" # 指定配置文件并开启持久化 privileged: true # 使用该参数,container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限 networks: network: From 665e5ce092e177b6c210b57d82102ed79bb2ebb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Sat, 30 Mar 2024 21:47:24 +0800 Subject: [PATCH 09/30] =?UTF-8?q?docker-compose.yml=20=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7d3f35d..8fd739f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,7 @@ services: TZ: Asia/Shanghai volumes: - ./docker_env/nginx/my.conf:/etc/nginx/conf.d/my.conf - - ./backend/media:/backend/media + - ./backend/media:/backend/media expose: - "8080" restart: always From 28a96de9288ff93fb02b2c7d79e31f901e7975ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Sun, 31 Mar 2024 01:02:25 +0800 Subject: [PATCH 10/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8E=88=E6=9D=83?= =?UTF-8?q?=E6=97=B6=E6=97=A0=E5=88=97=E6=9D=83=E9=99=90=E6=8A=A5=E9=94=99?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/views/role_menu_button_permission.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/dvadmin/system/views/role_menu_button_permission.py b/backend/dvadmin/system/views/role_menu_button_permission.py index 745daee..07fd917 100644 --- a/backend/dvadmin/system/views/role_menu_button_permission.py +++ b/backend/dvadmin/system/views/role_menu_button_permission.py @@ -232,12 +232,12 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): role_menu_permission_list.append(RoleMenuPermission(role_id=pk, menu_id=d["id"])) RoleMenuPermission.objects.bulk_create(role_menu_permission_list) # RoleMenuPermission.objects.create(role_id=pk, menu_id=menu.get('id')) - for btn in menu.get('btns'): + for btn in menu.get('btns', []): if btn.get('isCheck'): data_range = btn.get('data_range',0) or 0 instance = RoleMenuButtonPermission.objects.create(role_id=pk, menu_button_id=btn.get('id'),data_range=data_range) instance.dept.set(btn.get('dept',[])) - for col in menu.get('columns'): + for col in menu.get('columns', []): FieldPermission.objects.update_or_create(role_id=pk,field_id=col.get('id'),is_query=col.get('is_query'),is_create=col.get('is_create'),is_update=col.get('is_update')) return DetailResponse(msg="授权成功") From 94767d8bc14ebaa0be0358d43dda9d1a29f81fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BC=BA?= <1206709430@qq.com> Date: Thu, 4 Apr 2024 23:27:36 +0800 Subject: [PATCH 11/30] =?UTF-8?q?feat:=20=E4=BF=AE=E5=A4=8De-icon-picker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/package.json b/web/package.json index ac89be4..0a2d576 100644 --- a/web/package.json +++ b/web/package.json @@ -23,7 +23,7 @@ "axios": "^1.2.1", "countup.js": "^2.3.2", "cropperjs": "^1.5.13", - "e-icon-picker": "^2.2.0", + "e-icon-picker": "2.1.1", "echarts": "^5.4.1", "echarts-gl": "^2.0.9", "echarts-wordcloud": "^2.1.0", From a6e20d88da2003d088c7053760e6b15e5c81bff1 Mon Sep 17 00:00:00 2001 From: china_ahhui Date: Thu, 11 Apr 2024 16:57:14 +0800 Subject: [PATCH 12/30] =?UTF-8?q?init=E5=91=BD=E4=BB=A4=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8F=AF=E6=8C=87=E5=AE=9Aapp=E8=BF=9B=E8=A1=8C=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=EF=BC=8C'python=20manage.py=20init=20-app=20?= =?UTF-8?q?app1=20app2=20...'=E6=88=96=20'python=20manage.py=20init=20-A?= =?UTF-8?q?=20app1=20app2=20...'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/management/commands/init.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/dvadmin/system/management/commands/init.py b/backend/dvadmin/system/management/commands/init.py index d7602e2..58154a8 100644 --- a/backend/dvadmin/system/management/commands/init.py +++ b/backend/dvadmin/system/management/commands/init.py @@ -22,6 +22,8 @@ class Command(BaseCommand): parser.add_argument("-Y", nargs="*") parser.add_argument("-n", nargs="*") parser.add_argument("-N", nargs="*") + parser.add_argument("-app", nargs="*") + parser.add_argument("-A", nargs="*") def handle(self, *args, **options): reset = False @@ -29,9 +31,10 @@ class Command(BaseCommand): reset = True if isinstance(options.get("n"), list) or isinstance(options.get("N"), list): reset = False - + assign_apps = options.get("app") or options.get("A") or [] for app in settings.INSTALLED_APPS: - + if assign_apps and app not in assign_apps: + continue try: exec( f""" From a03b14a32d20f9657ec371d776acfcb1ad85ebad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Thu, 9 May 2024 10:20:41 +0800 Subject: [PATCH 13/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG:=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8Ddemo=E7=BC=BA=E5=B0=91=E6=96=87=E4=BB=B6=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/settings.ts | 4 ++-- web/src/views/system/demo/crud.tsx | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/web/src/settings.ts b/web/src/settings.ts index 552352a..cbef494 100644 --- a/web/src/settings.ts +++ b/web/src/settings.ts @@ -21,10 +21,10 @@ export default { app.use(FastCrud, { //i18n, //i18n配置,可选,默认使用中文,具体用法请看demo里的 src/i18n/index.js 文件 // 此处配置公共的dictRequest(字典请求) - async dictRequest({dict}: any) { + async dictRequest({dict,url}: any) { const {isTree} = dict //根据dict的url,异步返回一个字典数组 - return await request({url: dict.url, params: dict.params || {}}).then((res: any) => { + return await request({url: url, params: dict.params || {}}).then((res: any) => { if (isTree) { return XEUtils.toArrayTree(res.data, {parentKey: 'parent'}) } diff --git a/web/src/views/system/demo/crud.tsx b/web/src/views/system/demo/crud.tsx index cb6d0ac..b18ce69 100644 --- a/web/src/views/system/demo/crud.tsx +++ b/web/src/views/system/demo/crud.tsx @@ -111,7 +111,9 @@ export const createCrudOptions = function ({ username: { title: '测试自定义组件', dict:dict({ - url:'/api/system/role/', + url({form}){ + return '/api/system/role/' + }, label:'name', value:'id' }), From 0d9ee1f4d4673f3f5418a7964e145f8a1d77a482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Thu, 9 May 2024 11:11:23 +0800 Subject: [PATCH 14/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.密码重置; 2.个人中心密码修改 --- backend/dvadmin/system/views/user.py | 16 +++++++++++----- web/src/views/system/personal/index.vue | 2 ++ web/src/views/system/user/api.ts | 8 ++++++++ web/src/views/system/user/crud.tsx | 8 +++++++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/backend/dvadmin/system/views/user.py b/backend/dvadmin/system/views/user.py index 535d643..d1470fe 100644 --- a/backend/dvadmin/system/views/user.py +++ b/backend/dvadmin/system/views/user.py @@ -320,15 +320,17 @@ class UserViewSet(CustomModelViewSet): """密码修改""" data = request.data old_pwd = data.get("oldPassword") + print(old_pwd) new_pwd = data.get("newPassword") new_pwd2 = data.get("newPassword2") if old_pwd is None or new_pwd is None or new_pwd2 is None: return ErrorResponse(msg="参数不能为空") if new_pwd != new_pwd2: return ErrorResponse(msg="两次密码不匹配") - verify_password = check_password(old_pwd, self.request.user.password) + verify_password = check_password(old_pwd, request.user.password) if not verify_password: - verify_password = check_password(hashlib.md5(old_pwd.encode(encoding='UTF-8')).hexdigest(), self.request.user.password) + old_pwd_md5 = hashlib.md5(old_pwd.encode(encoding='UTF-8')).hexdigest() + verify_password = check_password(str(old_pwd_md5), request.user.password) if verify_password: request.user.password = make_password(hashlib.md5(new_pwd.encode(encoding='UTF-8')).hexdigest()) request.user.save() @@ -337,11 +339,15 @@ class UserViewSet(CustomModelViewSet): return ErrorResponse(msg="旧密码不正确") @action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated]) - def reset_to_default_password(self, request, *args, **kwargs): + def reset_to_default_password(self, request,pk): """恢复默认密码""" - instance = Users.objects.filter(id=kwargs.get("pk")).first() + if not self.request.user.is_superuser: + return ErrorResponse(msg="只允许超级管理员对其进行密码重置") + instance = Users.objects.filter(id=pk).first() if instance: - instance.set_password(dispatch.get_system_config_values("base.default_password")) + default_password = dispatch.get_system_config_values("base.default_password") + md5_pwd = hashlib.md5(default_password.encode(encoding='UTF-8')).hexdigest() + instance.password = make_password(md5_pwd) instance.save() return DetailResponse(data=None, msg="密码重置成功") else: diff --git a/web/src/views/system/personal/index.vue b/web/src/views/system/personal/index.vue index b61222d..6eb76fd 100644 --- a/web/src/views/system/personal/index.vue +++ b/web/src/views/system/personal/index.vue @@ -182,6 +182,7 @@ import { useRouter } from 'vue-router'; import { useUserInfo } from '/@/stores/userInfo'; import { successMessage } from '/@/utils/message'; import {dictionary} from "/@/utils/dictionary"; +import {Md5} from "ts-md5"; const router = useRouter(); // 头像裁剪组件 @@ -330,6 +331,7 @@ const passwordRules = reactive({ * 重新设置密码 */ const settingPassword = () => { + console.log(Md5.hashStr('admin123456')) userPasswordFormRef.value.validate((valid) => { if (valid) { api.UpdatePassword(userPasswordInfo).then((res: any) => { diff --git a/web/src/views/system/user/api.ts b/web/src/views/system/user/api.ts index 84d4b68..78a15ec 100644 --- a/web/src/views/system/user/api.ts +++ b/web/src/views/system/user/api.ts @@ -56,3 +56,11 @@ export function exportData(params:any){ method: 'get' }) } + + +export function resetToDefaultPassword(id:any){ + return request({ + url: apiPrefix + id + '/reset_to_default_password/', + method: 'put' + }) +} diff --git a/web/src/views/system/user/crud.tsx b/web/src/views/system/user/crud.tsx index b8d2e9c..5f6f0c6 100644 --- a/web/src/views/system/user/crud.tsx +++ b/web/src/views/system/user/crud.tsx @@ -37,10 +37,15 @@ export const createCrudOptions = function ({crudExpose}: CreateCrudOptionsProps) return await api.exportData(query) } + const resetToDefaultPasswordRequest = async (row:EditReq)=>{ + await api.resetToDefaultPassword(row.id) + successMessage("重置密码成功") + } + const systemConfigStore = SystemConfigStore() const {systemConfig} = storeToRefs(systemConfigStore) const getSystemConfig = computed(() => { - console.log(systemConfig.value) + // console.log(systemConfig.value) return systemConfig.value }) @@ -108,6 +113,7 @@ export const createCrudOptions = function ({crudExpose}: CreateCrudOptionsProps) //@ts-ignore click: (ctx: any) => { const {row} = ctx; + resetToDefaultPasswordRequest(row) }, }, }, From e6f898bef47bc5de081c49d39bb2424fd2fa2256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Thu, 9 May 2024 11:20:41 +0800 Subject: [PATCH 15/30] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8F=98=E5=8C=96:=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/views/system/personal/index.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/web/src/views/system/personal/index.vue b/web/src/views/system/personal/index.vue index 6eb76fd..05b5d12 100644 --- a/web/src/views/system/personal/index.vue +++ b/web/src/views/system/personal/index.vue @@ -331,7 +331,6 @@ const passwordRules = reactive({ * 重新设置密码 */ const settingPassword = () => { - console.log(Md5.hashStr('admin123456')) userPasswordFormRef.value.validate((valid) => { if (valid) { api.UpdatePassword(userPasswordInfo).then((res: any) => { From 49d56f6378142d3dac39fdc5421ca8dc771bc84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Thu, 9 May 2024 11:24:33 +0800 Subject: [PATCH 16/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG:=20=E6=97=A0?= =?UTF-8?q?=E4=BB=BB=E4=BD=95=E8=8F=9C=E5=8D=95=E6=9D=83=E9=99=90=E6=97=B6?= =?UTF-8?q?,=E6=97=A0=E6=B3=95=E8=BF=9B=E5=85=A5=E9=A6=96=E9=A1=B5?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/router/backEnd.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/router/backEnd.ts b/web/src/router/backEnd.ts index d933798..0839c49 100644 --- a/web/src/router/backEnd.ts +++ b/web/src/router/backEnd.ts @@ -49,7 +49,7 @@ export async function initBackEndControlRoutes() { const res = await getBackEndControlRoutes(); // 无登录权限时,添加判断 // https://gitee.com/lyt-top/vue-next-admin/issues/I64HVO - if (res.data.length <= 0) return Promise.resolve(true); + // if (res.data.length <= 0) return Promise.resolve(true); // 处理路由(component),替换 dynamicRoutes(/@/router/route)第一个顶级 children 的路由 const {frameIn,frameOut} = handleMenu(res.data) dynamicRoutes[0].children = await backEndComponent(frameIn); From 767cbbe366510888ba1050ee16bba4990e549b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Fri, 10 May 2024 10:23:00 +0800 Subject: [PATCH 17/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG:=20=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=AE=A1=E7=90=86=E5=AF=BC=E5=85=A5=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/views/system/user/crud.tsx | 1 + web/src/views/system/user/index.vue | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/web/src/views/system/user/crud.tsx b/web/src/views/system/user/crud.tsx index 5f6f0c6..1e28bb8 100644 --- a/web/src/views/system/user/crud.tsx +++ b/web/src/views/system/user/crud.tsx @@ -78,6 +78,7 @@ export const createCrudOptions = function ({crudExpose}: CreateCrudOptionsProps) export: { text: "导出",//按钮文字 title: "导出",//鼠标停留显示的信息 + show: auth('user:Export'), click() { return exportRequest(crudExpose!.getSearchFormData()) } diff --git a/web/src/views/system/user/index.vue b/web/src/views/system/user/index.vue index b91b40f..4ea5033 100644 --- a/web/src/views/system/user/index.vue +++ b/web/src/views/system/user/index.vue @@ -31,7 +31,7 @@ From 3786b4123b7e246ca4faa99f14a55b6f7196de59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Tue, 21 May 2024 21:46:11 +0800 Subject: [PATCH 18/30] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8F=98=E5=8C=96:=20?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=8A=A0=E5=85=A5=E5=88=A4=E6=96=AD,?= =?UTF-8?q?=E8=B6=85=E8=BF=875=E6=AC=A1=E8=B4=A6=E5=8F=B7=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E4=B8=8D=E6=AD=A3=E7=A1=AE=E5=88=99=E9=94=81=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/models.py | 1 + backend/dvadmin/system/views/login.py | 50 ++++++++++++++++----------- backend/dvadmin/system/views/user.py | 16 ++++----- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py index 0e29403..e0e1841 100644 --- a/backend/dvadmin/system/models.py +++ b/backend/dvadmin/system/models.py @@ -70,6 +70,7 @@ class Users(CoreModel, AbstractUser): blank=True, help_text="关联部门", ) + login_error_count = models.IntegerField(default=0, verbose_name="登录错误次数", help_text="登录错误次数") objects = CustomUserManager() def set_password(self, raw_password): diff --git a/backend/dvadmin/system/views/login.py b/backend/dvadmin/system/views/login.py index 766a6c7..91beb15 100644 --- a/backend/dvadmin/system/views/login.py +++ b/backend/dvadmin/system/views/login.py @@ -86,28 +86,36 @@ class LoginSerializer(TokenObtainPairSerializer): user = Users.objects.get(username=attrs['username']) if not user.is_active: - raise CustomValidationError("账号被锁定") + raise CustomValidationError("账号已被锁定,联系管理员解锁") + try: + data = super().validate(attrs) + data["name"] = self.user.name + data["userId"] = self.user.id + data["avatar"] = self.user.avatar + data['user_type'] = self.user.user_type + dept = getattr(self.user, 'dept', None) + if dept: + data['dept_info'] = { + 'dept_id': dept.id, + 'dept_name': dept.name, - data = super().validate(attrs) - data["name"] = self.user.name - data["userId"] = self.user.id - data["avatar"] = self.user.avatar - data['user_type'] = self.user.user_type - dept = getattr(self.user, 'dept', None) - if dept: - data['dept_info'] = { - 'dept_id': dept.id, - 'dept_name': dept.name, - - } - role = getattr(self.user, 'role', None) - if role: - data['role_info'] = role.values('id', 'name', 'key') - request = self.context.get("request") - request.user = self.user - # 记录登录日志 - save_login_log(request=request) - return {"code": 2000, "msg": "请求成功", "data": data} + } + role = getattr(self.user, 'role', None) + if role: + data['role_info'] = role.values('id', 'name', 'key') + request = self.context.get("request") + request.user = self.user + # 记录登录日志 + save_login_log(request=request) + return {"code": 2000, "msg": "请求成功", "data": data} + except Exception as e: + user.login_error_count += 1 + if user.login_error_count >= 5: + user.is_active = False + raise CustomValidationError("账号已被锁定,联系管理员解锁") + user.save() + count = 5 - user.login_error_count + raise CustomValidationError(f"账号/密码错误;重试{count}次后将被锁定~") class LoginView(TokenObtainPairView): diff --git a/backend/dvadmin/system/views/user.py b/backend/dvadmin/system/views/user.py index d1470fe..c6c002e 100644 --- a/backend/dvadmin/system/views/user.py +++ b/backend/dvadmin/system/views/user.py @@ -115,14 +115,14 @@ class UserUpdateSerializer(CustomModelSerializer): ], ) - # password = serializers.CharField(required=False, allow_blank=True) - # mobile = serializers.CharField( - # max_length=50, - # validators=[ - # CustomUniqueValidator(queryset=Users.objects.all(), message="手机号必须唯一") - # ], - # allow_blank=True - # ) + def validate_is_active(self, value): + """ + 更改激活状态 + """ + print(111, value) + if value: + self.initial_data["login_error_count"] = 0 + return value def save(self, **kwargs): data = super().save(**kwargs) From e8d39d01508a69189c61ae37867e76f83214896a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Tue, 21 May 2024 21:48:58 +0800 Subject: [PATCH 19/30] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8F=98=E5=8C=96:=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8E=88=E6=9D=83=E7=AE=A1=E7=90=86=E7=9A=84?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/views/role_menu_button_permission.py | 6 +++++- web/src/views/system/user/crud.tsx | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/dvadmin/system/views/role_menu_button_permission.py b/backend/dvadmin/system/views/role_menu_button_permission.py index 07fd917..b86952c 100644 --- a/backend/dvadmin/system/views/role_menu_button_permission.py +++ b/backend/dvadmin/system/views/role_menu_button_permission.py @@ -238,7 +238,11 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): instance = RoleMenuButtonPermission.objects.create(role_id=pk, menu_button_id=btn.get('id'),data_range=data_range) instance.dept.set(btn.get('dept',[])) for col in menu.get('columns', []): - FieldPermission.objects.update_or_create(role_id=pk,field_id=col.get('id'),is_query=col.get('is_query'),is_create=col.get('is_create'),is_update=col.get('is_update')) + FieldPermission.objects.update_or_create(role_id=pk,field_id=col.get('id'),defaults={ + "is_query":col.get('is_query'), + "is_create":col.get('is_create'), + "is_update":col.get('is_update') + }) return DetailResponse(msg="授权成功") diff --git a/web/src/views/system/user/crud.tsx b/web/src/views/system/user/crud.tsx index 1e28bb8..7281525 100644 --- a/web/src/views/system/user/crud.tsx +++ b/web/src/views/system/user/crud.tsx @@ -349,7 +349,7 @@ export const createCrudOptions = function ({crudExpose}: CreateCrudOptionsProps) }, }, is_active: { - title: '锁定', + title: '状态', search: { show: true, }, From 91d15ec15be906c943b8f7d354426b532161d6cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Wed, 22 May 2024 21:47:58 +0800 Subject: [PATCH 20/30] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8F=98=E5=8C=96:=20?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E5=AF=86=E7=A0=81=E9=94=99=E8=AF=AF=E8=B6=85?= =?UTF-8?q?=E8=BF=875=E6=AC=A1=E8=BF=9B=E8=A1=8C=E5=B0=81=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/dvadmin/system/views/login.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/dvadmin/system/views/login.py b/backend/dvadmin/system/views/login.py index 91beb15..e04743c 100644 --- a/backend/dvadmin/system/views/login.py +++ b/backend/dvadmin/system/views/login.py @@ -107,6 +107,8 @@ class LoginSerializer(TokenObtainPairSerializer): request.user = self.user # 记录登录日志 save_login_log(request=request) + user.login_error_count = 0 + user.save() return {"code": 2000, "msg": "请求成功", "data": data} except Exception as e: user.login_error_count += 1 From 3720fbe4a01f3fc21ced571db327221c160d79e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Wed, 22 May 2024 21:50:42 +0800 Subject: [PATCH 21/30] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8F=98=E5=8C=96:=201?= =?UTF-8?q?.=E5=85=81=E8=AE=B8=E5=8A=A8=E6=80=81=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E7=BD=91=E7=AB=99=E5=B0=8F=E5=9B=BE=E6=A0=87;=202.=E5=85=81?= =?UTF-8?q?=E8=AE=B8=E5=8A=A8=E6=80=81=E4=BF=AE=E6=94=B9=E7=BD=91=E7=AB=99?= =?UTF-8?q?=E6=A0=87=E9=A2=98;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/fixtures/init_systemconfig.json | 28 ++++++++++++++ web/src/App.vue | 1 + web/src/utils/other.ts | 37 +++++++++++++++++-- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/backend/dvadmin/system/fixtures/init_systemconfig.json b/backend/dvadmin/system/fixtures/init_systemconfig.json index 543b83c..98c95cd 100644 --- a/backend/dvadmin/system/fixtures/init_systemconfig.json +++ b/backend/dvadmin/system/fixtures/init_systemconfig.json @@ -12,6 +12,34 @@ "placeholder": null, "setting": null, "children": [ + { + "parent": 10, + "title": "网页标题", + "key": "web_title", + "value": "DVAdmin", + "sort": 1, + "status": true, + "data_options": null, + "form_item_type": 0, + "rule": [], + "placeholder": "请输入网站标题", + "setting": null, + "children": [] + }, + { + "parent": 10, + "title": "网站小图标", + "key": "web_favicon", + "value": "", + "sort": 1, + "status": true, + "data_options": null, + "form_item_type": 0, + "rule": [], + "placeholder": "请输入网站小图标", + "setting": null, + "children": [] + }, { "parent": 10, "title": "开启验证码", diff --git a/web/src/App.vue b/web/src/App.vue index caa36ca..0de8738 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -87,6 +87,7 @@ watch( () => route.path, () => { other.useTitle(); + other.useFavicon(); if (!websocket.websocket) { //websockt 模块 try { diff --git a/web/src/utils/other.ts b/web/src/utils/other.ts index 08dd477..6e1033e 100644 --- a/web/src/utils/other.ts +++ b/web/src/utils/other.ts @@ -8,6 +8,7 @@ import { useThemeConfig } from '/@/stores/themeConfig'; import { i18n } from '/@/i18n/index'; import { Local } from '/@/utils/storage'; import { verifyUrl } from '/@/utils/toolsValidate'; +import {SystemConfigStore} from "/@/stores/systemConfig"; // 引入组件 const SvgIcon = defineAsyncComponent(() => import('/@/components/svgIcon/index.vue')); @@ -30,18 +31,43 @@ export function elSvg(app: App) { * @method const title = useTitle(); ==> title() */ export function useTitle() { - const stores = useThemeConfig(pinia); - const { themeConfig } = storeToRefs(stores); + const stores = SystemConfigStore(pinia); + const { systemConfig } = storeToRefs(stores); nextTick(() => { let webTitle = ''; - let globalTitle: string = themeConfig.value.globalTitle; + let globalTitle: string = systemConfig['base.web_title']; const { path, meta } = router.currentRoute.value; if (path === '/login') { webTitle = meta.title; } else { webTitle = setTagsViewNameI18n(router.currentRoute.value); } - document.title = `${webTitle} - ${globalTitle}` || globalTitle; + document.title = `${webTitle} - ${globalTitle}` || "DVAdmin"; + }); +} + +/*** + * 设置网站favicon图标 + */ +export function useFavicon() { + const stores = SystemConfigStore(pinia); + const { systemConfig } = storeToRefs(stores); + nextTick(() => { + const iconUrl = systemConfig.value['base.web_favicon'] + if(iconUrl){ + // 动态设置 favicon,这里假设 favicon 的 URL 是动态获取的或从变量中来 + const faviconUrl = `${iconUrl}?t=${new Date().getTime()}`; + const link = document.querySelector("link[rel~='icon']") as HTMLLinkElement; + if (!link) { + const newLink = document.createElement('link') as HTMLLinkElement; + newLink.rel = 'shortcut icon'; + newLink.href = faviconUrl; + document.head.appendChild(newLink); + } else { + link.href = faviconUrl; + } + } + }); } @@ -191,6 +217,9 @@ const other = { useTitle: () => { useTitle(); }, + useFavicon:()=>{ + useFavicon() + }, setTagsViewNameI18n(route: RouteToFrom) { return setTagsViewNameI18n(route); }, From 7ed699593c5f60fe1dd5a34d5e624365e9e59dff Mon Sep 17 00:00:00 2001 From: china_ahhui Date: Sun, 2 Jun 2024 11:28:34 +0800 Subject: [PATCH 22/30] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E6=96=87=E4=BB=B6=E4=BB=A5=E5=8F=8A=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E9=80=BB=E8=BE=91=EF=BC=88=E8=A7=92=E8=89=B2=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E5=92=8C=E8=A7=92=E8=89=B2=E8=8F=9C=E5=8D=95=E6=8C=89?= =?UTF-8?q?=E9=92=AE=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dvadmin/system/fixtures/initSerializer.py | 35 +++++++++++-------- .../init_rolemenubuttonpermission.json | 9 ++--- .../fixtures/init_rolemenupermission.json | 10 +++--- backend/dvadmin/system/fixtures/initialize.py | 4 +-- 4 files changed, 31 insertions(+), 27 deletions(-) diff --git a/backend/dvadmin/system/fixtures/initSerializer.py b/backend/dvadmin/system/fixtures/initSerializer.py index a264ed7..9ed094f 100644 --- a/backend/dvadmin/system/fixtures/initSerializer.py +++ b/backend/dvadmin/system/fixtures/initSerializer.py @@ -175,22 +175,24 @@ class RoleMenuInitSerializer(CustomModelSerializer): """ 初始化角色菜单(用于生成初始化json文件) """ - role_key = serializers.CharField(max_length=100, required=True) - menu_component_name = serializers.CharField(max_length=100, required=True) + role__key = serializers.CharField(max_length=100, required=True) + menu__web_path = serializers.CharField(max_length=100, required=True) + menu__component_name = serializers.CharField(max_length=100, required=True, allow_blank=True) def create(self, validated_data): init_data = self.initial_data - validated_data.pop('menu_component_name') - validated_data.pop('role_key') - role_id = Role.objects.filter(key=init_data['role_key']).first() - menu_id = Menu.objects.filter(component_name=init_data['menu_component_name']).first() + validated_data.pop('menu__web_path') + validated_data.pop('menu__component_name') + validated_data.pop('role__key') + role_id = Role.objects.filter(key=init_data['role__key']).first() + menu_id = Menu.objects.filter(web_path=init_data['menu__web_path'], component_name=init_data['menu__component_name']).first() validated_data['role'] = role_id validated_data['menu'] = menu_id return super().create(validated_data) class Meta: model = RoleMenuPermission - fields = ['role_key', 'menu_component_name', 'creator', 'dept_belong_id'] + fields = ['role__key', 'menu__web_path', 'menu__component_name', 'creator', 'dept_belong_id'] read_only_fields = ["id"] extra_kwargs = { 'role': {'required': False}, @@ -204,25 +206,30 @@ class RoleMenuButtonInitSerializer(CustomModelSerializer): """ 初始化角色菜单按钮(用于生成初始化json文件) """ - role_key = serializers.CharField(max_length=100, required=True) - menu_button_value = serializers.CharField(max_length=100, required=True) + role__key = serializers.CharField(max_length=100, required=True) + menu_button__value = serializers.CharField(max_length=100, required=True) data_range = serializers.CharField(max_length=100, required=False) def create(self, validated_data): init_data = self.initial_data - validated_data.pop('menu_button_value') - validated_data.pop('role_key') - role_id = Role.objects.filter(key=init_data['role_key']).first() - menu_button_id = MenuButton.objects.filter(value=init_data['menu_button_value']).first() + validated_data.pop('menu_button__value') + validated_data.pop('role__key') + role_id = Role.objects.filter(key=init_data['role__key']).first() + menu_button_id = MenuButton.objects.filter(value=init_data['menu_button__value']).first() validated_data['role'] = role_id validated_data['menu_button'] = menu_button_id instance = super().create(validated_data) instance.dept.set([]) return instance + def save(self, **kwargs): + if self.instance and self.initial_data.get('reset'): + return super().save(**kwargs) + return self.instance + class Meta: model = RoleMenuButtonPermission - fields = ['role_key', 'menu_button_value', 'data_range', 'dept', 'creator', 'dept_belong_id'] + fields = ['role__key', 'menu_button__value', 'data_range', 'dept', 'creator', 'dept_belong_id'] read_only_fields = ["id"] extra_kwargs = { 'role': {'required': False}, diff --git a/backend/dvadmin/system/fixtures/init_rolemenubuttonpermission.json b/backend/dvadmin/system/fixtures/init_rolemenubuttonpermission.json index d4b4700..8057cd8 100644 --- a/backend/dvadmin/system/fixtures/init_rolemenubuttonpermission.json +++ b/backend/dvadmin/system/fixtures/init_rolemenubuttonpermission.json @@ -1,12 +1,7 @@ [ { - "role_key": "admin", - "menu_button_value": "menu:Search", - "data_range": 0 - }, - { - "role_key": "public", - "menu_button_value":"menu:Search", + "role__key": "admin", + "menu_button__value": "menu:Search", "data_range": 0 } ] diff --git a/backend/dvadmin/system/fixtures/init_rolemenupermission.json b/backend/dvadmin/system/fixtures/init_rolemenupermission.json index 8d09e8d..7a6244e 100644 --- a/backend/dvadmin/system/fixtures/init_rolemenupermission.json +++ b/backend/dvadmin/system/fixtures/init_rolemenupermission.json @@ -1,10 +1,12 @@ [ { - "role_key": "admin", - "menu_component_name": "menu" + "role__key": "admin", + "menu__web_path": "/system", + "menu__component_name": "" }, { - "role_key": "public", - "menu_component_name": "menu" + "role__key": "admin", + "menu__web_path": "/menu", + "menu__component_name": "menu" } ] diff --git a/backend/dvadmin/system/fixtures/initialize.py b/backend/dvadmin/system/fixtures/initialize.py index 74d89d7..f409643 100644 --- a/backend/dvadmin/system/fixtures/initialize.py +++ b/backend/dvadmin/system/fixtures/initialize.py @@ -45,13 +45,13 @@ class Initialize(CoreInitialize): """ 初始化角色菜单信息 """ - self.init_base(RoleMenuInitSerializer, unique_fields=['role', 'menu']) + self.init_base(RoleMenuInitSerializer, unique_fields=['role__key', 'menu__web_path', 'menu__component_name']) def init_role_menu_button(self): """ 初始化角色菜单按钮信息 """ - self.init_base(RoleMenuButtonInitSerializer, unique_fields=['role', 'menu_button']) + self.init_base(RoleMenuButtonInitSerializer, unique_fields=['role__key', 'menu_button__value']) def init_api_white_list(self): """ From 6e3f05c58f5761b7dffbdac8142e6d2d082487e6 Mon Sep 17 00:00:00 2001 From: china_ahhui Date: Sun, 2 Jun 2024 11:33:48 +0800 Subject: [PATCH 23/30] =?UTF-8?q?=E7=99=BB=E5=BD=95=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E6=89=AB=E7=A0=81=E6=8C=89=E9=92=AEui=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/views/system/login/index.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/views/system/login/index.vue b/web/src/views/system/login/index.vue index bb442bf..dbaf061 100644 --- a/web/src/views/system/login/index.vue +++ b/web/src/views/system/login/index.vue @@ -279,8 +279,8 @@ onMounted(() => { .login-content-main-sacn { position: absolute; - top: 0; - right: 0; + top: 2px; + right: 12px; width: 50px; height: 50px; overflow: hidden; From 30d74673690b67d36bd7e17bc06e56f76b3ac0c0 Mon Sep 17 00:00:00 2001 From: china_ahhui Date: Sun, 2 Jun 2024 12:07:46 +0800 Subject: [PATCH 24/30] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/main.ts | 8 +++++++- web/src/settings.ts | 13 +++++++------ web/src/views/system/login/component/account.vue | 12 ++++++------ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/web/src/main.ts b/web/src/main.ts index b5cd68e..54459c3 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -54,6 +54,12 @@ other.elSvg(app); app.use(VXETable) -app.use(pinia).use(router).use(ElementPlus, { i18n: i18n.global.t }).use(i18n).use(VueGridLayout).use(fastCrud).mount('#app'); +app.use(pinia) + .use(router) + .use(ElementPlus, { i18n: i18n.global.t }) + .use(i18n) + .use(VueGridLayout) + .use(fastCrud) + .mount('#app'); app.config.globalProperties.mittBus = mitt(); diff --git a/web/src/settings.ts b/web/src/settings.ts index cbef494..61881d3 100644 --- a/web/src/settings.ts +++ b/web/src/settings.ts @@ -9,7 +9,7 @@ import {getBaseURL} from '/@/utils/baseUrl'; import ui from '@fast-crud/ui-element'; import {request} from '/@/utils/service'; //扩展包 -import {FsExtendsEditor, FsExtendsUploader,FsCropperUploader} from '@fast-crud/fast-extends'; +import {FsExtendsEditor, FsExtendsUploader } from '@fast-crud/fast-extends'; import '@fast-crud/fast-extends/dist/style.css'; import {successNotification} from '/@/utils/message'; import XEUtils from "xe-utils"; @@ -75,6 +75,7 @@ export default { }, */ }; }, + logger: { off: { tableColumns: false } } }); //富文本 app.use(FsExtendsEditor, { @@ -89,7 +90,7 @@ export default { action: `/api/system/file/`, name: "file", withCredentials: false, - uploadRequest: async ({action, file, onProgress}) => { + uploadRequest: async ({ action, file, onProgress }: { action: string; file: any; onProgress: Function }) => { // @ts-ignore const data = new FormData(); data.append("file", file); @@ -101,12 +102,12 @@ export default { "Content-Type": "multipart/form-data" }, data, - onUploadProgress: (p) => { + onUploadProgress: (p: any) => { onProgress({percent: Math.round((p.loaded / p.total) * 100)}); } }); }, - successHandle(ret) { + successHandle(ret: any) { // 上传完成后的结果处理, 此处应返回格式为{url:xxx,key:xxx} return { url: getBaseURL(ret.data.url), @@ -115,8 +116,8 @@ export default { }; } }, - valueBuilder(context){ - const {row,key} = context + valueBuilder(context: any){ + const { row, key } = context return getBaseURL(row[key]) } }) diff --git a/web/src/views/system/login/component/account.vue b/web/src/views/system/login/component/account.vue index c4b1247..ee4e64f 100644 --- a/web/src/views/system/login/component/account.vue +++ b/web/src/views/system/login/component/account.vue @@ -1,5 +1,5 @@