Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
李强
2023-12-26 09:48:06 +08:00
27 changed files with 749 additions and 129 deletions

View File

@@ -155,6 +155,11 @@ STATICFILES_DIRS = [
MEDIA_ROOT = "media" # 项目下的目录
MEDIA_URL = "/media/" # 跟STATIC_URL类似指定用户可以通过这个url找到文件
#添加以下代码以后就不用写{% load staticfiles %},可以直接引用
STATICFILES_FINDERS = (
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder"
)
# 收集静态文件,必须将 MEDIA_ROOT,STATICFILES_DIRS先注释
# python manage.py collectstatic
# STATIC_ROOT=os.path.join(BASE_DIR,'static')
@@ -403,5 +408,6 @@ PLUGINS_URL_PATTERNS = []
# from dvadmin_third.settings import * # 第三方用户管理
# from dvadmin_ak_sk.settings import * # 秘钥管理管理
# from dvadmin_tenants.settings import * # 租户管理
from dvadmin_social_auth.settings import *
# ...
# ********** 一键导入插件配置结束 **********

View File

@@ -182,7 +182,7 @@
"parent": 1,
"title": "隐私链接",
"key": "privacy_url",
"value": "#",
"value": "/api/system/clause/privacy.html",
"sort": 7,
"status": true,
"data_options": null,
@@ -196,7 +196,7 @@
"parent": 1,
"title": "条款链接",
"key": "clause_url",
"value": "#",
"value": "/api/system/clause/terms_service.html",
"sort": 8,
"status": true,
"data_options": null,

View File

@@ -162,6 +162,7 @@ class Menu(CoreModel):
(1, ""),
)
is_link = models.BooleanField(default=False, verbose_name="是否外链", help_text="是否外链")
link_url = models.CharField(max_length=255, verbose_name="链接地址", null=True, blank=True, help_text="链接地址")
is_catalog = models.BooleanField(default=False, verbose_name="是否目录", help_text="是否目录")
web_path = models.CharField(max_length=128, verbose_name="路由地址", null=True, blank=True, help_text="路由地址")
component = models.CharField(max_length=128, verbose_name="组件地址", null=True, blank=True, help_text="组件地址")
@@ -171,6 +172,8 @@ class Menu(CoreModel):
cache = models.BooleanField(default=False, blank=True, verbose_name="是否页面缓存", help_text="是否页面缓存")
visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示",
help_text="侧边栏中是否显示")
is_iframe = models.BooleanField(default=False, blank=True, verbose_name="框架外显示", help_text="框架外显示")
is_affix = models.BooleanField(default=False, blank=True, verbose_name="是否固定", help_text="是否固定")
class Meta:
db_table = table_prefix + "system_menu"

View File

@@ -3,6 +3,7 @@ from rest_framework import routers
from dvadmin.system.views.api_white_list import ApiWhiteListViewSet
from dvadmin.system.views.area import AreaViewSet
from dvadmin.system.views.clause import PrivacyView, TermsServiceView
from dvadmin.system.views.dept import DeptViewSet
from dvadmin.system.views.dictionary import DictionaryViewSet
from dvadmin.system.views.file_list import FileViewSet
@@ -46,5 +47,7 @@ urlpatterns = [
path('login_log/', LoginLogViewSet.as_view({'get': 'list'})),
path('login_log/<int:pk>/', LoginLogViewSet.as_view({'get': 'retrieve'})),
path('dept_lazy_tree/', DeptViewSet.as_view({'get': 'dept_lazy_tree'})),
path('clause/privacy.html', PrivacyView.as_view()),
path('clause/terms_service.html', TermsServiceView.as_view()),
]
urlpatterns += system_url.urls

View File

@@ -0,0 +1,23 @@
from rest_framework.views import APIView
from django.shortcuts import render
class PrivacyView(APIView):
"""
后台隐私政策
"""
permission_classes = []
def get(self, request, *args, **kwargs):
return render(request, 'privacy.html')
class TermsServiceView(APIView):
"""
后台服务条款
"""
permission_classes = []
def get(self, request, *args, **kwargs):
return render(request, 'terms_service.html')

View File

@@ -71,8 +71,8 @@ class WebRouterSerializer(CustomModelSerializer):
class Meta:
model = Menu
fields = (
'id', 'parent', 'icon', 'sort', 'path', 'name', 'title', 'is_link', 'is_catalog', 'web_path', 'component',
'component_name', 'cache', 'visible', 'status')
'id', 'parent', 'icon', 'sort', 'path', 'name', 'title', 'is_link','link_url', 'is_catalog', 'web_path', 'component',
'component_name', 'cache', 'visible','is_iframe','is_affix', 'status')
read_only_fields = ["id"]

View File

@@ -0,0 +1,34 @@
html,body{width:100%;overflow-x: hidden;margin: 0;padding: 0;font-size:1rem;font-family: "PingFang SC","SF Pro SC","SF Pro Text","SF Pro Icons","Helvetica Neue","Helvetica","Arial",sans-serif;
-webkit-font-smoothing: antialiased;}
a{text-decoration:none;}
ul,li{list-style:none;padding:0;margin:0;}
.bg{background-repeat:no-repeat;background-position:center center;background-size:100%;}
.center{margin:0 auto;position:relative;}
.abs_center{position:absolute;left: 50%;transform: translateX(-50%);-webkit-transform:translateX(-50%);}
/*滚动条统一样式*/
.scrollbar{overflow-x:hidden;scrollbar-track-color:none;}
.scrollbar::-webkit-scrollbar{width:8px;background-color:transparent;} /*滚动条整体部分*/
.scrollbar::-webkit-scrollbar-track{border-radius:4px;-webkit-box-shadow: inset 0 0 0 rgba(0,0,0,0);background-color:transparent;display:none;} /* 滚动条的轨道*/
.scrollbar::-webkit-scrollbar-track-piece{background-color:transparent;display:none;}/* 滚动条的内层轨道*/
.scrollbar::-webkit-scrollbar-thumb{border-radius:4px;background: #313131;}/*滚动条里面的小方块,能向上向下移动(或往左往右移动,取决于是垂直滚动条还是水平滚动条)*/
h3,h4,h5{ font-weight: bold;}
h3{ font-size: .4rem; color:#000;}
h4{ font-size: .35rem; color: #000; margin:.2rem 0 0 0;}
p{ line-height: .5rem; margin:.2rem 0;word-break: break-all;text-align:justify;}
.app .main{width:90%;overflow:hidden;font-size:.30rem;box-sizing: border-box; margin: 0 auto; color: #484d57;}
.app ul { padding-left: .1rem; font-size: .26rem;}
.app ul p{ line-height: .4rem;}
.app .mainbg{position:absolute;left:50%;transform:translateX(-50%);background-repeat:no-repeat;background-size:100%;}
.app .poster{width:100%;height:31.85rem;background-image:url(../images/poster_bg.jpg);}
.pc .main{font-size:.16rem;}

View File

@@ -0,0 +1,233 @@
<!DOCTYPE html>
<html data-dpr="1" style="font-size: 50px;">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>隐私政策</title>
<link href="/static/clause/privacy.css" rel="stylesheet">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
</head>
<body class="app" style="font-size: 0.28rem;">
<div class="main">
<h3>隐私政策</h3>
<br>更新日期2024年01月01日
<br>生效日期2024年01月01日
<br>
<br>欢迎您使用DvAdmin产品DvAdmin非常重视用户的个人信息和隐私保护为同时给您提供更准确有个性化的服务和更安全的互联网环境我们依据中华人民共和国网络安全法信息安全技术个人信息安全规范GB/T35273-2017以及其他相关法律法规和技术规范制定了隐私政策阐述了关于您个人信息的相关权利等
<br>
<br>本政策适用于我们的所有DvAdmin系列产品及服务本政策与您所使用的我们的产品与/或服务息息相关您在下载安装启动浏览注册登录使用巨梦科技的产品及/或服务时我们将按照本政策的约定处理和保护您的个人信息我们将尽量以简明扼要的表述向您解释本政策所涉及的技术词汇以便于您理解
<br>
<br>您在使用DvAdmin的产品及/或服务时巨梦科技可能会收集和使用您的相关信息为此希望通过本隐私政策向您说明巨梦科技如何取得使用保存和管理这些信息请在使用/继续使用我们的各项产品与服务前仔细阅读并充分理解本政策特别应重点阅读我们以粗体/粗体下划线标识的条款并在需要时按照本政策的指引作出适当的选择如果您不同意本政策的内容将可能导致我们的产品与/或服务无法正常运行或者无法达到我们拟达到的服务效果您应立即停止访问/使用我们的产品与/或服务您使用或继续使用我们提供的产品与/或服务的行为都表示您充分理解和同意本隐私政策的全部内容
<br>
<br>隐私政策将帮助您了解以下内容
<br><a href="#1_chapter">第一章 如何收集您的个人信息</a>
<br><a href="#2_chapter">第二章 如何使用您的个人信息</a>
<br><a href="#3_chapter">第三章 如何使用Cookie和同类技术</a>
<br><a href="#4_chapter">第四章 如何共享转让公开披露您的个人信息</a>
<br><a href="#5_chapter">第五章 如何保护您的个人信息</a>
<br><a href="#6_chapter">第六章 如何保存您的个人信息</a>
<br><a href="#7_chapter">第七章 管理查看或删除您的个人信息</a>
<br><a href="#8_chapter">第八章 如何处理儿童的个人信息</a>
<br><a href="#9_chapter">第九章 本政策如何更新</a>
<br><a href="#10_chapter">第十章 投诉及建议</a>
<br><a href="#11_chapter">第十一章 其他</a>
<br>
<h1 id="1_chapter">第一章 如何收集您的个人信息</h1>
<br>
<br>在您使用我们的产品/服务时我们需要/可能需要收集和使用的您的个人信息包括如下两种
<br>第一种为实现向您提供我们产品及/或服务的基本功能您须授权我们收集使用的必要的信息如您拒绝提供相应信息您将无法正常使用我们的产品及/或服务
<br>第二种为实现向您提供我们产品及/或服务的附加功能您可选择单独同意或不同意我们收集使用的信息如您拒绝提供您将无法正常使用相关附加功能或无法达到我们拟达到的功能效果不会影响您使用我们的基本功能
<br>
<br>个人敏感信息是指一旦泄露非法提供或滥用可能危害人身和财产安全极易导致个人名誉身心健康受到损害或歧视性待遇等的个人信息如个人财产信息个人健康生理信息个人生物识别信息个人身份信息网络身份标识信息及其他信息
<br>上述信息所包含的内容均出自于GB/T35273信息安全技术 个人信息安全规范
<br>
<h3>1.1 您向巨梦科技提供相关个人信息</h3>
<h4>1.1.1
为使用巨梦科技的产品及/或服务您首先需要注册账号并登录您可以选择通过微信等方式创建巨梦科技产品及/或服务的账号并登录"账号登录"</h4>
<h5>1.1.1.1 通过微信第三方账户登录巨梦科技产品及/或服务时您同意我们从微信获取您授权共享的信息包括手机号位置信息昵称头像等
并且您同意将您的第三方账户与您的巨梦科技产品及/或服务账号绑定使您可以通过第三方账户直接登录并使用巨梦科技的产品及/或服务并借助该账户实现数据在不同设备之间的同步
我们会依据与第三方的约定并在符合相关法律法规的前提下使用您授权共享的个人信息如果您拒绝同意巨梦科技从第三方获取您授权共享的信息您将无法通过微信的方式注册账号并登录也无法借助该第三方账户实现数据的同步</h5>
<h4>1.1.2 在您使用巨梦科技产品及/或服务时您可能会因账号管理产品使用等问题联系巨梦科技客服为此您可能需要向巨梦科技提供姓名手机号码系统操作记录照片银行账号第三方支付平台的账号
与巨梦科技进行联系的通信记录及内容等与您使用巨梦科技产品及/或服务相关的信息以便巨梦科技的客服人员您联系并帮助您解决相关问题
如果您拒绝提供相关信息巨梦科技可能无法帮助您解决相关问题</h4>
<h3>1.2 巨梦科技收集您所使用的相关设备及网络信息</h3>
<h4>1.2.1
当您使用巨梦科技的产品及/或服务时巨梦科技将收集您所使用的相关设备信息以便为您提供持续稳定的服务支持使您在使用巨梦科技的产品及/或服务过程中获得最优体验巨梦科技收集的您所使用的相关设备信息包括浏览器信息网络信息IP地址日志信息如操作日志服务日志等等</h4>
<h3>1.3 巨梦科技向您收集的信息</h3>
<h4>1.3.1
为提升巨梦科技产品及/或服务的使用体验和便利程度巨梦科技可能会通过调用设备权限的方式收集您的如下个人信息如果您不同意提供这些个人信息您可能无法使用与提升用户体验相关的功能您也可能需要在使用巨梦科技产品及/或服务过程中手动重复填写一些信息</h4>
<h4>1.3.2
若您希望向巨梦科技上传您的头像及/或其他图片信息您可以选择授权巨梦科技调用您所使用设备中的摄像头或者相册权限</h4>
<h4>1.3.3
若您希望快速便捷地通过第三方移动运营商完成支付在您的设备支持的情况下您可以选择授权调用您所使用设备中的移动运营相关权限如短信以便您快速便捷地完成付款</h4>
<h4>1.3.4
若您希望实现或体验上述功能您可能需要在您的设备中向巨梦科技开启您的相应访问权限您也可以随时选择关闭相应访问权限以取消相应授权在不同设备中权限显示方式及关闭方式可能有所不同具体请参考设备及系统开发方的说明或指引</h4>
<h3>1.4 第三方向您收集的信息</h3>
<h4>1.4.1 第三方付款服务提供商收集相关个人信息</h4>
<h5>1.4.1.1
您可以通过向巨梦科技付款的方式获取巨梦科技产品及/或服务相关的产品上述付款服务可能由巨梦科技以外的第三方提供巨梦科技并不会获取与您付款相关的密码等信息但可能从您或第三方支付平台获得您的第三方支付账户微信账号若您希望了解第三方服务提供商收集个人信息的具体规则请查阅您选择的第三方付款服务提供商的隐私政策</h5>
<h3>1.5 您充分知晓在以下情形下我们收集使用个人信息无需征得您的授权同意</h3>
<h4>1.5.1 与国家安全国防安全有关的</h4>
<h4>1.5.2 与公共安全公共卫生重大公共利益有关的</h4>
<h4>1.5.3 与犯罪侦查起诉审判和判决执行等有关的</h4>
<h4>1.5.4 出于维护个人信息主体或其他个人的生命财产等重大合法权益但又很难得到本人同意的</h4>
<h4>1.5.5 所收集的个人信息是个人信息主体自行向社会公众公开的</h4>
<h4>1.5.6 从合法公开披露的信息中收集的您的个人信息的如合法的新闻报道政府信息公开等渠道</h4>
<h4>1.5.7 根据您要求签订和履行合同所必需的</h4>
<h4>1.5.8 用于维护所提供的产品及/或服务的安全稳定运行所必需的例如发现处置产品及/或服务的故障</h4>
<h4>1.5.9 法律法规规定的其他情形</h4>
<h3>1.6
根据法律规定向第三方提供经去标识化处理的个人信息且确保数据接收方无法复原并重新识别个人信息主体的不属于个人信息的对外共享转让及公开披露行为对此类数据的保存及处理将无需另行向您通知并征得您的同意</h3>
<br>
<h1 id="2_chapter">第二章 如何使用您的个人信息</h1>
<br>
<h2>在收集您的个人信息后巨梦科技将根据如下规则使用您的个人信息</h2>
<br>
<h3>2.1 会根据本隐私政策的约定并为实现巨梦科技的产品及/或服务功能对所收集的个人信息进行使用</h3>
<h3>2.2
请您注意对于您在使用巨梦科技的产品及/或服务时所提供的所有个人信息除非您删除或通过相关设置拒绝我们收集否则您将在使用产品及/或服务期间账号注销前持续授权我们使用</h3>
<h3>2.3
巨梦科技系列产品或服务对使用情况进行统计并可能会与公众或第三方共享这些统计信息以展示巨梦科技产品及/或服务的整体使用趋势但这些统计信息不会包含您的任何身份识别信息</h3>
<h3>2.4
当巨梦科技要将您的个人信息用于本政策未载明的其它用途时或将基于特定目的收集而来的信息用于其他目的时巨梦科技会主动事先征求您的明示同意</h3>
<br>
<h1 id="3_chapter">第三章 如何使用Cookie和同类技术</h1>
<h2>巨梦科技暂未使用任何信息收集工具</h2>
<br>
<h1 id="4_chapter">第四章 如何共享转让公开披露您的个人信息</h1>
<h2>共享</h2>
<h3>4.1 巨梦科技将严格遵守相关法律法规对您的个人信息予以保密除以下情况外我们不会向其他人共享您的个人信息</h3>
<h4>4.1.1 事先获得您明确的同意或授权</h4>
<h4>4.1.2 根据适用的法律法规规定或基于司法或行政主管部门的强制性要求进行提供</h4>
<h4>4.1.3
在法律法规允许的范围内为维护您或其他巨梦科技用户或其他个人的生命财产等合法权益或是社会公共利益而有必要提供</h4>
<h4>4.1.4 应您的监护人的合法要求而提供您的信息</h4>
<h4>4.1.5 根据与您签署的相关协议包括在线签署的电子协议以及相应的平台规则或其他的法律文件约定而提供</h4>
<h4>4.1.6 根据本隐私政策所述与第三方进行共享</h4>
<h4>4.1.7
巨梦科技可能会基于您的相应授权将您的个人信息与公司的关联方共享但巨梦科技只会共享必要的个人信息且受本隐私政策所述目的之约束 如果巨梦科技的关联方要改变个人信息的处理目的将适时向您征得明示同意</h4>
<h3>4.2
对巨梦科技与之共享个人信息的公司组织和个人我们将尽合理的努力要求其处理您的个人信息时遵守相关法律法规尽力要求其采取相关的保密和安全措施以保障您的个人信息安全</h3>
<h2>转让</h2>
<h3>4.3 巨梦科技不会将您的个人信息转让给任何公司组织和个人但以下情况除外</h3>
<h4>4.3.1 事先获得您明确的同意或授权</h4>
<h4>4.3.2 根据适用的法律法规法律程序的要求强制性的行政或司法要求而必须进行提供</h4>
<h4>4.3.3
涉及收购兼并破产清算重组等重大变更时如涉及到个人信息转让的巨梦科技会要求新的持有您个人信息的公司或组织继续履行本隐私政策项下的责任和义务如变更后的主体需变更个人信息使用目的我们会要求其事先获得您的明示同意</h4>
<h2>公开披露</h2>
<h3>4.4 巨梦科技仅会在以下情况下且在采取符合业界标准的安全防护措施的前提下才会公开披露您的个人信息</h3>
<h4>4.4.1根据您的需求在您明确同意的披露方式下披露您所指定的个人信息</h4>
<h4>4.4.2
根据法律法规的要求行政或司法机关的强制性要求我们可能会公开披露您的个人信息当巨梦科技收到上述披露请求时巨梦科技会依法要求请求方出具相关法律文件如传票或协助调查函等巨梦科技会慎重审查每一个披露请求以确保该等披露请求符合相关法律规定在法律法规许可的前提下巨梦科技会对包含披露信息的文件采取加密保护等措施</h4>
<br>
<h1 id="5_chapter">第五章 如何保护您的个人信息</h1>
<h3>5.1
巨梦科技非常重视个人信息安全并会采取一切合理可行的措施持续保护您的个人信息以防其他人在未经授权的情况下访问篡改或披露巨梦科技收集的您的个人信息</h3>
<h4>5.1.1
巨梦科技已采用符合行业标准的安全防护措施来保护您的个人信息防止数据遭到未经授权的访问公开披露使用修改损坏或丢失我们会采取一切合理可行的措施保护您的个人信息我们会使用受信赖的保护机制防止数据遭到恶意攻击</h4>
<h4>5.1.2
巨梦科技仅允许有必要知晓的人员访问相关个人信息并为此设置了严格的访问权限控制和监控机制巨梦科技同时要求可能接触到您个人信息的所有人员履行相应的保密义务如果未能履行这些义务可能会被追究法律责任或被终止与巨梦科技的相应法律关系</h4>
<h3>5.2 巨梦科技会采取一切合理可行的措施确保未收集无关的信息</h3>
<h3>5.3
您理解由于技术的限制以及可能存在的各种恶意手段在互联网行业即便我们竭尽所能加强安全措施但也不可能始终保证信息百分之百的绝对安全您需要了解和知悉您接入巨梦科技的产品及/或服务所用的系统和通讯网络有可能因我们可控范围外的其他因素而出现问题在此情形下我们会依法尽力协助解决</h3>
<h3>5.4
如不幸发生信息安全事故我们将按照法律法规的要求及时向您告知安全事件的基本情况和可能的影响我们已采取或将要采取的处置措施您可自主防范和降低风险的建议等我们同时将及时将事件相关情况以邮件信函电话推送通知等适合的方式告知您难以逐一告知信息主体时我们会采取合理有效的方式发布公告同时我们还将按照监管部门要求主动上报信息安全事件的处置情况</h3>
<br>
<h1 id="6_chapter">第六章 如何保存您的个人信息</h1>
<h2>保存期限</h2>
<h3>6.1 在用户使用巨梦科技产品及/或服务期间巨梦科技会持续保存用户的个人信息</h3>
<h3>6.2
巨梦科技承诺始终按照法律的规定在合理必要期限内在存储您个人信息对于日志信息记录备份等信息为您注销账号后180天但根据法律规定有最短保存期限要求的则我们会保存法律要求的最短期限交易信息为交易完成日起三年或您注销账号后180天以较长者为准在超出上述期限后我们会对您的相关信息进行删除或匿名化处理</h3>
<h2>保存地域</h2>
<h3>6.3 您的个人信息将全部被存储于中华人民共和国境内</h3>
<h3>6.4 目前我们不存在向境外提供个人信息的场景</h3>
<br>
<h1 id="7_chapter">第七章 管理查看或删除您的个人信息</h1>
<h2>巨梦科技非常尊重您对自己的个人信息所享有的权利我们保障您对个人信息所享有的访问更正删除管理等权利</h2>
<br>
<h2>访问和更正您的个人信息</h2>
<h3>7.1
除法律法规另有规定之外您有权行使数据访问权当您发现我们处理关于您的个人信息有错误或者您有其他修改补充需求时您也有权要求我们或自行予以更正您行使数据访问和更正权的方式包括但不限于</h3>
<h4>7.1.1
如果您希望访问或修改您在巨梦科技产品及/或服务中的账号信息包括头像昵称性别生日等您可以通过访问我们的产品及/或服务进行操作可通过点击我的功能后进行操作</h4>
<h4>7.1.2
如巨梦科技的产品及/或服务中提供发表话题参与讨论留言等功能并使得您有机会通过这些服务公开或提供的个人信息的则巨梦科技在提供前述服务的同时会提供相应的功能确保您可以再次访问或删除您在前述服务过程中公开或提供的个人信息</h4>
<h3>7.2
您有权知悉通过巨梦科技获得您的个人信息的第三方的身份或类型您可以通过本政策第一章和第四章了解第三方的身份或类型</h3>
<br>
<h2>删除您的个人信息及撤回已同意的授权</h2>
<h3>7.3 在以下情形中您可以向巨梦科技提出删除个人信息的请求</h3>
<h4>7.3.1 如果巨梦科技处理个人信息的行为违反相关的法律法规</h4>
<h4>7.3.2 如果巨梦科技收集使用您的个人信息却未征得您的同意</h4>
<h4>7.3.3 如果巨梦科技处理个人信息的行为违反了与您的约定或法律的规定</h4>
<h4>7.3.4 如果您不再使用巨梦科技的产品及/或服务或者您注销了相关账号</h4>
<h4>7.3.5 如果巨梦科技不再为您提供产品及/或服务</h4>
<h3>7.4
您有权向巨梦科技撤回您此前作出的有关同意收集使用您的个人信息的授权当您撤回同意后我们将不再处理您的相关个人信息但您撤回同意的决定不会影响此前基于您的授权而开展的个人信息处理活动</h3>
<h3>7.5 您可以通过删除相关个人信息的方式撤回您此前就特定个人信息而对我们作出的同意授权</h3>
<h2>注销账号</h2>
<h3>7.6
您有权随时提出申请注销您在巨梦科技产品及/或服务中注册的账号为保障账号及财产安全您需要通过客户服务或本隐私条款第十章载明的联系方式向巨梦科技提出您的账号注销请求巨梦科技将在与您核实相关信息后的15个工作日内为您注销账号</h3>
<h3>7.7
请您注意注销巨梦科技相关产品及/或服务账号是不可恢复的操作在注销账号之后我们将停止为您提供产品及/或服务并将删除该账号项下的您的个人信息除非法律法规另有规定</h3>
<h2>约束信息系统自动决策</h2>
<h3>7.8
在巨梦科技仅依据信息系统算法等在内的非人工自动决策机制做出决定并且这些决定显著影响您的合法权益的情况下您有权要求巨梦科技做出解释巨梦科技也将提供适当的救济方式</h3>
<h2>获取个人信息副本</h2>
<h3>7.9
根据您的请求巨梦科技可以向您提供巨梦科技持有的有关您的个人信息副本如个人基本资料您可以通过客户服务或本隐私条款第十章载明的联系方式向我们提出请求</h3>
<h2>响应您的上述请求</h2>
<h3>
7.10如果您对巨梦科技在以上列明的有关访问更正删除您的个人信息以及撤回同意注销账号约束信息系统自动决策方法有任何疑问您可以通过客户服务或本隐私政策第十章载明的联系方式与我们取得联系</h3>
<h3>7.11
对于您合理的请求巨梦科技原则上不收取费用但对多次重复超出合理限度的请求巨梦科技将视情况收取一定成本费用对于那些无端重复需要过多技术手段给他人合法权益带来风险或者非常不切实际的请求巨梦科技可能会予以拒绝</h3>
<h3>7.12 在以下情形下我们可能无法响应您的请求</h3>
<h4>7.12.1 与国家安全国防安全有关的</h4>
<h4>7.12.2 与公共安全公共卫生重大公共利益有关的</h4>
<h4>7.12.3 与犯罪侦查起诉和审判等有关的</h4>
<h4>7.12.4 有证据表明您存在主观恶意或滥用权利的</h4>
<h4>7.12.5 响应您的请求将导致其他个人组织的合法权益受到严重损害的</h4>
<h4>7.12.6 涉及商业秘密的</h4>
<h2>申诉机制</h2>
<h3>7.13
巨梦科技已经建立申诉管理机制包括跟踪流程等为了保障账号及财产安全巨梦科技可能会与您核实相关信息巨梦科技将在收到您的反馈后尽快受理并处理您的请求最长不超过15个工作日若您对答复意见不满意您可以再次通过客户服务进行申诉申诉的联系方式及相关具体信息请详见第十章</h3>
<br>
<br>
<h1 id="8_chapter">第八章 儿童信息的保护</h1>
<h3>8.1
我们的产品及服务主要面向成人巨梦科技非常重视对未成年人信息的保护如果您是未满18周岁的未成年人应在监护人监护指导并获得监护人同意情况下仔细阅读本隐私政策和使用巨梦科技的产品及/或服务</h3>
<h3>8.2 如果您/您的监护人不同意本隐私政策的任何内容您应该立即停止使用我们的产品及/或服务</h3>
<h3>8.3
若您是未成年人的监护人当您对您所监护的未成年人使用我们的产品及/或服务或其向我们提供的用户信息有任何疑问时请您及时与我们联系我们将根据国家相关法律法规及本政策的规定保护未成年人用户信息的保密性及安全性如果我们发现自己在未事先获得可证实的监护人同意的情况下收集了未成年人的个人信息则会设法尽快删除相关数据</h3>
<br>
<h1 id="9_chapter">第九章 本政策如何更新</h1>
<h3>9.1 如巨梦科技产品及/或服务发生以下变化巨梦科技将及时对本隐私政策进行相应的修订</h3>
<h4>9.1.1 巨梦科技产品及/或服务所涉业务功能发生变更导致处理个人信息的目的类型使用方式发生变更</h4>
<h4>9.1.2 您参与个人信息处理方面的权利及其行使方式发生重大变化</h4>
<h4>9.1.3 巨梦科技负责处理您的个人信息安全的部门的联络方式发生变更</h4>
<h4>9.1.4 发生其他可能影响用户个人信息安全或影响用户隐私权利的变更等</h4>
<h3>9.2
隐私政策修订后巨梦科技会在巨梦科技产品及/或服务相关界面发布最新版本并以弹窗推送通知等合理的方式告知用户以便用户及时了解隐私政策的最新版本</h3>
<h3>9.3 未经您的明确同意巨梦科技不会削减您基于本隐私政策所享有的权利</h3>
<h3>9.4 如无特殊说明修订后的隐私政策自公布之日起生效</h3>
<br>
<h1 id="10_chapter">第十章 投诉及建议</h1>
<h3>10.1
您在使用巨梦科技产品及/或服务的过程中如果对本隐私政策有任何的疑义或建议或您认为您的个人信息没有得到本隐私政策规定的保护您可以通过以下方式联系我们我们将真诚地处理您的投诉及建议</h3>
<h4>公司名称北京巨梦科技信息技术有限公司</h4>
<h4>联系邮箱qiangli@django-vue-admin.com</h4>
<h4>微信公众号巨梦科技9:00-22:00</h4>
<br>
<h1 id="11_chapter">第十一章 其他</h1>
<h3>11.1 因本政策以及我们处理您个人信息事宜引起的任何争议您可诉至有管辖权的人民法院</h3>
<h3>11.2 如果您认为我们的个人信息处理行为损害了您的合法权益您也可向有关政府部门进行反映</h3>
<h3>11.3
在巨梦科技发布本隐私政策或向您提供产品及/或服务均视为本隐私政策生效巨梦科技停止运营或永久停止提供产品及/或服务时本隐私政策失效</h3>
<br>
</div>
</body>
</html>

View File

@@ -0,0 +1,96 @@
<!DOCTYPE html>
<html data-dpr="1" style="font-size: 50px;">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户服务协议</title>
<link href="/static/clause/privacy.css" rel="stylesheet">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
</head>
<body class="app" style="font-size: 0.28rem;">
<div class="main">
<h3>服务使用协议</h3>
<br>更新日期2024年01月01日
<br>生效日期2024年01月01日
<br>DvAdmin服务使用协议是您下称"用户"与北京巨梦科技科技有限公司之间在使用其DvAdmin产品中注册或登录时签署的协议巨梦科技产品包括django-vue-admin产品请仔细阅读以下条款点击同意按钮即表示对相关条款的同意如果您阅读这份协议后有任何疑问或意见请与巨梦科技客服人员取得联系联系邮箱qiangli@django-vue-admin.cn微信公众号巨梦科技9:00-18:00
<br>
<h2>重要须知</h2>
<h3>
1用户应认真阅读未成年人应当在监护人陪同下阅读充分理解本协议中各条款除非用户接受本协议用户应当立即停止注册及使用行为</h3>
<h3>2用户在进行注册程序过程中点击同意按钮即表示用户完全接受本协议项下的全部条款</h3>
<br>
<h2>服务内容</h2>
<h3>1巨梦科技服务的具体内容由巨梦科技根据实际情况提供</h3>
<h3>2用户理解巨梦科技仅提供软件相关服务
除此之外与相关软件服务有关的设备如手机个人电脑及其他与接入互联网或移动网有关的装置及所需的费用如为接入互联网而支付的电话费及上网费为使用移动网而支付的手机费均应由用户自行负担</h3>
<h3>
3用户同意巨梦科技为本协议履行或相关研究的目的收集使用或授权第三方且该等第三方同意承担与巨梦科技同等的个人信息保护义务非商业地使用通过服务获取的用户信息包括但不限于身份信息性别职业兴趣爱好等资料巨梦科技承诺除非另行取得用户的事先同意否则巨梦科技不会将用户信息授权给与履行本协议无关的第三方用于商业目的</h3>
<h3>5根据相关法律法规及国家标准在以下情形中巨梦科技可能会依法收集并使用用户的个人信息并且无需征得用户的同意:</h3>
<h4>1与国家安全国防安全直接相关的</h4>
<h4>2与公共安全公共卫生重大公共利益直接相关的</h4>
<h4>3与犯罪侦查起诉审判和判决执行等直接相关的</h4>
<h4>4出于维护用户或他人的生命财产等重大合法权益但又很难得到用户本人同意的</h4>
<h4>5所收集的个人信息是用户自行向社会公众公开的</h4>
<h4>6从合法公开披露的信息中收集个人信息例如合法的新闻报道政府信息公开等渠道</h4>
<h4>7根据用户的要求签订和履行合同所必需的</h4>
<h4>8用于维护所提供的服务的安全稳定运行所必需的例如发现处置产品或服务的故障</h4>
<h4>9为合法的新闻报道所必需的</h4>
<h4>
10学术研究机构基于公共利益开展统计或学术研究所必要且对外提供学术研究或描述的结果时对结果中所包含的个人信息进行去标识化处理的</h4>
<h4>11法律法规规定的其他情形</h4>
<h3>6在以下情形中巨梦科技向第三方提供用户的个人信息无需事先征得用户的授权同意</h3>
<h4>1与国家安全国防安全有关的</h4>
<h4>2与公共安全公共卫生重大公共利益有关的</h4>
<h4>3与犯罪侦查起诉审判和判决执行等有关的</h4>
<h4>4出于维护用户或其他个人的生命财产等重大合法权益但又很难得到本人同意的</h4>
<h4>5用户自行向社会公众公开的个人信息</h4>
<h4>6从合法公开披露的信息中收集个人信息的如合法的新闻报道政府信息公开等渠道</h4>
<h3>
根据法律规定向第三方提供经去标识化处理的个人信息且确保数据接收方无法复原并重新识别个人信息主体的不属于个人信息的对外共享转让及公开披露行为对此类数据的保存及处理将无需另行向用户通知并征得用户的同意</h3>
<h3>本协议中涉及巨梦科技对于用户提供的个人信息的使用如与隐私政策不符的隐私政策为准</h3>
<br>
<h2>用户使用规则</h2>
<h3>1用户授权微信登录成功后用户有权使用巨梦科技软件功能包括参与活动终端管理经销商业务管理等</h3>
<h3>2用户有权使用巨梦科技提供的功能进行照片上传分享个人信息</h3>
<h3>3用户在使用巨梦科技时须遵守国家相关法律法规内容不得包含有下列内容之一的信息</h3>
<h4>a) 反对宪法所确定的基本原则的</h4>
<h4>b) 危害国家安全泄露国家秘密颠覆国家政权破坏国家统一的</h4>
<h4>c) 损害国家荣誉和利益的</h4>
<h4>d) 煽动民族仇恨民族歧视破坏民族团结的</h4>
<h4>e) 破坏国家宗教政策宣扬邪教和封建迷信的</h4>
<h4>f) 散布谣言扰乱社会秩序破坏社会稳定的</h4>
<h4>g) 散布淫秽色情赌博暴力凶杀恐怖或者教唆犯罪的</h4>
<h4>h) 侮辱或者诽谤他人侵害他人合法权利的</h4>
<h4>i) 含有虚假有害胁迫侵害他人隐私骚扰侵害中伤粗俗猥亵或其它道德上令人反感的内容</h4>
<h4>j) 含有中国法律法规规章条例以及任何具有法律效力之规范所限制或禁止的其它内容的</h4>
<h4>k) 含有巨梦科技认为不利于巨梦科技运营的内容</h4>
<h3>
4用户保证在使用巨梦科技时发布传播的信息的真实性准确性保证不得发布谣言或其他与事实不符引起他人不适的言论信息</h3>
<h3>
5用户保证在使用巨梦科技不得发布传播侵犯知识产权或其他合法权益的信息用户传播内容中涉及第三方拥有知识产权内容的相关授权或其他内容的合法性由用户自行负责巨梦科技对相关内容的知识产权权属或是否侵犯他人民事权益等情况不进行审查或监督但将按相关法规对涉嫌侵权的内容履行删除或断开链接等职责</h3>
<h3>
6若用户发生前述3-6的行为时由用户承担所有的违法侵权责任若因此给巨梦科技造成任何损失巨梦科技有权向责任用户主张相关责任同时巨梦科技有权对违法侵权违规的用户终止提供服务如果政府或者司法机关要求巨梦科技告知进行侵权行为用户的具体信息的巨梦科技有权根据现行法规向其告知用户信息</h3>
<h3>
7用户同意巨梦科技有权在提供服务过程中以各种方式投放各种商业性广告或其他任何类型的商业信息并且用户同意接受巨梦科技通过电子邮件或其他方式向用户发送商品促销或其他相关商业信息</h3>
<h3>
8用户承诺提供的注册信息的真实性合法性有效性承担全部责任用户不得冒充他人不得利用他人的名义发布任何信息或享受巨梦科技供的任何服务不得恶意使用注册帐号导致其他用户误认否则巨梦科技有权立即停止提供服务收回其帐号并由用户独自承担由此而产生的一切法律责任</h3>
<br>
<h2>服务变更中断或终止</h2>
<h3>
1鉴于服务的特殊性用户同意巨梦科技有权随时变更中断或终止部分或全部的服务如变更中断或终止的服务属于免费服务巨梦科技无需通知用户也无需对任何用户或任何第三方承担任何责任</h3>
<br>
<h2>巨梦科技企业客户服务说明</h2>
<h3>
1巨梦科技平台提供给多家企业客户使用企业客户通过巨梦科技平台进行发布用户活动等如果功夫企火星企业用户违反了隐私政策或发生其它侵犯用户权益的行为用户可要求巨梦科技提供必要的配合与巨梦科技企业用户进行沟通和维权维权过程中产生的费用由用户自行承担</h3>
<br>
<h2>其他事宜</h2>
<h3>
1巨梦科技有权根据法律法规的变化网站以及相应的巨梦科技运营的需要不时地对本协议及本站的内容进行修改,并在网站以及巨梦科技醒目位置张贴修改后的协议一旦被张贴在本站上即生效,并代替原来的协议,用户可随时登录查阅最新协议用户有义务及时关注并阅读最新版的协议及网站公告如用户不同意更新后的协议可以立即向巨梦科技进行反馈且应立即停止接受巨梦科技依据本协议提供的服务如用户继续使用本站提供的服务的,即视为同意更新后的协议</h3>
<h3>2本协议自用户点击同意接受后生效</h3>
<h3>3本协议所有条款的标题仅为方便而设,不具法律或契约效果</h3>
<h3>4在法律允许范围内 本协议的解释权归巨梦科技所有</h3>
</div>
</body>
</html>

View File

@@ -1,6 +1,6 @@
# port 端口号
VITE_PORT = 8080
VITE_API_URL = 'http://dvadmin3api.django.icu:8001'
# open 运行 npm run dev 时自动打开浏览器
VITE_OPEN = false

View File

@@ -1,7 +1,7 @@
<template>
<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
<img :src="logoMini" class="layout-logo-medium-img" />
<span style="font-size: x-large">{{ themeConfig.globalTitle }}</span>
<span style="font-size: x-large">{{ getSystemConfig['login.site_title'] || themeConfig.globalTitle }}</span>
</div>
<div class="layout-logo-size" v-else @click="onThemeConfigChange">
<img :src="logoMini" class="layout-logo-size-img" />
@@ -13,6 +13,7 @@ import { computed } from 'vue';
import { storeToRefs } from 'pinia';
import { useThemeConfig } from '/@/stores/themeConfig';
import logoMini from '/@/assets/logo-mini.svg';
import {SystemConfigStore} from "/@/stores/systemConfig";
// 定义变量内容
const storesThemeConfig = useThemeConfig();
@@ -28,6 +29,13 @@ const onThemeConfigChange = () => {
if (themeConfig.value.layout === 'transverse') return false;
themeConfig.value.isCollapse = !themeConfig.value.isCollapse;
};
const systemConfigStore = SystemConfigStore()
const {systemConfig} = storeToRefs(systemConfigStore)
const getSystemConfig = computed(()=>{
return systemConfig.value
})
</script>
<style scoped lang="scss">

View File

@@ -36,7 +36,7 @@ import { reactive, computed, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { useThemeConfig } from '/@/stores/themeConfig';
import { Local } from '/@/utils/storage';
import { Local,Session } from '/@/utils/storage';
// 定义变量内容
const { t } = useI18n();
@@ -57,6 +57,7 @@ const getThemeConfig = computed(() => {
// 残忍拒绝
const onCancel = () => {
state.isUpgrade = false;
Session.set('isUpgrade', false)
};
// 马上更新
const onUpgrade = () => {
@@ -66,13 +67,17 @@ const onUpgrade = () => {
Local.clear();
window.location.reload();
Local.set('version', state.version);
Session.set('isUpgrade', false)
}, 2000);
};
// 延迟显示,防止刷新时界面显示太快
const delayShow = () => {
const isUpgrade = Session.get('isUpgrade')===false?Session.get('isUpgrade'):true
if(isUpgrade){
setTimeout(() => {
state.isUpgrade = true;
}, 2000);
}
};
// 页面加载时
onMounted(() => {

View File

@@ -12,14 +12,13 @@ import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
import { useMenuApi } from '/@/api/menu/index';
import { handleMenu } from '../utils/menu';
import { BtnPermissionStore } from '/@/plugin/permission/store.permission';
import {SystemConfigStore} from "/@/stores/systemConfig";
const menuApi = useMenuApi();
const layouModules: any = import.meta.glob('../layout/routerView/*.{vue,tsx}');
const viewsModules: any = import.meta.glob('../views/**/*.{vue,tsx}');
// 后端控制路由
/**
* 获取目录下的 .vue、.tsx 全部文件
* @method import.meta.glob
@@ -45,9 +44,12 @@ export async function initBackEndControlRoutes() {
await useUserInfo().setUserInfos();
// 获取路由菜单数据
const res = await getBackEndControlRoutes();
// 无登录权限时,添加判断
// https://gitee.com/lyt-top/vue-next-admin/issues/I64HVO
if (res.data.length <= 0) return Promise.resolve(true);
// 处理路由component替换 dynamicRoutes/@/router/route第一个顶级 children 的路由
dynamicRoutes[0].children = await backEndComponent(handleMenu(res.data));
const {frameIn,frameOut} = handleMenu(res.data)
dynamicRoutes[0].children = await backEndComponent(frameIn);
// 添加动态路由
await setAddRoute();
// 设置路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
@@ -80,7 +82,10 @@ export function setCacheTagsViewRoutes() {
* @returns 返回替换后的路由数组
*/
export function setFilterRouteEnd() {
console.log(dynamicRoutes)
let filterRouteEnd: any = formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes));
// notFoundAndNoPower 防止 404、401 不在 layout 布局中不设置的话404、401 界面将全屏显示
// 关联问题 No match found for location with path 'xxx'
filterRouteEnd[0].children = [...filterRouteEnd[0].children, ...notFoundAndNoPower];
return filterRouteEnd;
}
@@ -105,6 +110,8 @@ export async function setAddRoute() {
export function getBackEndControlRoutes() {
//获取所有的按钮权限
BtnPermissionStore().getBtnPermissionStore();
// 获取系统配置
SystemConfigStore().getSystemConfigs()
return menuApi.getSystemMenu();
}
@@ -126,6 +133,37 @@ export function backEndComponent(routes: any) {
if (!routes) return;
return routes.map((item: any) => {
if (item.component) item.component = dynamicImport(dynamicViewsModules, item.component as string);
if(item.is_catalog){
// 对目录的处理
item.component = dynamicImport(dynamicViewsModules, 'layout/routerView/parent')
}
if(item.is_link){
// 对外链接的处理
item.meta.isIframe = !item.is_iframe
if(item.is_iframe){
item.component = dynamicImport(dynamicViewsModules, 'layout/routerView/link')
}else {
item.component = dynamicImport(dynamicViewsModules, 'layout/routerView/iframes')
}
}else{
console.log(item.is_iframe,item.web_path)
console.log(router.getRoutes())
if(item.is_iframe){
const iframeRoute:RouteRecordRaw = {
...item
}
console.log(iframeRoute)
router.addRoute(iframeRoute)
item.meta.isLink = item.path
item.path = `${item.path}Link`
item.name = `${item.name}Link`
item.meta.isIframe = !item.is_iframe
item.meta.isKeepAlive = false
item.meta.isIframeOpen = true
item.component = dynamicImport(dynamicViewsModules, 'layout/routerView/link.vue')
}
}
item.children && backEndComponent(item.children);
return item;
});

View File

@@ -7,7 +7,7 @@ import {useKeepALiveNames} from '/@/stores/keepAliveNames';
import {useRoutesList} from '/@/stores/routesList';
import {useThemeConfig} from '/@/stores/themeConfig';
import {Session} from '/@/utils/storage';
import {staticRoutes} from '/@/router/route';
import {notFoundAndNoPower,staticRoutes} from '/@/router/route';
import {initFrontEndControlRoutes} from '/@/router/frontEnd';
import {initBackEndControlRoutes} from '/@/router/backEnd';
@@ -32,7 +32,13 @@ const {isRequestRoutes} = themeConfig.value;
*/
export const router = createRouter({
history: createWebHashHistory(),
routes: staticRoutes,
/**
* 说明:
* 1、notFoundAndNoPower 默认添加 404、401 界面,防止一直提示 No match found for location with path 'xxx'
* 2、backEnd.ts(后端控制路由)、frontEnd.ts(前端控制路由) 中也需要加 notFoundAndNoPower 404、401 界面。
* 防止 404、401 不在 layout 布局中不设置的话404、401 界面将全屏显示
*/
routes: [...notFoundAndNoPower, ...staticRoutes]
});
/**
@@ -63,14 +69,7 @@ export function formatTwoStageRoutes(arr: any) {
const cacheList: Array<string> = [];
arr.forEach((v: any) => {
if (v.path === '/') {
newArr.push({
component: v.component,
name: v.name,
path: v.path,
redirect: v.redirect,
meta: v.meta,
children: []
});
newArr.push({component: v.component,name: v.name,path: v.path,redirect: v.redirect,meta: v.meta,children: []});
} else {
// 判断是否是动态路由xx/:id/:name用于 tagsView 等中使用
// 修复https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
@@ -114,13 +113,13 @@ router.beforeEach(async (to, from, next) => {
if (isRequestRoutes) {
// 后端控制路由:路由数据初始化,防止刷新时丢失
await initBackEndControlRoutes();
// 动态添加路由:防止非首页刷新时跳转回首页的问题
// 确保 addRoute() 时动态添加的路由已经被完全加载上去
next({...to, replace: true});
// 解决刷新时,一直跳 404 页面问题,关联问题 No match found for location with path 'xxx'
// to.query 防止页面刷新时普通路由带参数时参数丢失。动态路由xxx/:id/:name"isDynamic 无需处理
next({ path: to.path, query: to.query });
} else {
// https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP
await initFrontEndControlRoutes();
next({...to, replace: true});
next({ path: to.path, query: to.query });
}
} else {
next();

View File

@@ -88,4 +88,20 @@ export const staticRoutes: Array<RouteRecordRaw> = [
title: '登录',
},
},
{
path: '/operationLog',
name: 'operationLog',
component: () => import('/@/views/system/personal/index.vue'),
meta: {
title: 'message.router.personal'
},
},
// {
// path: '/demo',
// name: 'demo',
// component: () => import('/@/views/system/demo/index.vue'),
// meta: {
// title: 'message.router.personal'
// },
// }
];

View File

@@ -11,6 +11,7 @@ import { request } from '/@/utils/service';
import { FsExtendsEditor,FsExtendsUploader } from '@fast-crud/fast-extends';
import '@fast-crud/fast-extends/dist/style.css';
import { successMessage, successNotification } from '/@/utils/message';
import XEUtils from "xe-utils";
export default {
async install(app: any, options: any) {
// 先安装ui
@@ -20,8 +21,14 @@ export default {
//i18n, //i18n配置可选默认使用中文具体用法请看demo里的 src/i18n/index.js 文件
// 此处配置公共的dictRequest字典请求
async dictRequest({ dict }: any) {
const {isTree} = dict
console.log(222222,isTree)
//根据dict的url异步返回一个字典数组
return await request({ url: dict.url, params: dict.params || {} }).then((res:any)=>{
console.log(XEUtils.toArrayTree(res.data,{parentKey:'parent'}))
if(isTree){
return XEUtils.toArrayTree(res.data,{parentKey:'parent'})
}
return res.data
});
},
@@ -104,7 +111,8 @@ export default {
// 上传完成后的结果处理, 此处应返回格式为{url:xxx,key:xxx}
return {
url: getBaseURL() + ret.data.url,
key: ret.data.id
key: ret.data.id,
...ret.data
};
}
}

View File

@@ -22,5 +22,8 @@ export const useRoutesList = defineStore('routesList', {
async setColumnsNavHover(bool: Boolean) {
this.isColumnsNavHover = bool;
},
async addRoutesList(data: Array<string>) {
this.routesList.push(data);
}
},
});

130
web/src/utils/commonCrud.ts Normal file
View File

@@ -0,0 +1,130 @@
import { dict } from "@fast-crud/fast-crud";
export const commonCrudConfig = (options = {
create_datetime: {
form: false,
table: false,
search: false
},
update_datetime: {
form: false,
table: false,
search: false
},
creator_name: {
form: false,
table: false,
search: false
},
modifier_name: {
form: false,
table: false,
search: false
},
dept_belong_id: {
form: false,
table: false,
search: false
},
description: {
form: false,
table: false,
search: false
},
}) => {
return {
description: {
title: '备注',
search: {
show: options.description?.search || false
},
type: 'textarea',
column: {
show: options.description?.table || false,
},
form: {
component: {
show: options.description?.form || false,
placeholder: '请输入内容',
showWordLimit: true,
maxlength: '200',
}
}
},
modifier_name: {
title: '修改人',
search: {
show: options.modifier_name?.search || false
},
column: {
width: 100,
show: options.modifier_name?.table || false,
}
},
update_datetime: {
title: '更新时间',
type: 'datetime',
search: {
show: options.update_datetime?.search || false
},
column: {
width: 160,
show: options.update_datetime?.table || false,
}
},
creator_name: {
title: '创建人',
search: {
show: options.creator_name?.search || false
},
column: {
width: 100,
show: options.creator_name?.table || false,
}
},
create_datetime: {
title: '创建时间',
type: 'datetime',
search: {
show: options.create_datetime?.search || false
},
column: {
width: 160,
show: options.create_datetime?.table || false,
}
},
dept_belong_id: {
title: '所属部门',
type: 'dict-tree',
search: {
show: false
},
dict: dict({
url: '/api/system/dept/all_dept/',
isTree: true,
value: 'id',
label: 'name',
children: 'children' // 数据字典中children字段的属性名
}),
column: {
width: 150,
show: options.dept_belong_id?.table || false,
},
form: {
component: {
show: options.dept_belong_id?.form || false,
multiple: false,
clearable: true,
props: {
props: {
// 为什么这里要写两层props
// 因为props属性名与fs的动态渲染的props命名冲突所以要多写一层
label: "name",
value: "id",
}
}
},
helper: "默认不填则为当前创建用户的部门ID"
}
}
}
}

View File

@@ -1,4 +1,5 @@
import XEUtils from "xe-utils"
import {dynamicRoutes, staticRoutes} from "/@/router/route";
/**
* @description: 处理后端菜单数据格式
@@ -10,27 +11,56 @@ export const handleMenu = (menuData: Array<any>) => {
const handleMeta = (item: any) => {
item.meta = {
title: item.title,
isLink: item.is_link,
isLink: item.link_url,
isHide: !item.visible,
isKeepAlive: item.cache,
isAffix: false,
isIframe: false,
isAffix: item.is_affix,
isIframe: item.is_iframe,
roles: ['admin'],
icon: item.icon
}
item.name = item.component_name
item.path = item.web_path
return item
}
menuData.forEach((val) => {
handleMeta(val)
val.path = val.web_path
})
const data = XEUtils.toArrayTree(menuData, {
// 处理框架外的路由
const handleFrame = (item: any) => {
if (item.is_iframe) {
item.meta = {
title: item.title,
isLink: item.link_url,
isHide: !item.visible,
isKeepAlive: item.cache,
isAffix: item.is_affix,
isIframe: item.is_iframe,
roles: ['admin'],
icon: item.icon
}
item.name = item.component_name
item.path = item.web_path
}
return item
}
// 框架内路由
const defaultRoutes:Array<any> = []
// 框架外路由
const iframeRoutes:Array<any> = []
menuData.forEach((val) => {
// if (val.is_iframe) {
// // iframeRoutes.push(handleFrame(val))
// } else {
// defaultRoutes.push(handleMeta(val))
// }
defaultRoutes.push(handleMeta(val))
})
const data = XEUtils.toArrayTree(defaultRoutes, {
parentKey: 'parent',
strict: true,
})
const menu = [
const dynamicRoutes = [
{
path: '/home', name: 'home', component: '/system/home/index', meta: {
title: 'message.router.home',
@@ -45,5 +75,5 @@ export const handleMenu = (menuData: Array<any>) => {
},
...data
]
return menu
return {frameIn:dynamicRoutes,frameOut:iframeRoutes}
}

View File

@@ -96,12 +96,13 @@ function createService() {
return dataAxios;
case 4000:
errorCreate(`${dataAxios.msg}: ${response.config.url}`);
return dataAxios;
break;
default:
// 不是正确的 code
errorCreate(`${dataAxios.msg}: ${response.config.url}`);
return dataAxios;
break;
}
return Promise.reject(dataAxios);
}
},
(error) => {

View File

@@ -2,6 +2,7 @@
const cssCdnUrlList: Array<string> = [
'//at.alicdn.com/t/font_2298093_y6u00apwst.css',
'//at.alicdn.com/t/c/font_3882322_9ah7y8m9175.css', //dvadmin3项目用icon
'//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'
];
// 第三方 js url
const jsCdnUrlList: Array<string> = [];

View File

@@ -0,0 +1,13 @@
<template>
<div>
测试框架外显示
</div>
</template>
<script setup lang="ts" name="demo">
</script>
<style scoped>
</style>

View File

@@ -126,6 +126,7 @@ export default defineComponent({
});
};
const refreshCaptcha = async () => {
state.ruleForm.captcha=''
loginApi.getCaptcha().then((ret: any) => {
state.ruleForm.captchaImgBase = ret.data.image_base;
state.ruleForm.captchaKey = ret.data.key;
@@ -150,10 +151,10 @@ export default defineComponent({
// 执行完 initBackEndControlRoutes再执行 signInSuccess
loginSuccess();
}
} else if (res.code === 4000) {
}
}).catch((err: any) => {
// 登录错误之后,刷新验证码
refreshCaptcha();
}
});
} else {
errorMessage("请填写登录信息")

View File

@@ -18,7 +18,7 @@
<span class="login-right-warp-one"></span>
<span class="login-right-warp-two"></span>
<div class="login-right-warp-mian">
<div class="login-right-warp-main-title">{{ getThemeConfig.globalTitle }} 欢迎您</div>
<div class="login-right-warp-main-title">{{ getSystemConfig['login.site_title'] || getThemeConfig.globalTitle }} 欢迎您</div>
<div class="login-right-warp-main-form">
<div v-if="!state.isScan">
<el-tabs v-model="state.tabsActiveName">

View File

@@ -103,6 +103,9 @@ export const createCrudOptions = function ({ crudExpose, props,modelDialog,selec
label:'title',
value:'key'
}),
column:{
sortable: true,
},
form: {
rules: [
// 表单校验规则
@@ -113,6 +116,13 @@ export const createCrudOptions = function ({ crudExpose, props,modelDialog,selec
],
component: {
span: 12,
showSearch: true,
filterable: true,
//默认的filterOption仅支持value的过滤label并不会加入查询
//所以需要自定义filterOption
filterOption(inputValue, option) {
return option.label.indexOf(inputValue) >= 0 || option.value.indexOf(inputValue) >= 0;
}
},
},
},
@@ -143,6 +153,9 @@ export const createCrudOptions = function ({ crudExpose, props,modelDialog,selec
search: {
show: true,
},
column:{
sortable: true,
},
form: {
rules: [
// 表单校验规则
@@ -157,83 +170,6 @@ export const createCrudOptions = function ({ crudExpose, props,modelDialog,selec
},
},
},
// is_create: {
// title: '创建时显示',
// sortable: 'custom',
// search: {
// disabled: true,
// },
// type: 'dict-switch',
// dict: dict({
// data: [
// { value: true, label: '启用' },
// { value: false, label: '禁用' },
// ],
// }),
// form: {
// value: true,
// },
// column: {
// valueChange(context){
// return api.UpdateObj(context.row)
// },
// component: {
// name: 'fs-dict-switch',
// },
// },
// },
// is_update: {
// title: '编辑时显示',
// search: {
// show: true,
// },
// type: 'dict-switch',
// dict: dict({
// data: [
// { value: true, label: '启用' },
// { value: false, label: '禁用' },
// ],
// }),
// form: {
// value: true,
// },
// column: {
// component: {
// name: 'fs-dict-switch',
// onChange: compute((context) => {
// //动态onChange方法测试
// return () => {
// console.log('onChange', context.row.switch);
// };
// }),
// },
// },
// },
// is_query: {
// title: '列表中显示',
// type: 'dict-switch',
// dict: dict({
// data: [
// { value: true, label: '启用' },
// { value: false, label: '禁用' },
// ],
// }),
// form: {
// value: true,
// },
// column: {
// component: {
// name: 'fs-dict-switch',
// onChange: compute((context) => {
// //动态onChange方法测试
// return () => {
// console.log('onChange', context.row.switch);
// };
// }),
// },
// },
// },
},
},
};

View File

@@ -56,6 +56,16 @@
<el-switch v-model="menuFormData.is_link" width="60" inline-prompt active-text="是" inactive-text="否" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item required v-if="!menuFormData.is_catalog" label="是否固定">
<el-switch v-model="menuFormData.is_affix" width="60" inline-prompt active-text="是" inactive-text="否" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item v-if="!menuFormData.is_catalog" required label="框外显示">
<el-switch v-model="menuFormData.is_iframe" width="60" inline-prompt active-text="是" inactive-text="否" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注">
@@ -81,8 +91,8 @@
<el-input v-model="menuFormData.component_name" placeholder="请输入组件名称" />
</el-form-item>
<el-form-item v-if="!menuFormData.is_catalog && menuFormData.is_link" label="Url" prop="web_path">
<el-input v-model="menuFormData.web_path" placeholder="请输入Url" />
<el-form-item v-if="!menuFormData.is_catalog && menuFormData.is_link" label="外链接" prop="link_url">
<el-input v-model="menuFormData.link_url" placeholder="请输入外链接地址" />
</el-form-item>
<el-form-item v-if="!menuFormData.is_catalog" label="缓存">
@@ -128,9 +138,19 @@ const defaultTreeProps: any = {
},
};
const validateWebPath = (rule: any, value: string, callback: Function) => {
let pattern = /^\/.*?/;
const reg = pattern.test(value);
if (reg) {
callback();
} else {
callback(new Error('请输入正确的地址'));
}
};
const validateLinkUrl = (rule: any, value: string, callback: Function) => {
let pattern = /^\/.*?/;
let patternUrl = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/;
const reg = menuFormData.is_link ? patternUrl.test(value) : pattern.test(value);
const reg = pattern.test(value) || patternUrl.test(value)
if (reg) {
callback();
} else {
@@ -152,6 +172,7 @@ const rules = reactive<FormRules>({
name: [{ required: true, message: '菜单名称必填', trigger: 'blur' }],
component: [{ required: true, message: '请输入组件地址', trigger: 'blur' }],
component_name: [{ required: true, message: '请输入组件名称', trigger: 'blur' }],
link_url: [{ required: true, message: '请输入外链接地址',validator:validateLinkUrl, trigger: 'blur' }],
});
let deptDefaultList = ref<MenuTreeItemType[]>([]);
@@ -168,6 +189,9 @@ let menuFormData = reactive<MenuFormDataType>({
description: '',
is_catalog: false,
is_link: false,
is_iframe: false,
is_affix: false,
link_url:''
});
let menuBtnLoading = ref(false);
@@ -186,6 +210,9 @@ const setMenuFormData = () => {
menuFormData.description = props.initFormData?.description || '';
menuFormData.is_catalog = !!props.initFormData.is_catalog;
menuFormData.is_link = !!props.initFormData.is_link;
menuFormData.is_iframe =!!props.initFormData.is_iframe;
menuFormData.is_affix =!!props.initFormData.is_affix;
menuFormData.link_url =props.initFormData.link_url;
}
};

View File

@@ -44,6 +44,9 @@ export interface MenuTreeItemType {
visible: boolean;
creator: string;
parent: number | string;
is_iframe:boolean;
is_affix:boolean;
link_url:string;
}
export interface MenuFormDataType {
@@ -60,4 +63,7 @@ export interface MenuFormDataType {
description: string;
is_catalog: boolean;
is_link: boolean;
is_iframe:boolean;
is_affix:boolean;
link_url: string;
}