Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
@@ -155,6 +155,11 @@ STATICFILES_DIRS = [
|
|||||||
MEDIA_ROOT = "media" # 项目下的目录
|
MEDIA_ROOT = "media" # 项目下的目录
|
||||||
MEDIA_URL = "/media/" # 跟STATIC_URL类似,指定用户可以通过这个url找到文件
|
MEDIA_URL = "/media/" # 跟STATIC_URL类似,指定用户可以通过这个url找到文件
|
||||||
|
|
||||||
|
#添加以下代码以后就不用写{% load staticfiles %},可以直接引用
|
||||||
|
STATICFILES_FINDERS = (
|
||||||
|
"django.contrib.staticfiles.finders.FileSystemFinder",
|
||||||
|
"django.contrib.staticfiles.finders.AppDirectoriesFinder"
|
||||||
|
)
|
||||||
# 收集静态文件,必须将 MEDIA_ROOT,STATICFILES_DIRS先注释
|
# 收集静态文件,必须将 MEDIA_ROOT,STATICFILES_DIRS先注释
|
||||||
# python manage.py collectstatic
|
# python manage.py collectstatic
|
||||||
# STATIC_ROOT=os.path.join(BASE_DIR,'static')
|
# STATIC_ROOT=os.path.join(BASE_DIR,'static')
|
||||||
@@ -403,5 +408,6 @@ PLUGINS_URL_PATTERNS = []
|
|||||||
# from dvadmin_third.settings import * # 第三方用户管理
|
# from dvadmin_third.settings import * # 第三方用户管理
|
||||||
# from dvadmin_ak_sk.settings import * # 秘钥管理管理
|
# from dvadmin_ak_sk.settings import * # 秘钥管理管理
|
||||||
# from dvadmin_tenants.settings import * # 租户管理
|
# from dvadmin_tenants.settings import * # 租户管理
|
||||||
|
from dvadmin_social_auth.settings import *
|
||||||
# ...
|
# ...
|
||||||
# ********** 一键导入插件配置结束 **********
|
# ********** 一键导入插件配置结束 **********
|
||||||
|
|||||||
@@ -182,7 +182,7 @@
|
|||||||
"parent": 1,
|
"parent": 1,
|
||||||
"title": "隐私链接",
|
"title": "隐私链接",
|
||||||
"key": "privacy_url",
|
"key": "privacy_url",
|
||||||
"value": "#",
|
"value": "/api/system/clause/privacy.html",
|
||||||
"sort": 7,
|
"sort": 7,
|
||||||
"status": true,
|
"status": true,
|
||||||
"data_options": null,
|
"data_options": null,
|
||||||
@@ -196,7 +196,7 @@
|
|||||||
"parent": 1,
|
"parent": 1,
|
||||||
"title": "条款链接",
|
"title": "条款链接",
|
||||||
"key": "clause_url",
|
"key": "clause_url",
|
||||||
"value": "#",
|
"value": "/api/system/clause/terms_service.html",
|
||||||
"sort": 8,
|
"sort": 8,
|
||||||
"status": true,
|
"status": true,
|
||||||
"data_options": null,
|
"data_options": null,
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ class Menu(CoreModel):
|
|||||||
(1, "是"),
|
(1, "是"),
|
||||||
)
|
)
|
||||||
is_link = models.BooleanField(default=False, verbose_name="是否外链", help_text="是否外链")
|
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="是否目录")
|
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="路由地址")
|
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="组件地址")
|
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="是否页面缓存")
|
cache = models.BooleanField(default=False, blank=True, verbose_name="是否页面缓存", help_text="是否页面缓存")
|
||||||
visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示",
|
visible = models.BooleanField(default=True, blank=True, verbose_name="侧边栏中是否显示",
|
||||||
help_text="侧边栏中是否显示")
|
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:
|
class Meta:
|
||||||
db_table = table_prefix + "system_menu"
|
db_table = table_prefix + "system_menu"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from rest_framework import routers
|
|||||||
|
|
||||||
from dvadmin.system.views.api_white_list import ApiWhiteListViewSet
|
from dvadmin.system.views.api_white_list import ApiWhiteListViewSet
|
||||||
from dvadmin.system.views.area import AreaViewSet
|
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.dept import DeptViewSet
|
||||||
from dvadmin.system.views.dictionary import DictionaryViewSet
|
from dvadmin.system.views.dictionary import DictionaryViewSet
|
||||||
from dvadmin.system.views.file_list import FileViewSet
|
from dvadmin.system.views.file_list import FileViewSet
|
||||||
@@ -46,5 +47,7 @@ urlpatterns = [
|
|||||||
path('login_log/', LoginLogViewSet.as_view({'get': 'list'})),
|
path('login_log/', LoginLogViewSet.as_view({'get': 'list'})),
|
||||||
path('login_log/<int:pk>/', LoginLogViewSet.as_view({'get': 'retrieve'})),
|
path('login_log/<int:pk>/', LoginLogViewSet.as_view({'get': 'retrieve'})),
|
||||||
path('dept_lazy_tree/', DeptViewSet.as_view({'get': 'dept_lazy_tree'})),
|
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
|
urlpatterns += system_url.urls
|
||||||
|
|||||||
23
backend/dvadmin/system/views/clause.py
Normal file
23
backend/dvadmin/system/views/clause.py
Normal 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')
|
||||||
@@ -71,8 +71,8 @@ class WebRouterSerializer(CustomModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Menu
|
model = Menu
|
||||||
fields = (
|
fields = (
|
||||||
'id', 'parent', 'icon', 'sort', 'path', 'name', 'title', 'is_link', 'is_catalog', 'web_path', 'component',
|
'id', 'parent', 'icon', 'sort', 'path', 'name', 'title', 'is_link','link_url', 'is_catalog', 'web_path', 'component',
|
||||||
'component_name', 'cache', 'visible', 'status')
|
'component_name', 'cache', 'visible','is_iframe','is_affix', 'status')
|
||||||
read_only_fields = ["id"]
|
read_only_fields = ["id"]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
34
backend/static/clause/privacy.css
Normal file
34
backend/static/clause/privacy.css
Normal 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;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
233
backend/templates/privacy.html
Normal file
233
backend/templates/privacy.html
Normal 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>
|
||||||
96
backend/templates/terms_service.html
Normal file
96
backend/templates/terms_service.html
Normal 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>
|
||||||
2
web/.env
2
web/.env
@@ -1,6 +1,6 @@
|
|||||||
# port 端口号
|
# port 端口号
|
||||||
VITE_PORT = 8080
|
VITE_PORT = 8080
|
||||||
|
VITE_API_URL = 'http://dvadmin3api.django.icu:8001'
|
||||||
# open 运行 npm run dev 时自动打开浏览器
|
# open 运行 npm run dev 时自动打开浏览器
|
||||||
VITE_OPEN = false
|
VITE_OPEN = false
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
|
<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
|
||||||
<img :src="logoMini" class="layout-logo-medium-img" />
|
<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>
|
||||||
<div class="layout-logo-size" v-else @click="onThemeConfigChange">
|
<div class="layout-logo-size" v-else @click="onThemeConfigChange">
|
||||||
<img :src="logoMini" class="layout-logo-size-img" />
|
<img :src="logoMini" class="layout-logo-size-img" />
|
||||||
@@ -13,6 +13,7 @@ import { computed } from 'vue';
|
|||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||||
import logoMini from '/@/assets/logo-mini.svg';
|
import logoMini from '/@/assets/logo-mini.svg';
|
||||||
|
import {SystemConfigStore} from "/@/stores/systemConfig";
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const storesThemeConfig = useThemeConfig();
|
const storesThemeConfig = useThemeConfig();
|
||||||
@@ -28,6 +29,13 @@ const onThemeConfigChange = () => {
|
|||||||
if (themeConfig.value.layout === 'transverse') return false;
|
if (themeConfig.value.layout === 'transverse') return false;
|
||||||
themeConfig.value.isCollapse = !themeConfig.value.isCollapse;
|
themeConfig.value.isCollapse = !themeConfig.value.isCollapse;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const systemConfigStore = SystemConfigStore()
|
||||||
|
const {systemConfig} = storeToRefs(systemConfigStore)
|
||||||
|
const getSystemConfig = computed(()=>{
|
||||||
|
return systemConfig.value
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import { reactive, computed, onMounted } from 'vue';
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useThemeConfig } from '/@/stores/themeConfig';
|
import { useThemeConfig } from '/@/stores/themeConfig';
|
||||||
import { Local } from '/@/utils/storage';
|
import { Local,Session } from '/@/utils/storage';
|
||||||
|
|
||||||
// 定义变量内容
|
// 定义变量内容
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -57,6 +57,7 @@ const getThemeConfig = computed(() => {
|
|||||||
// 残忍拒绝
|
// 残忍拒绝
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
state.isUpgrade = false;
|
state.isUpgrade = false;
|
||||||
|
Session.set('isUpgrade', false)
|
||||||
};
|
};
|
||||||
// 马上更新
|
// 马上更新
|
||||||
const onUpgrade = () => {
|
const onUpgrade = () => {
|
||||||
@@ -66,13 +67,17 @@ const onUpgrade = () => {
|
|||||||
Local.clear();
|
Local.clear();
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
Local.set('version', state.version);
|
Local.set('version', state.version);
|
||||||
|
Session.set('isUpgrade', false)
|
||||||
}, 2000);
|
}, 2000);
|
||||||
};
|
};
|
||||||
// 延迟显示,防止刷新时界面显示太快
|
// 延迟显示,防止刷新时界面显示太快
|
||||||
const delayShow = () => {
|
const delayShow = () => {
|
||||||
|
const isUpgrade = Session.get('isUpgrade')===false?Session.get('isUpgrade'):true
|
||||||
|
if(isUpgrade){
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
state.isUpgrade = true;
|
state.isUpgrade = true;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// 页面加载时
|
// 页面加载时
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -12,14 +12,13 @@ import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
|
|||||||
import { useMenuApi } from '/@/api/menu/index';
|
import { useMenuApi } from '/@/api/menu/index';
|
||||||
import { handleMenu } from '../utils/menu';
|
import { handleMenu } from '../utils/menu';
|
||||||
import { BtnPermissionStore } from '/@/plugin/permission/store.permission';
|
import { BtnPermissionStore } from '/@/plugin/permission/store.permission';
|
||||||
|
import {SystemConfigStore} from "/@/stores/systemConfig";
|
||||||
|
|
||||||
const menuApi = useMenuApi();
|
const menuApi = useMenuApi();
|
||||||
|
|
||||||
const layouModules: any = import.meta.glob('../layout/routerView/*.{vue,tsx}');
|
const layouModules: any = import.meta.glob('../layout/routerView/*.{vue,tsx}');
|
||||||
const viewsModules: any = import.meta.glob('../views/**/*.{vue,tsx}');
|
const viewsModules: any = import.meta.glob('../views/**/*.{vue,tsx}');
|
||||||
|
|
||||||
// 后端控制路由
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取目录下的 .vue、.tsx 全部文件
|
* 获取目录下的 .vue、.tsx 全部文件
|
||||||
* @method import.meta.glob
|
* @method import.meta.glob
|
||||||
@@ -45,9 +44,12 @@ export async function initBackEndControlRoutes() {
|
|||||||
await useUserInfo().setUserInfos();
|
await useUserInfo().setUserInfos();
|
||||||
// 获取路由菜单数据
|
// 获取路由菜单数据
|
||||||
const res = await getBackEndControlRoutes();
|
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 的路由
|
// 处理路由(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();
|
await setAddRoute();
|
||||||
// 设置路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
// 设置路由到 vuex routesList 中(已处理成多级嵌套路由)及缓存多级嵌套数组处理后的一维数组
|
||||||
@@ -80,7 +82,10 @@ export function setCacheTagsViewRoutes() {
|
|||||||
* @returns 返回替换后的路由数组
|
* @returns 返回替换后的路由数组
|
||||||
*/
|
*/
|
||||||
export function setFilterRouteEnd() {
|
export function setFilterRouteEnd() {
|
||||||
|
console.log(dynamicRoutes)
|
||||||
let filterRouteEnd: any = formatTwoStageRoutes(formatFlatteningRoutes(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];
|
filterRouteEnd[0].children = [...filterRouteEnd[0].children, ...notFoundAndNoPower];
|
||||||
return filterRouteEnd;
|
return filterRouteEnd;
|
||||||
}
|
}
|
||||||
@@ -105,6 +110,8 @@ export async function setAddRoute() {
|
|||||||
export function getBackEndControlRoutes() {
|
export function getBackEndControlRoutes() {
|
||||||
//获取所有的按钮权限
|
//获取所有的按钮权限
|
||||||
BtnPermissionStore().getBtnPermissionStore();
|
BtnPermissionStore().getBtnPermissionStore();
|
||||||
|
// 获取系统配置
|
||||||
|
SystemConfigStore().getSystemConfigs()
|
||||||
return menuApi.getSystemMenu();
|
return menuApi.getSystemMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +133,37 @@ export function backEndComponent(routes: any) {
|
|||||||
if (!routes) return;
|
if (!routes) return;
|
||||||
return routes.map((item: any) => {
|
return routes.map((item: any) => {
|
||||||
if (item.component) item.component = dynamicImport(dynamicViewsModules, item.component as string);
|
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);
|
item.children && backEndComponent(item.children);
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {useKeepALiveNames} from '/@/stores/keepAliveNames';
|
|||||||
import {useRoutesList} from '/@/stores/routesList';
|
import {useRoutesList} from '/@/stores/routesList';
|
||||||
import {useThemeConfig} from '/@/stores/themeConfig';
|
import {useThemeConfig} from '/@/stores/themeConfig';
|
||||||
import {Session} from '/@/utils/storage';
|
import {Session} from '/@/utils/storage';
|
||||||
import {staticRoutes} from '/@/router/route';
|
import {notFoundAndNoPower,staticRoutes} from '/@/router/route';
|
||||||
import {initFrontEndControlRoutes} from '/@/router/frontEnd';
|
import {initFrontEndControlRoutes} from '/@/router/frontEnd';
|
||||||
import {initBackEndControlRoutes} from '/@/router/backEnd';
|
import {initBackEndControlRoutes} from '/@/router/backEnd';
|
||||||
|
|
||||||
@@ -32,7 +32,13 @@ const {isRequestRoutes} = themeConfig.value;
|
|||||||
*/
|
*/
|
||||||
export const router = createRouter({
|
export const router = createRouter({
|
||||||
history: createWebHashHistory(),
|
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> = [];
|
const cacheList: Array<string> = [];
|
||||||
arr.forEach((v: any) => {
|
arr.forEach((v: any) => {
|
||||||
if (v.path === '/') {
|
if (v.path === '/') {
|
||||||
newArr.push({
|
newArr.push({component: v.component,name: v.name,path: v.path,redirect: v.redirect,meta: v.meta,children: []});
|
||||||
component: v.component,
|
|
||||||
name: v.name,
|
|
||||||
path: v.path,
|
|
||||||
redirect: v.redirect,
|
|
||||||
meta: v.meta,
|
|
||||||
children: []
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// 判断是否是动态路由(xx/:id/:name),用于 tagsView 等中使用
|
// 判断是否是动态路由(xx/:id/:name),用于 tagsView 等中使用
|
||||||
// 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
|
// 修复:https://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G
|
||||||
@@ -114,13 +113,13 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
if (isRequestRoutes) {
|
if (isRequestRoutes) {
|
||||||
// 后端控制路由:路由数据初始化,防止刷新时丢失
|
// 后端控制路由:路由数据初始化,防止刷新时丢失
|
||||||
await initBackEndControlRoutes();
|
await initBackEndControlRoutes();
|
||||||
// 动态添加路由:防止非首页刷新时跳转回首页的问题
|
// 解决刷新时,一直跳 404 页面问题,关联问题 No match found for location with path 'xxx'
|
||||||
// 确保 addRoute() 时动态添加的路由已经被完全加载上去
|
// to.query 防止页面刷新时,普通路由带参数时,参数丢失。动态路由(xxx/:id/:name")isDynamic 无需处理
|
||||||
next({...to, replace: true});
|
next({ path: to.path, query: to.query });
|
||||||
} else {
|
} else {
|
||||||
// https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP
|
// https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP
|
||||||
await initFrontEndControlRoutes();
|
await initFrontEndControlRoutes();
|
||||||
next({...to, replace: true});
|
next({ path: to.path, query: to.query });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
|
|||||||
@@ -88,4 +88,20 @@ export const staticRoutes: Array<RouteRecordRaw> = [
|
|||||||
title: '登录',
|
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'
|
||||||
|
// },
|
||||||
|
// }
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { request } from '/@/utils/service';
|
|||||||
import { FsExtendsEditor,FsExtendsUploader } from '@fast-crud/fast-extends';
|
import { FsExtendsEditor,FsExtendsUploader } from '@fast-crud/fast-extends';
|
||||||
import '@fast-crud/fast-extends/dist/style.css';
|
import '@fast-crud/fast-extends/dist/style.css';
|
||||||
import { successMessage, successNotification } from '/@/utils/message';
|
import { successMessage, successNotification } from '/@/utils/message';
|
||||||
|
import XEUtils from "xe-utils";
|
||||||
export default {
|
export default {
|
||||||
async install(app: any, options: any) {
|
async install(app: any, options: any) {
|
||||||
// 先安装ui
|
// 先安装ui
|
||||||
@@ -20,8 +21,14 @@ export default {
|
|||||||
//i18n, //i18n配置,可选,默认使用中文,具体用法请看demo里的 src/i18n/index.js 文件
|
//i18n, //i18n配置,可选,默认使用中文,具体用法请看demo里的 src/i18n/index.js 文件
|
||||||
// 此处配置公共的dictRequest(字典请求)
|
// 此处配置公共的dictRequest(字典请求)
|
||||||
async dictRequest({ dict }: any) {
|
async dictRequest({ dict }: any) {
|
||||||
|
const {isTree} = dict
|
||||||
|
console.log(222222,isTree)
|
||||||
//根据dict的url,异步返回一个字典数组
|
//根据dict的url,异步返回一个字典数组
|
||||||
return await request({ url: dict.url, params: dict.params || {} }).then((res:any)=>{
|
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
|
return res.data
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -104,7 +111,8 @@ export default {
|
|||||||
// 上传完成后的结果处理, 此处应返回格式为{url:xxx,key:xxx}
|
// 上传完成后的结果处理, 此处应返回格式为{url:xxx,key:xxx}
|
||||||
return {
|
return {
|
||||||
url: getBaseURL() + ret.data.url,
|
url: getBaseURL() + ret.data.url,
|
||||||
key: ret.data.id
|
key: ret.data.id,
|
||||||
|
...ret.data
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,5 +22,8 @@ export const useRoutesList = defineStore('routesList', {
|
|||||||
async setColumnsNavHover(bool: Boolean) {
|
async setColumnsNavHover(bool: Boolean) {
|
||||||
this.isColumnsNavHover = bool;
|
this.isColumnsNavHover = bool;
|
||||||
},
|
},
|
||||||
|
async addRoutesList(data: Array<string>) {
|
||||||
|
this.routesList.push(data);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
130
web/src/utils/commonCrud.ts
Normal file
130
web/src/utils/commonCrud.ts
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import XEUtils from "xe-utils"
|
import XEUtils from "xe-utils"
|
||||||
|
import {dynamicRoutes, staticRoutes} from "/@/router/route";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description: 处理后端菜单数据格式
|
* @description: 处理后端菜单数据格式
|
||||||
@@ -10,27 +11,56 @@ export const handleMenu = (menuData: Array<any>) => {
|
|||||||
const handleMeta = (item: any) => {
|
const handleMeta = (item: any) => {
|
||||||
item.meta = {
|
item.meta = {
|
||||||
title: item.title,
|
title: item.title,
|
||||||
isLink: item.is_link,
|
isLink: item.link_url,
|
||||||
isHide: !item.visible,
|
isHide: !item.visible,
|
||||||
isKeepAlive: item.cache,
|
isKeepAlive: item.cache,
|
||||||
isAffix: false,
|
isAffix: item.is_affix,
|
||||||
isIframe: false,
|
isIframe: item.is_iframe,
|
||||||
roles: ['admin'],
|
roles: ['admin'],
|
||||||
icon: item.icon
|
icon: item.icon
|
||||||
}
|
}
|
||||||
item.name = item.component_name
|
item.name = item.component_name
|
||||||
|
item.path = item.web_path
|
||||||
return item
|
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',
|
parentKey: 'parent',
|
||||||
strict: true,
|
strict: true,
|
||||||
})
|
})
|
||||||
const menu = [
|
const dynamicRoutes = [
|
||||||
{
|
{
|
||||||
path: '/home', name: 'home', component: '/system/home/index', meta: {
|
path: '/home', name: 'home', component: '/system/home/index', meta: {
|
||||||
title: 'message.router.home',
|
title: 'message.router.home',
|
||||||
@@ -45,5 +75,5 @@ export const handleMenu = (menuData: Array<any>) => {
|
|||||||
},
|
},
|
||||||
...data
|
...data
|
||||||
]
|
]
|
||||||
return menu
|
return {frameIn:dynamicRoutes,frameOut:iframeRoutes}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,12 +96,13 @@ function createService() {
|
|||||||
return dataAxios;
|
return dataAxios;
|
||||||
case 4000:
|
case 4000:
|
||||||
errorCreate(`${dataAxios.msg}: ${response.config.url}`);
|
errorCreate(`${dataAxios.msg}: ${response.config.url}`);
|
||||||
return dataAxios;
|
break;
|
||||||
default:
|
default:
|
||||||
// 不是正确的 code
|
// 不是正确的 code
|
||||||
errorCreate(`${dataAxios.msg}: ${response.config.url}`);
|
errorCreate(`${dataAxios.msg}: ${response.config.url}`);
|
||||||
return dataAxios;
|
break;
|
||||||
}
|
}
|
||||||
|
return Promise.reject(dataAxios);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
const cssCdnUrlList: Array<string> = [
|
const cssCdnUrlList: Array<string> = [
|
||||||
'//at.alicdn.com/t/font_2298093_y6u00apwst.css',
|
'//at.alicdn.com/t/font_2298093_y6u00apwst.css',
|
||||||
'//at.alicdn.com/t/c/font_3882322_9ah7y8m9175.css', //dvadmin3项目用icon
|
'//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
|
// 第三方 js url
|
||||||
const jsCdnUrlList: Array<string> = [];
|
const jsCdnUrlList: Array<string> = [];
|
||||||
|
|||||||
13
web/src/views/system/demo/index.vue
Normal file
13
web/src/views/system/demo/index.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
测试框架外显示
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="demo">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -126,6 +126,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
const refreshCaptcha = async () => {
|
const refreshCaptcha = async () => {
|
||||||
|
state.ruleForm.captcha=''
|
||||||
loginApi.getCaptcha().then((ret: any) => {
|
loginApi.getCaptcha().then((ret: any) => {
|
||||||
state.ruleForm.captchaImgBase = ret.data.image_base;
|
state.ruleForm.captchaImgBase = ret.data.image_base;
|
||||||
state.ruleForm.captchaKey = ret.data.key;
|
state.ruleForm.captchaKey = ret.data.key;
|
||||||
@@ -150,10 +151,10 @@ export default defineComponent({
|
|||||||
// 执行完 initBackEndControlRoutes,再执行 signInSuccess
|
// 执行完 initBackEndControlRoutes,再执行 signInSuccess
|
||||||
loginSuccess();
|
loginSuccess();
|
||||||
}
|
}
|
||||||
} else if (res.code === 4000) {
|
}
|
||||||
|
}).catch((err: any) => {
|
||||||
// 登录错误之后,刷新验证码
|
// 登录错误之后,刷新验证码
|
||||||
refreshCaptcha();
|
refreshCaptcha();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
errorMessage("请填写登录信息")
|
errorMessage("请填写登录信息")
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<span class="login-right-warp-one"></span>
|
<span class="login-right-warp-one"></span>
|
||||||
<span class="login-right-warp-two"></span>
|
<span class="login-right-warp-two"></span>
|
||||||
<div class="login-right-warp-mian">
|
<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 class="login-right-warp-main-form">
|
||||||
<div v-if="!state.isScan">
|
<div v-if="!state.isScan">
|
||||||
<el-tabs v-model="state.tabsActiveName">
|
<el-tabs v-model="state.tabsActiveName">
|
||||||
|
|||||||
@@ -103,6 +103,9 @@ export const createCrudOptions = function ({ crudExpose, props,modelDialog,selec
|
|||||||
label:'title',
|
label:'title',
|
||||||
value:'key'
|
value:'key'
|
||||||
}),
|
}),
|
||||||
|
column:{
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
form: {
|
form: {
|
||||||
rules: [
|
rules: [
|
||||||
// 表单校验规则
|
// 表单校验规则
|
||||||
@@ -113,6 +116,13 @@ export const createCrudOptions = function ({ crudExpose, props,modelDialog,selec
|
|||||||
],
|
],
|
||||||
component: {
|
component: {
|
||||||
span: 12,
|
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: {
|
search: {
|
||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
|
column:{
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
form: {
|
form: {
|
||||||
rules: [
|
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);
|
|
||||||
// };
|
|
||||||
// }),
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -56,6 +56,16 @@
|
|||||||
<el-switch v-model="menuFormData.is_link" width="60" inline-prompt active-text="是" inactive-text="否" />
|
<el-switch v-model="menuFormData.is_link" width="60" inline-prompt active-text="是" inactive-text="否" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</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-row>
|
||||||
|
|
||||||
<el-form-item label="备注">
|
<el-form-item label="备注">
|
||||||
@@ -81,8 +91,8 @@
|
|||||||
<el-input v-model="menuFormData.component_name" placeholder="请输入组件名称" />
|
<el-input v-model="menuFormData.component_name" placeholder="请输入组件名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item v-if="!menuFormData.is_catalog && menuFormData.is_link" label="Url" prop="web_path">
|
<el-form-item v-if="!menuFormData.is_catalog && menuFormData.is_link" label="外链接" prop="link_url">
|
||||||
<el-input v-model="menuFormData.web_path" placeholder="请输入Url" />
|
<el-input v-model="menuFormData.link_url" placeholder="请输入外链接地址" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item v-if="!menuFormData.is_catalog" label="缓存">
|
<el-form-item v-if="!menuFormData.is_catalog" label="缓存">
|
||||||
@@ -128,9 +138,19 @@ const defaultTreeProps: any = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const validateWebPath = (rule: any, value: string, callback: Function) => {
|
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 pattern = /^\/.*?/;
|
||||||
let patternUrl = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/;
|
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) {
|
if (reg) {
|
||||||
callback();
|
callback();
|
||||||
} else {
|
} else {
|
||||||
@@ -152,6 +172,7 @@ const rules = reactive<FormRules>({
|
|||||||
name: [{ required: true, message: '菜单名称必填', trigger: 'blur' }],
|
name: [{ required: true, message: '菜单名称必填', trigger: 'blur' }],
|
||||||
component: [{ required: true, message: '请输入组件地址', trigger: 'blur' }],
|
component: [{ required: true, message: '请输入组件地址', trigger: 'blur' }],
|
||||||
component_name: [{ 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[]>([]);
|
let deptDefaultList = ref<MenuTreeItemType[]>([]);
|
||||||
@@ -168,6 +189,9 @@ let menuFormData = reactive<MenuFormDataType>({
|
|||||||
description: '',
|
description: '',
|
||||||
is_catalog: false,
|
is_catalog: false,
|
||||||
is_link: false,
|
is_link: false,
|
||||||
|
is_iframe: false,
|
||||||
|
is_affix: false,
|
||||||
|
link_url:''
|
||||||
});
|
});
|
||||||
let menuBtnLoading = ref(false);
|
let menuBtnLoading = ref(false);
|
||||||
|
|
||||||
@@ -186,6 +210,9 @@ const setMenuFormData = () => {
|
|||||||
menuFormData.description = props.initFormData?.description || '';
|
menuFormData.description = props.initFormData?.description || '';
|
||||||
menuFormData.is_catalog = !!props.initFormData.is_catalog;
|
menuFormData.is_catalog = !!props.initFormData.is_catalog;
|
||||||
menuFormData.is_link = !!props.initFormData.is_link;
|
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ export interface MenuTreeItemType {
|
|||||||
visible: boolean;
|
visible: boolean;
|
||||||
creator: string;
|
creator: string;
|
||||||
parent: number | string;
|
parent: number | string;
|
||||||
|
is_iframe:boolean;
|
||||||
|
is_affix:boolean;
|
||||||
|
link_url:string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MenuFormDataType {
|
export interface MenuFormDataType {
|
||||||
@@ -60,4 +63,7 @@ export interface MenuFormDataType {
|
|||||||
description: string;
|
description: string;
|
||||||
is_catalog: boolean;
|
is_catalog: boolean;
|
||||||
is_link: boolean;
|
is_link: boolean;
|
||||||
|
is_iframe:boolean;
|
||||||
|
is_affix:boolean;
|
||||||
|
link_url: string;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user