├── .idea
├── .gitignore
├── dataSources.xml
├── djangoProject_genshin_player_backend.iml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
└── vcs.xml
├── README.md
├── app
├── CONSTANTS.py
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ ├── 0001_initial.py
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
├── db.sqlite3
├── djangoProject_genshin_player_backend
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
├── image
├── ScreenShot1.JPG
└── ScreenShot2.JPG
├── manage.py
├── static
└── theme
│ ├── css
│ ├── bootstrap.min.css
│ ├── font-awesome.min.css
│ ├── i.css
│ ├── layer.css
│ └── style.css
│ ├── images
│ ├── HarmonyOS_Sans_SC_Medium.subset.woff2
│ ├── bg.jpg
│ └── favicon.ico
│ └── js
│ ├── clipboard.js
│ ├── jquery.min.js
│ ├── jquery.sliderBar.js
│ ├── layer.js
│ ├── pay.js
│ └── theme
│ └── default
│ └── layer.css
└── templates
├── cdkey兑换.html
├── 创建cdkey.html
├── 幸运抽奖.html
├── 每日签到.html
├── 用户后台.html
├── 登录认证.html
├── 解锁深渊.html
├── 设置世界等级.html
└── 远程执行.html
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/dataSources.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | sqlite.xerial
6 | true
7 | org.sqlite.JDBC
8 | jdbc:sqlite:C:\Users\DELL\PycharmProjects\djangoProject_genshin_player_backend\db.sqlite3
9 | $ProjectFileDir$
10 |
11 |
12 | file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.34.0/sqlite-jdbc-3.34.0.jar
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/djangoProject_genshin_player_backend.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
28 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Grasscutter-CDKeySystem - Grasscutter 外置CDKey
3 |
4 | 
5 |
6 | Grasscutter-CDKeySystem 是一个 [Grasscutter](https://github.com/Grasscutters/Grasscutter) 外置系统, 你可以用它来轻松的兑换和分发游戏的CDKey
7 |
8 | * 已适配YSGM(MUIP)官方服务端
9 |
10 | 推荐使用 Grasscutter 命令生成工具:
11 | [GrasscutterCommandGenerator](https://github.com/jie65535/GrasscutterCommandGenerator)
12 |
13 | 前端页面源自[blueyst](https://github.com/blueyst/blueyst.github.io)
14 |
15 | ## 💡Feature
16 |
17 | - [x] **通过opencommand连接Grasscutter.**
18 | - [x] **通过YSGM(MUIP)连接官方服务端.**
19 | - [x] **CDKey兑换** - 玩家可以兑换已经生成的CDKey.
20 | - [x] **CDKey生成** - 管理者可以生成CDKey的内容,支持批量生成。
21 | - [X] **开启地图和深渊** - 玩家可以一键开启地图和深渊(仅限Grasscutter).
22 | - [X] **设置世界等级** - 玩家可以任意设置世界等级(仅限Grasscutter).
23 | - [x] **远程执行** - 可以远程执行命令.
24 | - [x] **每日签到** - 签到系统(默认是Grasscutter的命令,每天1000摩拉).
25 | - [x] **自定义背景图** - 可以自定义页面的背景图链接(比如随机图)
26 | - [ ] **幸运抽奖** - 抽奖系统.
27 | - [ ] **更多** - Comming soon...
28 |
29 | ## 🍗Setup
30 | ### 安装
31 | 注意:
32 |
33 | 一旦确定好使用的连接方式就不要更改,否则可能会由于命令语法不兼容导致执行出错!
34 | 以下两种连接方式可以任选其一:
35 | #### 一、连接Grasscutter:
36 | >本项目基于 [opencommand-plugin](https://github.com/jie65535/gc-opencommand-plugin) 插件
37 |
38 | 1. [下载opencommand插件](https://github.com/jie65535/gc-opencommand-plugin/releases)
39 | 2. 把插件放进你的Grasscutter服务器的 `plugins` 文件夹。
40 | 3. 启动服务器,插件会自动在你的服务器插件文件夹下生成 `opencommand-plugin` 文件夹。
41 | 4. 打开 `opencommand-plugin` 文件夹,打开并编辑 `config.json`。
42 | 5. 设置 `consoleToken` 的值为你的连接秘钥,建议使用至少32字符的长随机字符串。
43 | 6. 安装Python3和依赖包:
44 | ```shell
45 | pip3 install django==3.2 requests
46 | ```
47 | 7. 下载本仓库到服务器,打开并编辑`app`文件夹里的`CONSTANTS.py`文件。
48 | 8. 设置服务器地址、opencommand的Token和自定义密码,保存
49 | >务必保证YSGM(MUIP)的enable状态为False
50 | ```python
51 | # 设置服务器open-command的token
52 | Server_token = 'token_value'
53 |
54 | # 设置服务器地址,不带后边的/
55 | Server_addr = 'https://127.0.0.1'
56 |
57 | # 设置MeaMail插件的邮件模板文件夹(暂不需要)
58 | MeaMail_addr = r'plugins\MeaMailPlus\template'
59 |
60 | # 设置登录认证的密码
61 | auth_pwd = 'jixiaob'
62 | ```
63 | 9. 在项目目录运行
64 | ```shell
65 | python3 manage.py runserver 0.0.0.0:8000
66 | ```
67 | 即可在8000端口访问到页面。
68 |
69 | #### 二、连接YSGM(MUIP)
70 |
71 | 1. 在游戏服务器部署好YSGM(MUIP)
72 | 2. 安装Python3和依赖包:
73 | ```shell
74 | pip3 install django==3.2 requests
75 | ```
76 | 3. 下载本仓库到服务器,打开并编辑`app`文件夹里的`CONSTANTS.py`文件。
77 | 4. 设置YSGM的地址、服务器和自定义密码,保存
78 | ```python
79 | # 设置使用Crepe-Inc-YSGM
80 | YSGM = {
81 | # 启用状态。若未启用则使用open-command
82 | 'enable': True,
83 | # MUIP_HOST的api地址,带有/api
84 | 'MUIP_HOST': 'http://127.0.0.1:20011/api',
85 | 'MUIP_TARGET_REGION': 'dev_gio'
86 | }
87 |
88 | # 设置登录认证的密码
89 | auth_pwd = 'jixiaob'
90 | ```
91 | 9. 在项目目录运行
92 | ```shell
93 | python3 manage.py runserver 0.0.0.0:8000
94 | ```
95 | 即可在8000端口访问到页面。
96 |
97 | ### 使用
98 | 设置CDKey的地址:/cdk_create
99 |
100 | 进入需要验证密码,即刚刚设置的`auth_pwd`
101 | 
102 |
103 | 可以设置单个CDKey的使用次数
104 |
105 | 执行的命令可以是give,当然也可以是其他的命令,多条命令用回车隔开。
106 |
107 | 多条命令快速执行可能会引发异常问题,可以在其间隔添加延时指令
108 | ```shell
109 | sleep100
110 | ```
111 | sleep后面跟延时的时间,单位是毫秒。
112 |
113 | >使用不同的连接方式需要对应不同的命令!命令不可混用!
114 |
115 | 如果连接的是Grasscutter,推荐使用 Grasscutter 命令生成工具:
116 | [GrasscutterCommandGenerator](https://github.com/jie65535/GrasscutterCommandGenerator)
117 |
118 | 还有其他在线命令工具:
119 |
120 | [https://www.xmmt.site/](https://www.xmmt.site/)
121 |
122 | [https://cmd.amoe.cc/](https://cmd.amoe.cc/)
123 |
124 | 如果连接的是MUIP,可以参考以下的在线命令生成工具:
125 |
126 | [https://gm.casks.me/](https://gm.casks.me)
127 |
128 |
129 | 生成的个数可以填多个就可以批量生成,但是不要过多。
130 |
131 | 选择CDK的过期时间(默认为90天后,可以在app/CONSTANTS.py里面更改)
132 |
133 | 限制每个uid可以兑换的同一个CDK的个数
134 |
135 | 生成速度取决于服务器性能。
136 |
137 |
138 | ### 高级
139 |
140 | 1. 设置CDK的默认过期时间。
141 |
142 | 创建CDK时如果不想每次都设置一个时间,可以在`CONSTANTS.py`中设置默认过期时间
143 | ```python
144 | # 设置CDK默认过期时间(默认为90天)
145 | CDK_expire_day = 90
146 | ```
147 | >这样就会自动计算90天之后的日期,然后自动填写在生成CDK页面的表单上。
148 |
149 |
150 | 2. 设置右上角在线人数缓存时间。
151 | >右上角的在线人数之前一直都是打开一次页面就请求服务器获取一次,因此极大的拖慢了页面的加载速度。
152 |
153 | >因此在2022/12/7引入缓存机制,默认是60秒之内只请求一次服务器获取真实的服务器在线人数,其余的都将使用缓存,而不是重新请求服务器,使得页面访问速度大大提高。
154 |
155 | 可以在`CONSTANTS.py`中更改默认的缓存过期时间:
156 | ```python
157 | # 设置获取在线人数的缓存时间秒数,时间过短可能导致所有页面加载缓慢和大量的服务器查询人数请求
158 | # 默认为60秒
159 | online_cache_time = 60
160 | ```
161 | 可以将它调大,这样请求服务器获取真实在线人数的频率会更低,但是在线人数的时效性会大幅降低。
162 |
163 | 也可以把它调小,增加获取在线人数的时效性,但是可能请求服务器获取真实人数的频率会变高。
164 |
165 | 当然也可以把它调为0或者负数,这样就和没有缓存一样,每次加载页面都会请求服务器获取真实人数,降低页面响应速度。
166 |
167 |
168 | 3. 不想使用的功能
169 |
170 | 可能有些提供的功能并不想使用,可以进行如下操作,以远程执行为例:
171 |
172 | ①首先修改`templates/用户后台.html`,把里面的按钮使用` {# #} `引起来,注释掉
173 | ```html
174 | {# 远程执行 #}
175 | ```
176 | 保存。
177 |
178 | ②注释掉可能还不够,有写人可能会猜出地址,还要禁掉对应的路由
179 |
180 | 修改'djangoProject_genshin_player_backend/urls.py'
181 |
182 | 在对应的功能的路由前加上`# `注释这一行
183 | ```python
184 | # path('remote_cmd', views.remote_cmd),
185 | ```
186 | 保存。
187 |
188 | 这样就可以把不想要的功能去掉了。
189 |
190 |
191 | 4. 自定义网页背景图
192 |
193 | 大家还是喜欢背景图是随机图的多,于是直接提供了一个修改图片地址的设置参数,这样就不用一个个到html里面修改了。
194 | ```python
195 | # 设置网页背景图链接,默认是/static/images/bg.jpg文件
196 | # 也可以设置一些随机图的地址 比如https://api.mtyqx.cn/tapi/random.php
197 | # 更多随机图地址详见我博客https://blog.jixiaob.cn/?post=93
198 | background_image = './usr/theme/images/bg.jpg'
199 | ```
200 | 默认就是/static/images/bg.jpg这个图片文件,
201 | 当然也可以改成一些随机图的地址,比如[https://api.mtyqx.cn/tapi/random.php](https://api.mtyqx.cn/tapi/random.php)
202 |
203 | [我博客](https://blog.jixiaob.cn/?post=93) 也分享了一些其他的随机图地址以供参考=w=
204 |
--------------------------------------------------------------------------------
/app/CONSTANTS.py:
--------------------------------------------------------------------------------
1 | """
2 | @FILE_NAME : CONSTANTS
3 | -*- coding : utf-8 -*-
4 | @Author : Zhaokugua
5 | @Time : 2022/10/11 9:40
6 | """
7 | import time
8 | import requests
9 | import random
10 | import datetime
11 | import hashlib
12 | import base64
13 | import json
14 | # 设置服务器open-command的token
15 | Server_token = 'token_value'
16 |
17 | # 设置服务器地址,后面不带/
18 | Server_addr = 'https://127.0.0.1'
19 |
20 | # 设置MeaMail插件的邮件模板文件夹(暂不需要)
21 | MeaMail_addr = r'plugins\MeaMailPlus\template'
22 |
23 | # 邮件默认过期时间戳(默认为邮件发送时间+30天)
24 | Mail_default_expire_time = int((datetime.datetime.now() + datetime.timedelta(days=30)).timestamp())
25 |
26 | # 设置CDK默认过期时间(默认为90天)
27 | CDK_expire_day = 90
28 |
29 | # 设置网页背景图链接,默认是/static/images/bg.jpg文件
30 | # 也可以设置一些随机图的地址 比如https://api.mtyqx.cn/tapi/random.php
31 | # 更多随机图地址详见我博客https://blog.jixiaob.cn/?post=93
32 | background_image = './usr/theme/images/bg.jpg'
33 |
34 | # 设置获取在线人数的缓存时间秒数,时间过短可能导致所有页面加载缓慢和大量的服务器查询人数请求
35 | # 默认为1分钟
36 | online_cache_time = 60
37 |
38 | # 设置使用Crepe-Inc-YSGM(MUIP方法)
39 | YSGM = {
40 | # 启用状态。若未启用则使用open-command
41 | 'enable': False,
42 | # MUIP_HOST的api地址,带有/api
43 | 'MUIP_HOST': 'http://127.0.0.1:54321/api',
44 | 'MUIP_TARGET_REGION': 'dev_test'
45 | }
46 |
47 | # 设置登录认证的密码
48 | auth_pwd = 'jixiaob'
49 |
50 |
51 | def YSGM_api(cmd, uid=None, msg=None):
52 | if YSGM['enable']:
53 | params = {
54 | 'cmd': f'{cmd}',
55 | 'region': YSGM['MUIP_TARGET_REGION'],
56 | 'ticket': f'YSGM@{int(datetime.datetime.now().timestamp())}'
57 | }
58 | if uid:
59 | params['uid'] = uid
60 | if msg:
61 | params['msg'] = msg
62 | sha256_salt = '1d8z98SAKF98bdf878skswa8kdjfy1m9dses'
63 | query_string = '&'.join([f'{x}={params[x]}' for x in params])
64 | sha256_result = hashlib.sha256((query_string+sha256_salt).encode('utf8')).hexdigest()
65 | params['sign'] = sha256_result
66 | return params
67 | else:
68 | print('未开启YSGM!')
69 | return False
70 |
71 |
72 | def YSGM_mail(uid, title, sender='PAIMON', expire_time=Mail_default_expire_time, content='This is a Mail.', item_list=None, is_collectible=False):
73 | """
74 | 生成发送邮件的编码
75 | uid=235078418&
76 | title=test&
77 | content=nyan&
78 | sender=YSGM&
79 | expire_time=1669215550&
80 | is_collectible=False&
81 | importance=&
82 | config_id=&
83 | item_limit_type=2&
84 | tag=&
85 | source_type=&
86 | item_list=&
87 | cmd=1005
88 | ®ion=dev_gio&
89 | ticket=YSGM%401668616882&
90 | sign=9529ea7646fcf8551a0aed72e93125e8b71cd3ceb8613c1ab01bbc1a48ddedea
91 | :param uid: 要发给的用户的uid
92 | :param title: 邮件标题
93 | :param sender: 发送者,默认为PAIMON
94 | :param expire_time: 过期时间,默认为发送邮件后30天
95 | :param content: 正文内容,默认为'This is a Mail.'
96 | :param item_list: 物品列表,默认为空
97 | item_list = [
98 | {
99 | 'item_id': 11101, # 物品id
100 | 'amount': 1, # 数量
101 | 'level': 90, # 等级
102 | 'promote_level': 0, # 突破等级
103 | },
104 | {
105 | 'item_id': 11201, # 物品id
106 | 'amount': 3, # 数量
107 | 'level': 56, # 等级
108 | 'promote_level': 1, # 突破等级
109 | },
110 | ]
111 | :param is_collectible: 是否可以收藏,默认为否
112 | :return: 返回生成后的字符串
113 | """
114 | if item_list:
115 | item_str = ','.join([f'{x.item_id}:{x.amount}:{x.level}:{x.promote_level}' for x in item_list])
116 | else:
117 | item_str = ''
118 | mail_json = {
119 | 'uid': f'{uid}',
120 | 'title': title,
121 | 'sender': sender,
122 | 'expire_time': f'{expire_time}',
123 | 'content': content,
124 | 'item_list': item_str,
125 | 'is_collectible': is_collectible,
126 | }
127 | b64_res = base64.b64encode(bytes(json.dumps(mail_json, ensure_ascii=False, separators=(',', ':')), encoding='utf8'))
128 | return str(b64_res, encoding='utf8')
129 |
130 |
131 | def initialize():
132 | if YSGM['enable']:
133 | # 1101获取服务器人数状态
134 | params = YSGM_api(1101)
135 |
136 | req_url = YSGM['MUIP_HOST']
137 |
138 | try:
139 | res = requests.get(req_url, params=params)
140 | result = res.json()
141 | if result['msg'] == 'succ' and result['retcode'] == 0:
142 | # {'gameserver_player_num': {'809.2.1.1': 0}, 'internal_data': 0, 'online_player_num_except_sub_account': 0}
143 | print('YSGM连接成功!')
144 | return True
145 | else:
146 | print(f'连接服务器失败!请检查配置信息!msg: {result["msg"]}, retcode: {result["retcode"]}')
147 | return False
148 | except:
149 | print('连接服务器失败!请检查运行状态是否正常!')
150 | return False
151 |
152 | # 测试是否已启用插件
153 | req_url = f'{Server_addr}/opencommand/api'
154 | json_ping = {
155 | 'action': 'ping',
156 | }
157 | try:
158 | res_ping = requests.post(req_url, verify=False, json=json_ping)
159 | except:
160 | print('连接服务器失败!')
161 | return False
162 | if res_ping.status_code != 200:
163 | if res_ping.status_code == 404:
164 | print('open-command插件未启用!')
165 | else:
166 | print('open-command插件启动异常!')
167 | return False
168 | else:
169 | ping_result = res_ping.json()
170 | if ping_result['retcode'] == 200 and ping_result['message'] == 'Success':
171 | print('已检测到open-command插件。')
172 | else:
173 | print(f'open-command插件连接失败!{str(ping_result)}')
174 | return False
175 |
176 | json_server = {
177 | 'action': 'server',
178 | 'token': Server_token
179 | }
180 | res_ping = requests.post(req_url, verify=False, json=json_server).json()
181 | if res_ping['retcode'] != 403:
182 | print('暂不支持多服务器!')
183 | return False
184 |
185 | json_test = {
186 | 'action': 'command',
187 | 'token': Server_token,
188 | 'data': 'list uid',
189 | }
190 | res_test = requests.post(req_url, verify=False, json=json_test).json()
191 | if res_test['retcode'] != 200:
192 | if res_test['retcode'] == 401:
193 | print('opencommand token认证失败!')
194 |
195 | else:
196 | print('opencommand 未知错误')
197 | return False
198 | else:
199 | print('opencommand 登录成功!')
200 | return True
201 |
202 |
203 | # 获取在线人数的缓存,加速短时间内获取在线人数的速度,减少请求服务器的速度
204 | online_cache = (datetime.datetime.now(), 0)
205 |
206 |
207 | def get_online():
208 | global online_cache
209 | if datetime.datetime.now() - online_cache[0] < datetime.timedelta(seconds=online_cache_time):
210 | return online_cache[1], None
211 |
212 | if YSGM['enable']:
213 | params = YSGM_api(1101)
214 | req_url = YSGM['MUIP_HOST']
215 |
216 | try:
217 | res = requests.get(req_url, params=params)
218 | result = res.json()
219 | if result['msg'] == 'succ' and result['retcode'] == 0:
220 | # {'gameserver_player_num': {'809.2.1.1': 0}, 'internal_data': 0, 'online_player_num_except_sub_account': 0}
221 | # 暂时用这个人数看看对不对
222 | total_num = result['data']['online_player_num_except_sub_account']
223 | # 更新缓存
224 | online_cache = (datetime.datetime.now(), total_num)
225 | return total_num, None
226 | else:
227 | return 0, 'Error'
228 | except:
229 | return 0, 'Error'
230 |
231 | req_url = f'{Server_addr}/status/server'
232 | try:
233 | res_online = requests.get(req_url, verify=False).json()['status']['playerCount']
234 | # 更新缓存
235 | online_cache = (datetime.datetime.now(), res_online)
236 | return res_online, None
237 | except:
238 | return 0, 'Error'
239 |
240 | # req_url = f'{Server_addr}/opencommand/api'
241 | # json_online = {
242 | # 'action': 'online',
243 | # }
244 | # res_online = requests.post(req_url, json=json_online)
245 | # if res_online.status_code != 200:
246 | # print('open-command插件状态异常!')
247 | # return False
248 | # else:
249 | # online_result = res_online.json()
250 | # if online_result['retcode'] == 200 and online_result['message'] == 'Success':
251 | # u_count, u_list = online_result['data']['count'], online_result['data']['playerList']
252 | # # print(f'获取在线用户成功!\n当前在线人数{u_count}:{str(u_list)}')
253 | # return u_count, u_list
254 | # else:
255 | # print(f'open-command插件连接失败!{str(online_result)}')
256 | # return False
257 |
258 |
259 | def generate_code(code_len=6):
260 | all_char = '0123456789qazwsxedcrfvtgbyhnujmikolpQAZWSXEDCRFVTGBYHNUJIKOLP'
261 | index = len(all_char) - 1
262 | code = ''
263 | for _ in range(code_len):
264 | num = random.randint(0, index)
265 | # print(num)
266 | code += all_char[num]
267 | return code.upper()
268 |
269 |
270 | def exec_command(command, uid=None):
271 | # 执行命令没写转换
272 | # 所以如果生成cdk的时候用的命令是gc的,执行的时候一定不要改成GM的!
273 |
274 | # 20230123 新增延迟执行命令(单位毫秒)
275 | if command[:5] == 'sleep':
276 | sleep_time = command.replace('sleep', '')
277 | # 判断后面剩下的是不是纯数字
278 | if sleep_time.isdigit():
279 | # 是就sleep
280 | sleep_time = int(sleep_time)
281 | print(f'正在执行延时命令:sleep{sleep_time}...')
282 | time.sleep(sleep_time/1000)
283 | return True, {'data': f'延迟命令执行{sleep_time}ms'}
284 | else:
285 | # 不是就返回错误
286 | return False, {'data': f'延迟命令语法错误!正确的语法示例:sleep100'}
287 |
288 | command = command[1:] if command.startswith('/') or command.startswith('!') else command
289 | if YSGM['enable']:
290 |
291 | # 如果填写了uid,判断uid是否为纯数字(官端应该只有纯数字uid)
292 | # 防止兑换cdk的时候uid加字母卡多次兑换bug
293 | if uid:
294 | if not uid.isdigit():
295 | return False, {'data': 'uid不是纯数字!'}
296 |
297 | params = YSGM_api(1116, uid=uid, msg=command)
298 | req_url = YSGM['MUIP_HOST']
299 | try:
300 | res = requests.get(req_url, params=params)
301 | result = res.json()
302 | if result['msg'] == 'succ' and result['retcode'] == 0:
303 | print('YSGM命令执行成功!')
304 | return True, result
305 | else:
306 | print('YSGM命令执行失败!')
307 | result['data'] = '执行失败,可能是玩家未上线' if not result['data'] else result['data']
308 | return False, result
309 | except BaseException as e:
310 | print('YSGM命令执行失败!')
311 | print(e)
312 | return False, {'data': '请求错误,检查服务器'}
313 |
314 | if uid:
315 | command = command + f' @{uid}'
316 | req_url = f'{Server_addr}/opencommand/api'
317 | json_exec = {
318 | 'action': 'command',
319 | 'token': Server_token,
320 | 'data': command,
321 | }
322 | res_exec = requests.post(req_url, verify=False, json=json_exec).json()
323 | if res_exec['retcode'] != 200:
324 | res_exec['data'] = '' if not res_exec['data'] else res_exec['data']
325 | print('opencommand 命令执行异常!')
326 | return False, res_exec
327 | else:
328 | print('opencommand 命令执行成功!')
329 | print(command)
330 | print(res_exec)
331 | if res_exec['data'] == '玩家不存在。':
332 | return False, res_exec
333 | if '当前目标离线' in res_exec['data']:
334 | return False, res_exec
335 | return True, res_exec
336 |
--------------------------------------------------------------------------------
/app/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zhaokugua/Grasscutter-CDKeySystem/0af77fa64c0013be0bc712430ea5a6d0908b3f6d/app/__init__.py
--------------------------------------------------------------------------------
/app/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/app/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class AppConfig(AppConfig):
5 | default_auto_field = 'django.db.models.BigAutoField'
6 | name = 'app'
7 |
--------------------------------------------------------------------------------
/app/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2 on 2022-11-16 12:09
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | initial = True
9 |
10 | dependencies = [
11 | ]
12 |
13 | operations = [
14 | migrations.CreateModel(
15 | name='CDKey',
16 | fields=[
17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18 | ('key', models.CharField(max_length=16)),
19 | ('cdk_value', models.TextField(null=True)),
20 | ('mail_template_id', models.IntegerField(default=0)),
21 | ('end_time', models.DateField(default='2022-10-1')),
22 | ('total_num', models.IntegerField(default=1)),
23 | ('used_num', models.IntegerField(default=0)),
24 | ('num_by_uid', models.IntegerField(default=1)),
25 | ],
26 | ),
27 | migrations.CreateModel(
28 | name='CDkey_Record',
29 | fields=[
30 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
31 | ('key', models.CharField(max_length=16)),
32 | ('use_time', models.DateTimeField(auto_now=True)),
33 | ('user_uid', models.CharField(max_length=16)),
34 | ],
35 | ),
36 | migrations.CreateModel(
37 | name='Daily_Sign_Record',
38 | fields=[
39 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
40 | ('sign_date', models.DateField(auto_now=True)),
41 | ('sign_uid', models.CharField(max_length=16)),
42 | ],
43 | ),
44 | ]
45 |
--------------------------------------------------------------------------------
/app/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zhaokugua/Grasscutter-CDKeySystem/0af77fa64c0013be0bc712430ea5a6d0908b3f6d/app/migrations/__init__.py
--------------------------------------------------------------------------------
/app/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
5 |
6 | class CDKey(models.Model):
7 | # cdkey的值,一般为12位字母和数字
8 | key = models.CharField(max_length=16)
9 | # cdk内容(回车分隔的命令,不带/)
10 | cdk_value = models.TextField(null=True)
11 | # 邮件模板(可以设置已经创建好的邮件模板,设置之后将忽略cdk_value)
12 | mail_template_id = models.IntegerField(default=0)
13 | # 过期时间
14 | end_time = models.DateField(default='2022-10-1')
15 | # 总数(有的cdkey可以重复兑换,默认为1)
16 | total_num = models.IntegerField(default=1)
17 | # 已经兑换的数量
18 | used_num = models.IntegerField(default=0)
19 | # 设置每个uid可兑换次数
20 | num_by_uid = models.IntegerField(default=1)
21 |
22 |
23 | class CDkey_Record(models.Model):
24 | # cdkey
25 | key = models.CharField(max_length=16)
26 | # 兑换时间
27 | use_time = models.DateTimeField(auto_now=True)
28 | # 兑换用户uid
29 | user_uid = models.CharField(max_length=16)
30 |
31 |
32 | # 记录uid上次签到时间来判断今天是否已签到
33 | class Daily_Sign_Record(models.Model):
34 | # 最近签到日期
35 | sign_date = models.DateField(auto_now=True)
36 | # 签到的uid
37 | sign_uid = models.CharField(max_length=16)
38 |
--------------------------------------------------------------------------------
/app/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/app/views.py:
--------------------------------------------------------------------------------
1 | from django.http import HttpResponseRedirect
2 | from django.shortcuts import render
3 | import datetime
4 | from time import sleep
5 | from app.CONSTANTS import *
6 | from app.models import *
7 |
8 | # Create your views here.
9 |
10 | online_num = get_online()[0]
11 |
12 | if not initialize():
13 | print('服务器连接失败!可能无法正常进行操作!')
14 |
15 |
16 | def index(request):
17 | global online_num
18 | online_num = get_online()[0]
19 | context = {
20 | 'online_num': online_num,
21 | 'bg_url': background_image,
22 | }
23 | return render(request, '用户后台.html', context=context)
24 |
25 |
26 | def cdkey(request):
27 | global online_num
28 | online_num = get_online()[0]
29 | if request.method == 'POST':
30 | user_uid = request.POST.get('username')
31 | cdkey_value = request.POST.get('getcdk')
32 | cdk_obj = CDKey.objects.filter(key=cdkey_value).first()
33 | if not user_uid:
34 | context = {
35 | 'message': "请填写uid! ",
36 | 'online_num': online_num,
37 | 'bg_url': background_image,
38 | }
39 | return render(request, 'cdkey兑换.html', context=context)
40 | if cdk_obj:
41 | if datetime.date.today() > cdk_obj.end_time:
42 | context = {
43 | 'message': "兑换码已过期! ",
44 | 'online_num': online_num,
45 | 'bg_url': background_image,
46 | }
47 | return render(request, 'cdkey兑换.html', context=context)
48 | if cdk_obj.used_num >= cdk_obj.total_num:
49 | context = {
50 | 'message': "兑换码已被使用! ",
51 | 'online_num': online_num,
52 | 'bg_url': background_image,
53 | }
54 | return render(request, 'cdkey兑换.html', context=context)
55 | else:
56 | context = {
57 | 'message': "无效的兑换码! ",
58 | 'online_num': online_num,
59 | 'bg_url': background_image,
60 | }
61 | return render(request, 'cdkey兑换.html', context=context)
62 |
63 | # MUIP的UID只能是不包含字母、特殊符号并且不能以0开头的纯数字
64 | if YSGM['enable']:
65 | try:
66 | user_uid = f'{int(user_uid)}'
67 | except ValueError as e:
68 | context = {
69 | 'message': "UID只能为纯数字! ",
70 | 'online_num': online_num,
71 | 'bg_url': background_image,
72 | }
73 | return render(request, 'cdkey兑换.html', context=context)
74 |
75 | # 判断每个用户的使用次数
76 | used_times = len(CDkey_Record.objects.filter(user_uid=user_uid).filter(key=cdkey_value))
77 |
78 | if used_times >= cdk_obj.num_by_uid:
79 | context = {
80 | 'message': "同一个兑换码单个uid使用次数达到上限! ",
81 | 'online_num': online_num,
82 | 'bg_url': background_image,
83 | }
84 | return render(request, 'cdkey兑换.html', context=context)
85 |
86 | result_list = []
87 | success = True
88 | for command in cdk_obj.cdk_value.split('\r\n'):
89 |
90 | flag, res = exec_command(command, uid=user_uid)
91 |
92 | if res['data'] == '玩家不存在。':
93 | context = {
94 | 'message': "玩家不存在,请检查uid! ",
95 | 'online_num': online_num,
96 | 'bg_url': background_image,
97 | }
98 |
99 | return render(request, 'cdkey兑换.html', context=context)
100 | if '当前目标离线' in res['data']:
101 | context = {
102 | 'message': "当前玩家离线,请上线后再执行! ",
103 | 'online_num': online_num,
104 | 'bg_url': background_image,
105 | }
106 |
107 | return render(request, 'cdkey兑换.html', context=context)
108 | if not flag:
109 | success = False
110 | result_list.append(res['data'])
111 | if not success:
112 | context = {
113 | 'message': f"执行兑换时出现异常!请联系管理员! {str(result_list)}",
114 | 'online_num': online_num,
115 | 'bg_url': background_image,
116 | }
117 |
118 | return render(request, 'cdkey兑换.html', context=context)
119 | # 修改兑换码已使用次数
120 | cdk_obj.used_num += 1
121 | cdk_obj.save()
122 | # 记录兑换记录
123 | used_info = CDkey_Record()
124 | used_info.key = cdkey_value
125 | used_info.user_uid = user_uid
126 | used_info.save()
127 | context = {
128 | 'message': "兑换成功! ",
129 | 'online_num': online_num,
130 | 'bg_url': background_image,
131 | }
132 |
133 | return render(request, 'cdkey兑换.html', context=context)
134 | context = {
135 | 'online_num': online_num,
136 | 'bg_url': background_image
137 | }
138 | return render(request, 'cdkey兑换.html', context=context)
139 |
140 |
141 | def create_cdkey(request):
142 | """
143 | 创建cdkey
144 | 可设置cdk的值或者随机生成
145 | 可以批量创建
146 | 设置兑换奖励
147 | 截止时间
148 | :param request:
149 | :return:
150 | """
151 | global online_num
152 | online_num = get_online()[0]
153 | # 配置文件可以设置兑换码的默认过期时间,默认90天过期
154 | default_time = str(datetime.date.today() + datetime.timedelta(days=CDK_expire_day))
155 | if request.session.get('auth') != 'jixiaob.cn':
156 | return HttpResponseRedirect('auth')
157 |
158 | cdk_list = [x.key for x in CDKey.objects.all()] # 获取所有key
159 |
160 | if request.method == 'POST':
161 | cdk_value = request.POST.get('cdk_value')
162 | end_time = request.POST.get('end_time')
163 | total_num = request.POST.get('total_num')
164 | cdk_num = request.POST.get('cdk_num')
165 | num_by_uid = request.POST.get('num_by_uid')
166 |
167 | new_cdk_list = []
168 | while len(new_cdk_list) < int(cdk_num):
169 | cdk_code = generate_code(12)
170 | while cdk_code in cdk_list: # 如果已存在就重新生成,直到不存在
171 | cdk_code = generate_code(12)
172 | cdk_list.append(cdk_code)
173 | # 获取信息并生成
174 | new_cdk = CDKey()
175 | new_cdk.key = cdk_code
176 | new_cdk.cdk_value = cdk_value
177 | # new_cdk.mail_template_id = 1111
178 | new_cdk.end_time = end_time
179 | new_cdk.total_num = total_num
180 | new_cdk.num_by_uid = num_by_uid
181 | new_cdk.save()
182 | new_cdk_list.append(cdk_code)
183 | cdk_str = " ".join(new_cdk_list)
184 | context = {
185 | 'online_num': online_num,
186 | 'message': f'生成CDK成功!\n{cdk_str}',
187 | 'default_time': default_time,
188 | 'bg_url': background_image,
189 |
190 | }
191 | return render(request, '创建cdkey.html', context=context)
192 | context = {
193 | 'online_num': online_num,
194 | 'default_time': default_time,
195 | 'bg_url': background_image,
196 | }
197 | return render(request, '创建cdkey.html', context=context)
198 |
199 |
200 | def lucky(request):
201 | global online_num
202 | online_num = get_online()[0]
203 | if request.method == 'POST':
204 | # 从前端获取用户uid
205 | uuid = request.POST.get('uuid')
206 | # 可以用exec_command随机执行一个命令来获取抽奖奖励,用户离线时可以用邮件命令发送奖励
207 | # 然后context的message显示随机到的抽奖结果返回到页面上显示
208 | # 例:
209 | # # 记录随机命令列表
210 | # command_list = [
211 | # '/give 202 x1000',
212 | # '/give 201 x100',
213 | # '/give 223 x10'
214 | # ]
215 | # # 记录命令对应的结果
216 | # result_list = [
217 | # '100摩拉',
218 | # '100原石',
219 | # '10纠缠之缘'
220 | # ]
221 | # # 随机选取
222 | # random_result = ramdom.randint(0, len(command_list))
223 | # exec_command(command_list[random_result], uuid) # give命令需要玩家在线
224 | # context = {
225 | # 'message': f"抽奖成功!获得{result_list[random_result]}!",
226 | # 'online_num': online_num,
227 | # }
228 | context = {
229 | 'message': "功能暂未开放! ",
230 | 'online_num': online_num,
231 | 'bg_url': background_image,
232 | }
233 | return render(request, '幸运抽奖.html', context=context)
234 | context = {
235 | 'online_num': online_num,
236 | 'bg_url': background_image,
237 | }
238 | return render(request, '幸运抽奖.html', context=context)
239 |
240 |
241 | def sign(request):
242 | global online_num
243 | online_num = get_online()[0]
244 | if request.method == 'POST':
245 | # 从前端获取用户uid
246 | uuid = request.POST.get('uuid')
247 |
248 | if not uuid:
249 | context = {
250 | 'message': "请填写uid!",
251 | 'online_num': online_num,
252 | 'bg_url': background_image,
253 | }
254 | return render(request, '每日签到.html', context=context)
255 |
256 | # 判断数据库里是否有记录和今天是否已经签到
257 | user = Daily_Sign_Record.objects.filter(sign_uid=uuid).first()
258 | if user:
259 | if user.sign_date == datetime.date.today():
260 | context = {
261 | 'message': "你今天已经签到过了哦!",
262 | 'online_num': online_num,
263 | 'bg_url': background_image,
264 | }
265 | return render(request, '每日签到.html', context=context)
266 | else:
267 | user = Daily_Sign_Record(sign_uid=uuid)
268 | # 可以用exec_command执行一个命令来获取签到奖励,用户离线时可以用邮件命令发送奖励
269 | # 然后context的message显示签到结果返回到页面上显示
270 | # 然后写到数据库记录一下今天已签到
271 | flag, res = exec_command('/give 202 x1000', uuid) # give命令需要玩家在线
272 | if not flag:
273 | context = {
274 | 'message': f"执行兑换时出现异常!请联系管理员! {str(res['data'])}",
275 | 'online_num': online_num,
276 | 'bg_url': background_image,
277 | }
278 | return render(request, '每日签到.html', context=context)
279 | # 成功了就更新一下表,表示今天签到了
280 | user.save()
281 | # 返回信息
282 | context = {
283 | 'message': "签到成功!获得1000摩拉!",
284 | 'online_num': online_num,
285 | 'bg_url': background_image,
286 | }
287 | return render(request, '每日签到.html', context=context)
288 | context = {
289 | 'online_num': online_num,
290 | 'bg_url': background_image
291 | }
292 | return render(request, '每日签到.html', context=context)
293 |
294 |
295 | def unlock_map(request):
296 | global online_num
297 | online_num = get_online()[0]
298 | if request.method == 'POST':
299 | uuid = request.POST.get('uuid')
300 | if uuid:
301 | exec_command(f'prop um 1', uuid)
302 | flag, res = exec_command(f'prop ut 12', uuid)
303 | if res['data'] == '玩家不存在。':
304 | context = {
305 | 'message': "玩家不存在,请检查uid! ",
306 | 'online_num': online_num,
307 | 'bg_url': background_image,
308 | }
309 | return render(request, '解锁深渊.html', context=context)
310 | if '当前目标离线' in res['data']:
311 | context = {
312 | 'message': "当前玩家离线,请上线后再执行! ",
313 | 'online_num': online_num,
314 | 'bg_url': background_image,
315 | }
316 | return render(request, '解锁深渊.html', context=context)
317 | context = {
318 | 'message': "解锁成功! ",
319 | 'online_num': online_num,
320 | 'bg_url': background_image,
321 | }
322 | return render(request, '解锁深渊.html', context=context)
323 | else:
324 | context = {
325 | 'message': "请填写uid! ",
326 | 'online_num': online_num,
327 | 'bg_url': background_image,
328 | }
329 | return render(request, '解锁深渊.html', context=context)
330 | context = {
331 | 'online_num': online_num,
332 | 'bg_url': background_image,
333 | }
334 | return render(request, '解锁深渊.html', context=context)
335 |
336 |
337 | def set_world_level(request):
338 | global online_num
339 | online_num = get_online()[0]
340 | if request.method == 'POST':
341 | uuid = request.POST.get('uuid')
342 | level = request.POST.get('level')
343 | if uuid:
344 | flag, res = exec_command(f'prop wl {level}', uuid)
345 | if res['data'] == '玩家不存在。':
346 | context = {
347 | 'message': "玩家不存在,请检查uid! ",
348 | 'online_num': online_num,
349 | 'bg_url': background_image,
350 | }
351 | return render(request, '设置世界等级.html', context=context)
352 | if '当前目标离线' in res['data']:
353 | context = {
354 | 'message': "当前玩家离线,请上线后再执行! ",
355 | 'online_num': online_num,
356 | 'bg_url': background_image,
357 | }
358 | return render(request, '设置世界等级.html', context=context)
359 | context = {
360 | 'message': "设置成功! ",
361 | 'online_num': online_num,
362 | 'bg_url': background_image,
363 | }
364 | return render(request, '设置世界等级.html', context=context)
365 | else:
366 | context = {
367 | 'message': "请填写uid! ",
368 | 'online_num': online_num,
369 | 'bg_url': background_image,
370 | }
371 | return render(request, '设置世界等级.html', context=context)
372 | context = {
373 | 'online_num': online_num,
374 | 'bg_url': background_image,
375 | }
376 | return render(request, '设置世界等级.html', context=context)
377 |
378 |
379 | def auth(request):
380 | global online_num
381 | online_num = get_online()[0]
382 | if request.method == 'POST':
383 | pwd = request.POST.get('password')
384 | if pwd == auth_pwd:
385 | request.session['auth'] = 'jixiaob.cn'
386 | return HttpResponseRedirect('./cdk_create')
387 | else:
388 | context = {
389 | 'message': '认证失败!',
390 | 'online_num': online_num,
391 | 'bg_url': background_image,
392 | }
393 | return render(request, '登录认证.html', context=context)
394 | context = {
395 | 'online_num': online_num,
396 | 'bg_url': background_image,
397 | }
398 | return render(request, '登录认证.html', context=context)
399 |
400 |
401 | def remote_cmd(request):
402 | global online_num
403 | online_num = get_online()[0]
404 | if request.method == 'POST':
405 | uuid = request.POST.get('uuid')
406 | command = request.POST.get('command')
407 | if uuid:
408 | flag, res = exec_command(f'{command}', uuid)
409 | if res['data'] == '玩家不存在。':
410 | context = {
411 | 'message': "玩家不存在,请检查uid! ",
412 | 'online_num': online_num,
413 | 'bg_url': background_image,
414 | }
415 | return render(request, '远程执行.html', context=context)
416 | if '当前目标离线' in res['data']:
417 | context = {
418 | 'message': "当前玩家离线,请上线后再执行! ",
419 | 'online_num': online_num,
420 | 'bg_url': background_image,
421 | }
422 | return render(request, '远程执行.html', context=context)
423 | if not flag:
424 | context = {
425 | 'message': f"执行命令时出现异常!请检查命令格式! {str(res)}",
426 | 'online_num': online_num,
427 | 'bg_url': background_image,
428 | }
429 | return render(request, '远程执行.html', context=context)
430 | context = {
431 | 'message': "执行命令成功! ",
432 | 'online_num': online_num,
433 | 'bg_url': background_image,
434 | }
435 | return render(request, '远程执行.html', context=context)
436 | else:
437 | context = {
438 | 'message': "请填写uid! ",
439 | 'online_num': online_num,
440 | 'bg_url': background_image,
441 | }
442 | return render(request, '远程执行.html', context=context)
443 | context = {
444 | 'online_num': online_num,
445 | 'bg_url': background_image,
446 | }
447 | return render(request, '远程执行.html', context=context)
448 |
--------------------------------------------------------------------------------
/db.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zhaokugua/Grasscutter-CDKeySystem/0af77fa64c0013be0bc712430ea5a6d0908b3f6d/db.sqlite3
--------------------------------------------------------------------------------
/djangoProject_genshin_player_backend/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zhaokugua/Grasscutter-CDKeySystem/0af77fa64c0013be0bc712430ea5a6d0908b3f6d/djangoProject_genshin_player_backend/__init__.py
--------------------------------------------------------------------------------
/djangoProject_genshin_player_backend/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for djangoProject_genshin_player_backend project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject_genshin_player_backend.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/djangoProject_genshin_player_backend/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for djangoProject_genshin_player_backend project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.2.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.2/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 |
15 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
16 | BASE_DIR = Path(__file__).resolve().parent.parent
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 'django-insecure-oj$414xpyjgnz$y#sq!e^7vwjaf$f-#h)l4%55zf_hzo+yj*&!'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = ['*']
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.auth',
35 | 'django.contrib.contenttypes',
36 | 'django.contrib.sessions',
37 | 'django.contrib.messages',
38 | 'django.contrib.staticfiles',
39 | 'app.apps.AppConfig',
40 | ]
41 |
42 | MIDDLEWARE = [
43 | 'django.middleware.security.SecurityMiddleware',
44 | 'django.contrib.sessions.middleware.SessionMiddleware',
45 | 'django.middleware.common.CommonMiddleware',
46 | # 'django.middleware.csrf.CsrfViewMiddleware',
47 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
48 | 'django.contrib.messages.middleware.MessageMiddleware',
49 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
50 | ]
51 |
52 | ROOT_URLCONF = 'djangoProject_genshin_player_backend.urls'
53 |
54 | TEMPLATES = [
55 | {
56 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
57 | 'DIRS': [BASE_DIR / 'templates']
58 | ,
59 | 'APP_DIRS': True,
60 | 'OPTIONS': {
61 | 'context_processors': [
62 | 'django.template.context_processors.debug',
63 | 'django.template.context_processors.request',
64 | 'django.contrib.auth.context_processors.auth',
65 | 'django.contrib.messages.context_processors.messages',
66 | ],
67 | },
68 | },
69 | ]
70 |
71 | WSGI_APPLICATION = 'djangoProject_genshin_player_backend.wsgi.application'
72 |
73 |
74 | # Database
75 | # https://docs.djangoproject.com/en/3.2/ref/settings/#databases
76 |
77 | DATABASES = {
78 | 'default': {
79 | 'ENGINE': 'django.db.backends.sqlite3',
80 | 'NAME': BASE_DIR / 'db.sqlite3',
81 | }
82 | }
83 |
84 |
85 | # Password validation
86 | # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
87 |
88 | AUTH_PASSWORD_VALIDATORS = [
89 | {
90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
91 | },
92 | {
93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
94 | },
95 | {
96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
97 | },
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
100 | },
101 | ]
102 |
103 |
104 | # Internationalization
105 | # https://docs.djangoproject.com/en/3.2/topics/i18n/
106 |
107 | LANGUAGE_CODE = 'zh-hans'
108 |
109 | TIME_ZONE = 'UTC'
110 |
111 | USE_I18N = True
112 |
113 | USE_L10N = True
114 |
115 | USE_TZ = True
116 |
117 |
118 | # Static files (CSS, JavaScript, Images)
119 | # https://docs.djangoproject.com/en/3.2/howto/static-files/
120 |
121 | STATIC_URL = '/usr/'
122 | STATICFILES_DIRS = ['static']
123 | # Default primary key field type
124 | # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
125 |
126 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
127 |
--------------------------------------------------------------------------------
/djangoProject_genshin_player_backend/urls.py:
--------------------------------------------------------------------------------
1 | """djangoProject_genshin_player_backend URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | # from django.contrib import admin
17 | from django.urls import path
18 | from app import views
19 |
20 | urlpatterns = [
21 | # path('admin/', admin.site.urls),
22 | path('cdk', views.cdkey),
23 | path('cdk_create', views.create_cdkey),
24 | path('auth', views.auth),
25 | path('lucky', views.lucky),
26 | path('sign', views.sign),
27 | path('unlockmap', views.unlock_map),
28 | path('setworldlevel', views.set_world_level),
29 | path('remote_cmd', views.remote_cmd),
30 | path('', views.index),
31 |
32 | ]
33 |
--------------------------------------------------------------------------------
/djangoProject_genshin_player_backend/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for djangoProject_genshin_player_backend project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject_genshin_player_backend.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/image/ScreenShot1.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zhaokugua/Grasscutter-CDKeySystem/0af77fa64c0013be0bc712430ea5a6d0908b3f6d/image/ScreenShot1.JPG
--------------------------------------------------------------------------------
/image/ScreenShot2.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zhaokugua/Grasscutter-CDKeySystem/0af77fa64c0013be0bc712430ea5a6d0908b3f6d/image/ScreenShot2.JPG
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject_genshin_player_backend.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/static/theme/css/font-awesome.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
4 | */@font-face{font-family:'FontAwesome';src:url('../images/fontawesome-webfont.eot');src:url('../images/fontawesome-webfont_b9b6830ad2a349ccba47412f3c3eb53e.eot') format('embedded-opentype'),url('../images/fontawesome-webfont.woff2') format('woff2'),url('../images/fontawesome-webfont.woff') format('woff'),url('../images/fontawesome-webfont.ttf') format('truetype'),url('../images/fontawesome-webfont.svg') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}
5 |
--------------------------------------------------------------------------------
/static/theme/css/i.css:
--------------------------------------------------------------------------------
1 | p, ul {
2 | margin-top: 0
3 | }
4 |
5 | p, ul {
6 | margin-bottom: 1rem
7 | }
8 |
9 | img {
10 | vertical-align: middle
11 | }
12 |
13 | .content-icp {
14 | color: #a19d9d;
15 | font-weight: bolder;
16 | text-align: center;
17 | max-width: 1110px;
18 | margin: 30px auto 0 auto;
19 | border-radius: 20px;
20 | padding: 5px;
21 | }
22 |
23 | @font-face {
24 | font-family: HarmonyOS;
25 | font-style: normal;
26 | font-display: swap;
27 | src: url(../images/HarmonyOS_Sans_SC_Medium.subset.woff2) format('woff2')
28 | }
29 |
30 | body {
31 | text-align: left;
32 | font-family: HarmonyOS !important;
33 | }
34 |
35 | button, input {
36 | overflow: visible
37 | }
38 |
39 | nav {
40 | display: block
41 | }
42 |
43 | label {
44 | margin-bottom: .5rem
45 | }
46 |
47 | .badge {
48 | vertical-align: baseline
49 | }
50 |
51 | label {
52 | display: inline-block
53 | }
54 |
55 | .navbar-nav {
56 | -webkit-box-direction: normal
57 | }
58 |
59 | .btn-outline-success {
60 | background-image: none
61 | }
62 |
63 | .navbar-nav {
64 | list-style: none
65 | }
66 |
67 |
68 | *, ::after, ::before {
69 | -webkit-box-sizing: border-box;
70 | -moz-box-sizing: border-box;
71 | box-sizing: border-box
72 | }
73 |
74 | html {
75 | font-family: sans-serif;
76 | line-height: 1.15;
77 | -webkit-text-size-adjust: 100%;
78 | -ms-text-size-adjust: 100%;
79 | -ms-overflow-style: scrollbar;
80 | -webkit-tap-highlight-color: transparent
81 | }
82 |
83 |
84 | body {
85 | margin: 0;
86 | color: #212529;
87 | background-color: #F4F5FA
88 | }
89 |
90 | h1, h3, h5 {
91 | margin-top: 0;
92 | margin-bottom: .75rem
93 | }
94 |
95 | .btn:focus, .btn:hover, a {
96 | text-decoration: none
97 | }
98 |
99 | .btn:not(:disabled):not(.disabled), .close:not(:disabled):not(.disabled), .fc button:not(:disabled):not(.disabled), .navbar-toggler:not(:disabled):not(.disabled), .page-link:not(:disabled):not(.disabled), button:hover {
100 | cursor: pointer
101 | }
102 |
103 | a {
104 | background-color: transparent;
105 | -webkit-text-decoration-skip: objects
106 | }
107 |
108 | a:not([href]):not([tabindex]), a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
109 | color: inherit;
110 | text-decoration: none
111 | }
112 |
113 | a:not([href]):not([tabindex]):focus {
114 | outline: 0
115 | }
116 |
117 | img {
118 | border-style: none
119 | }
120 |
121 | button {
122 | border-radius: 0
123 | }
124 |
125 | button:focus {
126 | outline: dotted 1px;
127 | outline: -webkit-focus-ring-color auto 5px
128 | }
129 |
130 | button, input, select {
131 | margin: 0;
132 | font-family: inherit;
133 | font-size: inherit;
134 | line-height: inherit
135 | }
136 |
137 | button, select {
138 | text-transform: none
139 | }
140 |
141 | [type=submit], button, html [type=button] {
142 | -webkit-appearance: button
143 | }
144 |
145 | [type=button]::-moz-focus-inner, [type=submit]::-moz-focus-inner, button::-moz-focus-inner {
146 | padding: 0;
147 | border-style: none
148 | }
149 |
150 | input[type=radio] {
151 | -webkit-box-sizing: border-box;
152 | -moz-box-sizing: border-box;
153 | box-sizing: border-box;
154 | padding: 0
155 | }
156 |
157 | fieldset {
158 | min-width: 0;
159 | padding: 0;
160 | margin: 0;
161 | border: 0
162 | }
163 |
164 | .badge, .btn, .navbar-brand {
165 | white-space: nowrap
166 | }
167 |
168 | [type=number]::-webkit-inner-spin-button, [type=number]::-webkit-outer-spin-button {
169 | height: auto
170 | }
171 |
172 | ::-webkit-file-upload-button {
173 | font: inherit;
174 | -webkit-appearance: button
175 | }
176 |
177 | h1, h3, h5 {
178 | margin-bottom: .75rem
179 | }
180 |
181 | .container {
182 | padding-right: 15px;
183 | padding-left: 15px;
184 | margin-right: auto;
185 | margin-left: auto;
186 | width: 100%;
187 | }
188 |
189 |
190 | .row {
191 | display: -webkit-box;
192 | display: -webkit-flex;
193 | display: -moz-box;
194 | display: -ms-flexbox;
195 | display: flex;
196 | -webkit-flex-wrap: wrap;
197 | -ms-flex-wrap: wrap;
198 | flex-wrap: wrap;
199 | margin-right: -15px;
200 | margin-left: -15px
201 | }
202 |
203 | .col, .col-3, .col-md-2, .col-md-5, .col-md-7 {
204 | position: relative;
205 | width: 100%;
206 | min-height: 1px;
207 | padding-right: 15px;
208 | padding-left: 15px
209 | }
210 |
211 | .col {
212 | -webkit-flex-basis: 0;
213 | -ms-flex-preferred-size: 0;
214 | flex-basis: 0;
215 | -webkit-box-flex: 1;
216 | -webkit-flex-grow: 1;
217 | -moz-box-flex: 1;
218 | -ms-flex-positive: 1;
219 | flex-grow: 1;
220 | max-width: 100%
221 | }
222 |
223 | .col-3 {
224 | -webkit-box-flex: 0
225 | }
226 |
227 | .col-3 {
228 | -webkit-flex: 0 0 25%;
229 | -moz-box-flex: 0;
230 | -ms-flex: 0 0 25%;
231 | flex: 0 0 25%;
232 | max-width: 25%
233 | }
234 |
235 | .offset-9 {
236 | margin-left: 75%
237 | }
238 |
239 | .form-control {
240 | display: block;
241 | width: 100%;
242 | height: -webkit-calc(2.25rem + 2px);
243 | height: -moz-calc(2.25rem + 2px);
244 | height: calc(2.25rem + 2px);
245 | padding: .375rem .75rem;
246 | font-size: 1rem;
247 | line-height: 1.5;
248 | color: #495057;
249 | background-color: rgba(255, 255, 255, 0.17);
250 | -webkit-background-clip: padding-box;
251 | background-clip: padding-box;
252 | border: 1px solid #CED4DA;
253 | border-radius: .25rem;
254 | -webkit-transition: border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out;
255 | -o-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
256 | -moz-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
257 | transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
258 | transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out, -webkit-box-shadow .15s ease-in-out
259 | }
260 |
261 | @media screen and (prefers-reduced-motion: reduce) {
262 | .form-control {
263 | -webkit-transition: none;
264 | -o-transition: none;
265 | -moz-transition: none;
266 | transition: none
267 | }
268 | }
269 |
270 | .form-control::-ms-expand {
271 | background-color: transparent;
272 | border: 0
273 | }
274 |
275 | .form-control:focus {
276 | color: #495057;
277 | background-color: #FFF;
278 | outline: 0;
279 | -webkit-box-shadow: 0 0 0 .2rem rgba(102, 110, 232, .25);
280 | box-shadow: 0 0 0 .2rem rgba(102, 110, 232, .25)
281 | }
282 |
283 | .form-control::-webkit-input-placeholder {
284 | color: #6C757D;
285 | opacity: 1
286 | }
287 |
288 | .form-control:-moz-placeholder {
289 | color: #6C757D;
290 | opacity: 1
291 | }
292 |
293 | .form-control::-moz-placeholder {
294 | color: #6C757D;
295 | opacity: 1
296 | }
297 |
298 | .form-control:-ms-input-placeholder {
299 | color: #6C757D;
300 | opacity: 1
301 | }
302 |
303 | .form-control:disabled {
304 | opacity: 1
305 | }
306 |
307 | select.form-control:focus::-ms-value {
308 | color: #495057;
309 | background-color: #FFF
310 | }
311 |
312 | .form-group {
313 | margin-bottom: 1rem
314 | }
315 |
316 | .navbar-nav {
317 | -webkit-box-orient: vertical;
318 | -moz-box-orient: vertical;
319 | -moz-box-direction: normal
320 | }
321 |
322 | .btn {
323 | display: inline-block;
324 | font-weight: 400;
325 | text-align: center;
326 | vertical-align: middle;
327 | -webkit-user-select: none;
328 | -moz-user-select: none;
329 | -ms-user-select: none;
330 | user-select: none;
331 | border: 1px solid transparent;
332 | padding: .375rem .75rem;
333 | font-size: 1rem;
334 | line-height: 1.5;
335 | border-radius: .25rem;
336 | -webkit-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, -webkit-box-shadow .15s ease-in-out;
337 | -o-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
338 | -moz-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
339 | transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
340 | transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out, -webkit-box-shadow .15s ease-in-out
341 | }
342 |
343 | @media screen and (prefers-reduced-motion: reduce) {
344 | .btn {
345 | -webkit-transition: none;
346 | -o-transition: none;
347 | -moz-transition: none;
348 | transition: none
349 | }
350 | }
351 |
352 | .btn:focus {
353 | outline: 0;
354 | -webkit-box-shadow: 0 0 0 .2rem rgba(102, 110, 232, .25);
355 | box-shadow: 0 0 0 .2rem rgba(102, 110, 232, .25)
356 | }
357 |
358 | .btn:disabled {
359 | opacity: .65
360 | }
361 |
362 | .btn-primary:not(:disabled):not(.disabled).active, .btn-primary:not(:disabled):not(.disabled):active {
363 | color: #FFF;
364 | background-color: #3A44E1;
365 | border-color: #2F39E0
366 | }
367 |
368 | .btn-primary:not(:disabled):not(.disabled).active:focus, .btn-primary:not(:disabled):not(.disabled):active:focus {
369 | -webkit-box-shadow: 0 0 0 .2rem rgba(102, 110, 232, .5);
370 | box-shadow: 0 0 0 .2rem rgba(102, 110, 232, .5)
371 | }
372 |
373 | .btn-secondary:not(:disabled):not(.disabled).active, .btn-secondary:not(:disabled):not(.disabled):active, .fc button:not(:disabled):not(.disabled).active, .fc button:not(:disabled):not(.disabled):active, .fc-toolbar .fc-state-active:not(:disabled):not(.disabled), .fc-toolbar .ui-state-active:not(:disabled):not(.disabled) {
374 | color: #FFF;
375 | background-color: #6C757D;
376 | border-color: #666E76
377 | }
378 |
379 | .btn-secondary:not(:disabled):not(.disabled).active:focus, .btn-secondary:not(:disabled):not(.disabled):active:focus, .fc button:not(:disabled):not(.disabled).active:focus, .fc button:not(:disabled):not(.disabled):active:focus, .fc-toolbar .fc-state-active:not(:disabled):not(.disabled):focus, .fc-toolbar .ui-state-active:not(:disabled):not(.disabled):focus {
380 | -webkit-box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5);
381 | box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5)
382 | }
383 |
384 | .btn-success:hover {
385 | color: #FFF;
386 | background-color: #22B07D;
387 | border-color: #20A576
388 | }
389 |
390 | .btn-success:focus {
391 | -webkit-box-shadow: 0 0 0 .2rem rgba(40, 208, 148, .5);
392 | box-shadow: 0 0 0 .2rem rgba(40, 208, 148, .5)
393 | }
394 |
395 | .btn-success:disabled {
396 | color: #212529;
397 | background-color: #28D094;
398 | border-color: #28D094
399 | }
400 |
401 | .btn-success:not(:disabled):not(.disabled).active, .btn-success:not(:disabled):not(.disabled):active {
402 | color: #FFF;
403 | background-color: #20A576;
404 | border-color: #1E9B6E
405 | }
406 |
407 | .btn-success:not(:disabled):not(.disabled).active:focus, .btn-success:not(:disabled):not(.disabled):active:focus {
408 | -webkit-box-shadow: 0 0 0 .2rem rgba(40, 208, 148, .5);
409 | box-shadow: 0 0 0 .2rem rgba(40, 208, 148, .5)
410 | }
411 |
412 | .btn-info:not(:disabled):not(.disabled).active, .btn-info:not(:disabled):not(.disabled):active {
413 | color: #FFF;
414 | background-color: #0C84D1;
415 | border-color: #0B7CC5
416 | }
417 |
418 | .btn-info:not(:disabled):not(.disabled).active:focus, .btn-info:not(:disabled):not(.disabled):active:focus {
419 | -webkit-box-shadow: 0 0 0 .2rem rgba(30, 159, 242, .5);
420 | box-shadow: 0 0 0 .2rem rgba(30, 159, 242, .5)
421 | }
422 |
423 | .btn-warning:not(:disabled):not(.disabled).active, .btn-warning:not(:disabled):not(.disabled):active {
424 | color: #FFF;
425 | background-color: #FF7216;
426 | border-color: #FF6A09
427 | }
428 |
429 | .btn-warning:not(:disabled):not(.disabled).active:focus, .btn-warning:not(:disabled):not(.disabled):active:focus {
430 | -webkit-box-shadow: 0 0 0 .2rem rgba(255, 145, 73, .5);
431 | box-shadow: 0 0 0 .2rem rgba(255, 145, 73, .5)
432 | }
433 |
434 | .btn-danger:not(:disabled):not(.disabled).active, .btn-danger:not(:disabled):not(.disabled):active {
435 | color: #FFF;
436 | background-color: #FF1635;
437 | border-color: #FF092A
438 | }
439 |
440 | .btn-danger:not(:disabled):not(.disabled).active:focus, .btn-danger:not(:disabled):not(.disabled):active:focus {
441 | -webkit-box-shadow: 0 0 0 .2rem rgba(255, 73, 97, .5);
442 | box-shadow: 0 0 0 .2rem rgba(255, 73, 97, .5)
443 | }
444 |
445 | .btn-light:not(:disabled):not(.disabled).active, .btn-light:not(:disabled):not(.disabled):active {
446 | color: #212529;
447 | background-color: #DAE0E5;
448 | border-color: #D3D9DF
449 | }
450 |
451 | .btn-light:not(:disabled):not(.disabled).active:focus, .btn-light:not(:disabled):not(.disabled):active:focus {
452 | -webkit-box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5);
453 | box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5)
454 | }
455 |
456 | .btn-dark:not(:disabled):not(.disabled).active, .btn-dark:not(:disabled):not(.disabled):active {
457 | color: #FFF;
458 | background-color: #1D2124;
459 | border-color: #171A1D
460 | }
461 |
462 | .btn-dark:not(:disabled):not(.disabled).active:focus, .btn-dark:not(:disabled):not(.disabled):active:focus {
463 | -webkit-box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5);
464 | box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5)
465 | }
466 |
467 | .btn-base:not(:disabled):not(.disabled).active, .btn-base:not(:disabled):not(.disabled):active {
468 | color: #FFF;
469 | background-color: #858585;
470 | border-color: #7E7E7E
471 | }
472 |
473 | .btn-base:not(:disabled):not(.disabled).active:focus, .btn-base:not(:disabled):not(.disabled):active:focus {
474 | -webkit-box-shadow: 0 0 0 .2rem rgba(158, 158, 158, .5);
475 | box-shadow: 0 0 0 .2rem rgba(158, 158, 158, .5)
476 | }
477 |
478 | .btn-outline-primary:not(:disabled):not(.disabled).active, .btn-outline-primary:not(:disabled):not(.disabled):active {
479 | color: #FFF;
480 | background-color: #666EE8;
481 | border-color: #666EE8
482 | }
483 |
484 | .btn-outline-primary:not(:disabled):not(.disabled).active:focus, .btn-outline-primary:not(:disabled):not(.disabled):active:focus {
485 | -webkit-box-shadow: 0 0 0 .2rem rgba(102, 110, 232, .5);
486 | box-shadow: 0 0 0 .2rem rgba(102, 110, 232, .5)
487 | }
488 |
489 | .btn-outline-secondary:not(:disabled):not(.disabled).active, .btn-outline-secondary:not(:disabled):not(.disabled):active {
490 | color: #FFF;
491 | background-color: #868E96;
492 | border-color: #868E96
493 | }
494 |
495 | .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, .btn-outline-secondary:not(:disabled):not(.disabled):active:focus {
496 | -webkit-box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5);
497 | box-shadow: 0 0 0 .2rem rgba(134, 142, 150, .5)
498 | }
499 |
500 | .btn-outline-success:hover {
501 | border-color: #28D094
502 | }
503 |
504 | .btn-outline-success:focus {
505 | -webkit-box-shadow: 0 0 0 .2rem rgba(40, 208, 148, .5);
506 | box-shadow: 0 0 0 .2rem rgba(40, 208, 148, .5)
507 | }
508 |
509 | .btn-outline-success:disabled {
510 | color: #28D094;
511 | background-color: transparent
512 | }
513 |
514 | .btn-outline-success:not(:disabled):not(.disabled).active, .btn-outline-success:not(:disabled):not(.disabled):active {
515 | color: #212529;
516 | background-color: #28D094;
517 | border-color: #28D094
518 | }
519 |
520 | .btn-outline-success:not(:disabled):not(.disabled).active:focus, .btn-outline-success:not(:disabled):not(.disabled):active:focus {
521 | -webkit-box-shadow: 0 0 0 .2rem rgba(40, 208, 148, .5);
522 | box-shadow: 0 0 0 .2rem rgba(40, 208, 148, .5)
523 | }
524 |
525 | .btn-outline-info:not(:disabled):not(.disabled).active, .btn-outline-info:not(:disabled):not(.disabled):active {
526 | color: #FFF;
527 | background-color: #1E9FF2;
528 | border-color: #1E9FF2
529 | }
530 |
531 | .btn-outline-info:not(:disabled):not(.disabled).active:focus, .btn-outline-info:not(:disabled):not(.disabled):active:focus {
532 | -webkit-box-shadow: 0 0 0 .2rem rgba(30, 159, 242, .5);
533 | box-shadow: 0 0 0 .2rem rgba(30, 159, 242, .5)
534 | }
535 |
536 | .btn-outline-warning:not(:disabled):not(.disabled).active, .btn-outline-warning:not(:disabled):not(.disabled):active {
537 | color: #212529;
538 | background-color: #FF9149;
539 | border-color: #FF9149
540 | }
541 |
542 | .btn-outline-warning:not(:disabled):not(.disabled).active:focus, .btn-outline-warning:not(:disabled):not(.disabled):active:focus {
543 | -webkit-box-shadow: 0 0 0 .2rem rgba(255, 145, 73, .5);
544 | box-shadow: 0 0 0 .2rem rgba(255, 145, 73, .5)
545 | }
546 |
547 | .btn-outline-danger:not(:disabled):not(.disabled).active, .btn-outline-danger:not(:disabled):not(.disabled):active {
548 | color: #FFF;
549 | background-color: #FF4961;
550 | border-color: #FF4961
551 | }
552 |
553 | .btn-outline-danger:not(:disabled):not(.disabled).active:focus, .btn-outline-danger:not(:disabled):not(.disabled):active:focus {
554 | -webkit-box-shadow: 0 0 0 .2rem rgba(255, 73, 97, .5);
555 | box-shadow: 0 0 0 .2rem rgba(255, 73, 97, .5)
556 | }
557 |
558 | .btn-outline-light:not(:disabled):not(.disabled).active, .btn-outline-light:not(:disabled):not(.disabled):active {
559 | color: #212529;
560 | background-color: #F8F9FA;
561 | border-color: #F8F9FA
562 | }
563 |
564 | .btn-outline-light:not(:disabled):not(.disabled).active:focus, .btn-outline-light:not(:disabled):not(.disabled):active:focus {
565 | -webkit-box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5);
566 | box-shadow: 0 0 0 .2rem rgba(248, 249, 250, .5)
567 | }
568 |
569 | .btn-outline-dark:not(:disabled):not(.disabled).active, .btn-outline-dark:not(:disabled):not(.disabled):active {
570 | color: #FFF;
571 | background-color: #343A40;
572 | border-color: #343A40
573 | }
574 |
575 | .btn-outline-dark:not(:disabled):not(.disabled).active:focus, .btn-outline-dark:not(:disabled):not(.disabled):active:focus {
576 | -webkit-box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5);
577 | box-shadow: 0 0 0 .2rem rgba(52, 58, 64, .5)
578 | }
579 |
580 | .btn-outline-base:not(:disabled):not(.disabled).active, .btn-outline-base:not(:disabled):not(.disabled):active {
581 | color: #212529;
582 | background-color: #9E9E9E;
583 | border-color: #9E9E9E
584 | }
585 |
586 | .btn-outline-base:not(:disabled):not(.disabled).active:focus, .btn-outline-base:not(:disabled):not(.disabled):active:focus {
587 | -webkit-box-shadow: 0 0 0 .2rem rgba(158, 158, 158, .5);
588 | box-shadow: 0 0 0 .2rem rgba(158, 158, 158, .5)
589 | }
590 |
591 | .btn-sm {
592 | padding: .25rem .5rem;
593 | font-size: .875rem;
594 | line-height: 1.5;
595 | border-radius: .2rem
596 | }
597 |
598 | .input-group > .form-control:not(:last-child) {
599 | border-top-right-radius: 0;
600 | border-bottom-right-radius: 0
601 | }
602 |
603 | .input-group {
604 | display: -webkit-box;
605 | display: -webkit-flex;
606 | display: -moz-box;
607 | display: -ms-flexbox
608 | }
609 |
610 | .input-group {
611 | position: relative;
612 | display: flex;
613 | -webkit-flex-wrap: wrap;
614 | -ms-flex-wrap: wrap;
615 | flex-wrap: wrap;
616 | -webkit-box-align: stretch;
617 | -webkit-align-items: stretch;
618 | -moz-box-align: stretch;
619 | -ms-flex-align: stretch;
620 | align-items: stretch;
621 | width: 100%;
622 | }
623 |
624 | .input-group > .form-control {
625 | position: relative;
626 | -webkit-box-flex: 1;
627 | -webkit-flex: 1 1 auto;
628 | -moz-box-flex: 1;
629 | -ms-flex: 1 1 auto;
630 | flex: 1 1 auto;
631 | width: 1%;
632 | margin-bottom: 0
633 | }
634 |
635 | .input-group > .form-control:focus {
636 | z-index: 3
637 | }
638 |
639 | .navbar {
640 | display: -webkit-box;
641 | display: -webkit-flex;
642 | display: -moz-box;
643 | display: -ms-flexbox;
644 | -webkit-flex-wrap: wrap
645 | }
646 |
647 | .navbar-toggler-icon {
648 | content: ''
649 | }
650 |
651 | .nav-link {
652 | display: inline-block;
653 | padding: .5rem 1rem
654 | }
655 |
656 | .nav-link:focus, .nav-link:hover {
657 | text-decoration: none
658 | }
659 |
660 | .navbar {
661 | display: flex;
662 | -ms-flex-wrap: wrap;
663 | flex-wrap: wrap;
664 | -webkit-box-align: center;
665 | -webkit-align-items: center;
666 | -moz-box-align: center;
667 | -ms-flex-align: center;
668 | align-items: center;
669 | -webkit-box-pack: justify;
670 | -webkit-justify-content: space-between;
671 | -moz-box-pack: justify;
672 | -ms-flex-pack: justify;
673 | justify-content: space-between
674 | }
675 |
676 | .navbar > .container {
677 | display: -webkit-box;
678 | display: -webkit-flex;
679 | display: -moz-box;
680 | display: -ms-flexbox;
681 | display: flex;
682 | -webkit-flex-wrap: wrap;
683 | -ms-flex-wrap: wrap;
684 | flex-wrap: wrap;
685 | -webkit-box-align: center;
686 | -webkit-align-items: center;
687 | -moz-box-align: center;
688 | -ms-flex-align: center;
689 | align-items: center;
690 | -webkit-box-pack: justify;
691 | -webkit-justify-content: space-between;
692 | -moz-box-pack: justify;
693 | -ms-flex-pack: justify;
694 | justify-content: space-between
695 | }
696 |
697 | .navbar-brand {
698 | display: inline-block;
699 | padding-top: .3125rem;
700 | padding-bottom: .3125rem;
701 | margin-right: 1.5rem;
702 | font-size: 1.25rem;
703 | line-height: inherit
704 | }
705 |
706 | .card, .navbar-nav {
707 | display: -webkit-box;
708 | display: -webkit-flex;
709 | display: -moz-box;
710 | display: -ms-flexbox
711 | }
712 |
713 | .navbar-brand:focus, .navbar-brand:hover {
714 | text-decoration: none
715 | }
716 |
717 |
718 | .navbar-nav {
719 | display: flex;
720 | -webkit-flex-direction: column;
721 | -ms-flex-direction: column;
722 | flex-direction: column;
723 | padding-left: 0;
724 | margin-bottom: 0
725 | }
726 |
727 | .navbar-collapse {
728 | -webkit-flex-basis: 100%;
729 | -ms-flex-preferred-size: 100%;
730 | flex-basis: 100%;
731 | -webkit-box-flex: 1;
732 | -webkit-flex-grow: 1;
733 | -moz-box-flex: 1;
734 | -ms-flex-positive: 1;
735 | flex-grow: 1;
736 | -webkit-box-align: center;
737 | -webkit-align-items: center;
738 | -moz-box-align: center;
739 | -ms-flex-align: center;
740 | align-items: center
741 | }
742 |
743 | .navbar-toggler {
744 | padding: .25rem .75rem;
745 | font-size: 1.25rem;
746 | line-height: 1;
747 | background-color: transparent;
748 | border: 1px solid transparent;
749 | border-radius: .25rem
750 | }
751 |
752 | .navbar-toggler:focus, .navbar-toggler:hover {
753 | text-decoration: none
754 | }
755 |
756 | .navbar-toggler-icon {
757 | display: inline-block;
758 | width: 1.5em;
759 | height: 1.5em;
760 | vertical-align: middle;
761 | background: center center no-repeat;
762 | -webkit-background-size: 100% 100%;
763 | background-size: 100% 100%
764 | }
765 |
766 |
767 | .card {
768 | -webkit-box-orient: vertical;
769 | -moz-box-orient: vertical;
770 | -webkit-box-direction: normal;
771 | -moz-box-direction: normal;
772 | }
773 |
774 | .navbar-light .navbar-brand, .navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover {
775 | color: rgba(0, 0, 0, .9)
776 | }
777 |
778 | .navbar-light .navbar-toggler {
779 | color: rgba(0, 0, 0, .5);
780 | border-color: rgba(0, 0, 0, .1)
781 | }
782 |
783 | .navbar-light .navbar-toggler-icon {
784 | background-image: url('data:image/svg+xml;charset=utf8,%3Csvg viewBox=\'0 0 30 30\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath stroke=\'rgba(0, 0, 0, 0.5)\' stroke-width=\'2\' stroke-linecap=\'round\' stroke-miterlimit=\'10\' d=\'M4 7h22M4 15h22M4 23h22\'/%3E%3C/svg%3E')
785 | }
786 |
787 | .card {
788 | position: relative;
789 | display: flex;
790 | -webkit-flex-direction: column;
791 | -ms-flex-direction: column;
792 | flex-direction: column;
793 | min-width: 0;
794 | word-wrap: break-word;
795 | background-color: #FFF;
796 | -webkit-background-clip: border-box;
797 | background-clip: border-box
798 | }
799 |
800 | .card-body {
801 | -webkit-box-flex: 1;
802 | -webkit-flex: 1 1 auto;
803 | -moz-box-flex: 1;
804 | -ms-flex: 1 1 auto;
805 | flex: 1 1 auto;
806 | padding: 1.25rem
807 | }
808 |
809 | .card-header {
810 | padding: .75rem 1.25rem;
811 | background-color: rgba(0, 0, 0, .03)
812 | }
813 |
814 | .card-title {
815 | margin-bottom: .75rem;
816 | font-weight: bolder !important;
817 | }
818 |
819 | .card-header {
820 | margin-bottom: 0
821 | }
822 |
823 | .card-header {
824 | border-bottom: 1px solid rgba(0, 0, 0, .125)
825 | }
826 |
827 | .card-header:first-child {
828 | border-radius: -webkit-calc(.25rem - 1px) -webkit-calc(.25rem - 1px) 0 0;
829 | border-radius: -moz-calc(.25rem - 1px) -moz-calc(.25rem - 1px) 0 0;
830 | border-radius: calc(.25rem - 1px) calc(.25rem - 1px) 0 0
831 | }
832 |
833 | .badge {
834 | line-height: 1
835 | }
836 |
837 | .badge {
838 | display: inline-block;
839 | text-align: center;
840 | border-radius: .25rem
841 | }
842 |
843 | .badge-pill {
844 | padding-right: .6em;
845 | padding-left: .6em;
846 | border-radius: 10rem
847 | }
848 |
849 | .badge-success {
850 | color: #212529;
851 | background-color: #28D094;
852 | }
853 |
854 | .badge-info {
855 | color: #FFF;
856 | background-color: #1E9FF2
857 | }
858 |
859 | .badge-danger {
860 | color: #FFF;
861 | background-color: #FF4961
862 | }
863 |
864 | .close:not(:disabled):not(.disabled):focus, .close:not(:disabled):not(.disabled):hover {
865 | color: #000;
866 | text-decoration: none;
867 | opacity: .75
868 | }
869 |
870 | .badge, p {
871 | letter-spacing: .3px
872 | }
873 |
874 | @supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)) {
875 | }
876 |
877 | @supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)) {
878 | }
879 |
880 | @supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)) {
881 | }
882 |
883 | @supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)) {
884 | }
885 |
886 | .bg-light {
887 | background-color: #F8F9FA !important
888 | }
889 |
890 | @supports ((position:-webkit-sticky) or (position:sticky)) {
891 | }
892 |
893 | .my-2 {
894 | margin-top: .75rem !important
895 | }
896 |
897 | .my-2 {
898 | margin-bottom: .75rem !important
899 | }
900 |
901 | .mr-auto {
902 | margin-right: auto !important
903 | }
904 |
905 |
906 | .text-right {
907 | text-align: right !important
908 | }
909 |
910 | .text-white {
911 | color: #FFF !important
912 | }
913 |
914 | @media print {
915 | img {
916 | page-break-inside: avoid
917 | }
918 |
919 | *, ::after, ::before {
920 | text-shadow: none !important;
921 | -webkit-box-shadow: none !important;
922 | box-shadow: none !important
923 | }
924 |
925 | a:not(.btn) {
926 | text-decoration: underline
927 | }
928 |
929 | h3, p {
930 | orphans: 3;
931 | widows: 3
932 | }
933 |
934 | h3 {
935 | page-break-after: avoid
936 | }
937 |
938 | @page {
939 | size: a3
940 | }
941 |
942 | .container, body {
943 | min-width: 992px !important
944 | }
945 |
946 | .navbar {
947 | display: none
948 | }
949 |
950 | .badge {
951 | border: 1px solid #000
952 | }
953 | }
954 |
955 | .btn-success {
956 | background-color: #28D094 !important;
957 | color: #FFF !important;
958 | border-color: #28D094
959 | }
960 |
961 | .btn-outline-success:focus {
962 | background-color: transparent !important;
963 | color: #28D094 !important
964 | }
965 |
966 | .btn-outline-success:focus {
967 | -webkit-box-shadow: transparent !important;
968 | box-shadow: transparent !important
969 | }
970 |
971 | .btn-outline-success {
972 | border: 1px solid #28D094;
973 | background-color: transparent;
974 | color: #28D094;
975 | -webkit-box-shadow: none !important;
976 | box-shadow: none !important
977 | }
978 |
979 | .btn-outline-success:hover {
980 | background-color: #26C38B !important;
981 | color: #FFF !important
982 | }
983 |
984 | .card {
985 | /* font-size: 1rem;
986 | font-weight: 400;*/
987 | }
988 |
989 |
990 | body {
991 | font-family: 'Open+Sans', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
992 | font-weight: 300;
993 | line-height: 1.5em;
994 | color: rgba(97, 97, 97, .87);
995 | min-height: 100vh
996 | }
997 |
998 | h1, h3, h5 {
999 | font-family: Montserrat, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif
1000 | }
1001 |
1002 | .content-wrapper {
1003 | /* padding: 0 15px*/
1004 | }
1005 |
1006 | h1, h3, h5 {
1007 | font-weight: 300;
1008 | line-height: 1.15em;
1009 | color: #454545
1010 | }
1011 |
1012 | a {
1013 | color: #666EE8
1014 | }
1015 |
1016 | a:focus, a:hover {
1017 | color: #5059E5;
1018 | text-decoration: none
1019 | }
1020 |
1021 | p {
1022 | font-size: 1rem
1023 | }
1024 |
1025 | .badge {
1026 | padding: 6px 10px;
1027 | font-size: 85%;
1028 | font-weight: 500
1029 | }
1030 |
1031 | .badge-pill {
1032 | padding: 3px 6px
1033 | }
1034 |
1035 | .btn[class*=btn-] {
1036 | margin-bottom: 1rem
1037 | }
1038 |
1039 | .input-group {
1040 | margin-bottom: 1rem
1041 | }
1042 |
1043 | .input-group .btn[class*=btn-] {
1044 | margin-bottom: 0
1045 | }
1046 |
1047 | .btn:active {
1048 | background-image: initial
1049 | }
1050 |
1051 | .card {
1052 | border: 0;
1053 | margin: 15px 0;
1054 | -webkit-box-shadow: 0 6px 0 0 rgb(0 0 0 / 1%), 0 15px 32px 0 #eda9c324;
1055 | box-shadow: 0 6px 0 0 rgb(0 0 0 / 1%), 0 15px 32px 0 #eda9c324;
1056 | border-radius: 20px;
1057 |
1058 | }
1059 |
1060 | .card .card-header {
1061 | padding: 1.5rem;
1062 | border-bottom: none;
1063 | background-color: transparent
1064 | }
1065 |
1066 | .card .card-body {
1067 | padding: 0;
1068 | height: auto
1069 | }
1070 |
1071 | .card .card-block {
1072 | padding: 1rem 1.5rem 1.5rem
1073 | }
1074 |
1075 | select.form-control {
1076 | padding-top: 0 !important;
1077 | padding-bottom: 0 !important
1078 | }
1079 |
1080 | .form-control:disabled {
1081 | background-color: #ECEFF1
1082 | }
1083 |
1084 | .navbar {
1085 | border: 0;
1086 | border-radius: 0
1087 | }
1088 |
1089 | .navbar .navbar-brand {
1090 | position: relative
1091 | }
1092 |
1093 | .navbar .navbar-nav {
1094 | display: block;
1095 | margin-right: -18px
1096 | }
1097 |
1098 | h1 {
1099 | font-size: 2.5rem
1100 | }
1101 |
1102 | h3 {
1103 | font-size: 1.75rem
1104 | }
1105 |
1106 | h5 {
1107 | font-size: 1.25rem
1108 | }
1109 |
1110 | li {
1111 | line-height: 2rem
1112 | }
1113 |
1114 | .text-success {
1115 | color: #28D094 !important
1116 | }
1117 |
1118 | html {
1119 | width: 100%;
1120 | }
1121 |
1122 | * {
1123 | -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
1124 | -webkit-tap-highlight-color: transparent
1125 | }
1126 |
1127 | :focus {
1128 | outline: 0
1129 | }
1130 |
1131 | a:active, a:focus, button::-moz-focus-inner, button:active, button:focus, button:hover, select::-moz-focus-inner {
1132 | outline: 0 !important
1133 | }
1134 |
1135 | .btn-round {
1136 | border-radius: 30px
1137 | }
1138 |
1139 | .form-control:focus {
1140 | border-color: #666EE8 !important
1141 | }
1142 |
1143 | .wrapper.menu-collapsed .app-sidebar:not(:hover) .navigation li .has-sub > a, .wrapper.menu-collapsed .app-sidebar:not(:hover) .navigation li > a, .wrapper.menu-collapsed .off-canvas-sidebar:not(:hover) .navigation li .has-sub > a, .wrapper.menu-collapsed .off-canvas-sidebar:not(:hover) .navigation li > a {
1144 | padding: 7px 0
1145 | }
1146 |
1147 | .wrapper.menu-collapsed .app-sidebar:not(:hover) .navigation li.has-sub > a:after, .wrapper.menu-collapsed .off-canvas-sidebar:not(:hover) .navigation li.has-sub > a:after {
1148 | display: none
1149 | }
1150 |
1151 | .wrapper.menu-collapsed .app-sidebar:not(:hover) .navigation li.nav-collapsed-open > a, .wrapper.menu-collapsed .off-canvas-sidebar:not(:hover) .navigation li.nav-collapsed-open > a {
1152 | -webkit-box-shadow: 0 6px 14px 2px rgba(0, 0, 0, .2);
1153 | box-shadow: 0 6px 14px 2px rgba(0, 0, 0, .2);
1154 | border-radius: 50%;
1155 | padding: 4px 0 4px 4px;
1156 | margin-left: 8px;
1157 | margin-right: 12px
1158 | }
1159 |
1160 | .wrapper.menu-collapsed .app-sidebar:not(:hover) .navigation li.nav-collapsed-open > a i, .wrapper.menu-collapsed .off-canvas-sidebar:not(:hover) .navigation li.nav-collapsed-open > a i {
1161 | color: #FF4961 !important
1162 | }
1163 |
1164 | .wrapper.menu-collapsed .app-sidebar:not(:hover) .navigation > li > a, .wrapper.menu-collapsed .off-canvas-sidebar:not(:hover) .navigation > li > a {
1165 | padding: 4px;
1166 | margin-left: 8px;
1167 | margin-right: 12px
1168 | }
1169 |
1170 | .wrapper.menu-collapsed .app-sidebar:not(:hover) .navigation > li.active ~ .nav-collapsed-open > a, .wrapper.menu-collapsed .off-canvas-sidebar:not(:hover) .navigation > li.active ~ .nav-collapsed-open > a {
1171 | background-color: transparent !important
1172 | }
1173 |
1174 | .wrapper.menu-collapsed .app-sidebar:not(:hover) .navigation > li.active ~ .nav-collapsed-open > a > i, .wrapper.menu-collapsed .off-canvas-sidebar:not(:hover) .navigation > li.active ~ .nav-collapsed-open > a > i {
1175 | color: #FFF !important
1176 | }
1177 |
1178 | .wrapper.menu-collapsed .app-sidebar:not(:hover)[data-background-color=white] .navigation li.nav-collapsed-open a, .wrapper.menu-collapsed .off-canvas-sidebar:not(:hover)[data-background-color=white] .navigation li.nav-collapsed-open a {
1179 | background-image: -webkit-linear-gradient(45deg, #FC00FF, #00DBDE);
1180 | background-image: -o-linear-gradient(45deg, #FC00FF, #00DBDE);
1181 | background-image: linear-gradient(45deg, #FC00FF, #00DBDE);
1182 | background-repeat: repeat-x;
1183 | color: #FFF
1184 | }
1185 |
1186 | .wrapper.menu-collapsed .app-sidebar:not(:hover)[data-background-color=white] .navigation li.nav-collapsed-open a i, .wrapper.menu-collapsed .off-canvas-sidebar:not(:hover)[data-background-color=white] .navigation li.nav-collapsed-open a i {
1187 | color: #FFF !important
1188 | }
1189 |
1190 | .wrapper .app-sidebar:not(:hover) .navigation li.nav-collapsed-open > a, .wrapper .off-canvas-sidebar:not(:hover) .navigation li.nav-collapsed-open > a {
1191 | background-color: #FFF;
1192 | -webkit-transition: background-color .4s ease-in;
1193 | -o-transition: background-color .4s ease-in;
1194 | -moz-transition: background-color .4s ease-in;
1195 | transition: background-color .4s ease-in
1196 | }
1197 |
1198 | .wrapper .app-sidebar:not(:hover)[data-background-color=white] .navigation li.active a, .wrapper .off-canvas-sidebar:not(:hover)[data-background-color=white] .navigation li.active a {
1199 | background-image: -webkit-linear-gradient(45deg, #FC00FF, #00DBDE);
1200 | background-image: -o-linear-gradient(45deg, #FC00FF, #00DBDE);
1201 | background-image: linear-gradient(45deg, #FC00FF, #00DBDE);
1202 | background-repeat: repeat-x
1203 | }
1204 |
1205 | .wrapper .app-sidebar:not(:hover)[data-background-color=white] .navigation > li.nav-collapsed-open > a, .wrapper .app-sidebar:not(:hover)[data-background-color=white] .navigation > li.nav-collapsed-open > a i, .wrapper .off-canvas-sidebar:not(:hover)[data-background-color=white] .navigation > li.nav-collapsed-open > a, .wrapper .off-canvas-sidebar:not(:hover)[data-background-color=white] .navigation > li.nav-collapsed-open > a i {
1206 | color: #000
1207 | }
1208 |
1209 | .wrapper .app-sidebar:not([data-background-color=white]):not(:hover) .navigation > li.nav-collapsed-open > a, .wrapper .app-sidebar:not([data-background-color=white]):not(:hover) .navigation > li.nav-collapsed-open > a i, .wrapper .off-canvas-sidebar:not([data-background-color=white]):not(:hover) .navigation > li.nav-collapsed-open > a, .wrapper .off-canvas-sidebar:not([data-background-color=white]):not(:hover) .navigation > li.nav-collapsed-open > a i {
1210 | color: #FF4961
1211 | }
1212 |
1213 |
1214 | .btn:active:focus, .btn:focus {
1215 | outline: 0
1216 | }
1217 |
1218 | a {
1219 | cursor: pointer
1220 | }
1221 |
1222 | .round {
1223 | border: 1px solid rgba(128, 128, 128, 0.11);
1224 | border-radius: 4px;
1225 | padding: 2px;
1226 | padding-left: 5px;
1227 | font-size: 14px;
1228 | display: inline-block;
1229 | width: 60%;
1230 | height: 30px;
1231 | }
1232 |
1233 | .navbar {
1234 | position: fixed;
1235 | top: 0;
1236 | right: 0;
1237 | left: 0;
1238 | z-index: 4;
1239 | background-color: #FFF;
1240 | padding: .5rem 1.5rem;
1241 | -webkit-box-shadow: 0 6px 0 0 rgb(0 0 0 / 1%), 0 15px 32px 0 #ea6af50f;
1242 | box-shadow: 0 6px 0 0 rgb(0 0 0 / 1%), 0 15px 32px 0 #ea6af50f;
1243 | }
1244 |
1245 | .navbar.navbar-light .nav-link {
1246 | color: rgba(0, 0, 0, .5)
1247 | }
1248 |
1249 | .card {
1250 | background-color: rgba(255, 255, 255, 0.85)
1251 | }
1252 |
1253 | .card-header {
1254 | padding-top: 10px !important;
1255 | padding-bottom: 10px !important;
1256 | border-bottom: 1px dashed #efefef !important;
1257 | }
1258 |
1259 | .card-title {
1260 | margin-bottom: 0 !important;
1261 | }
1262 |
1263 | .card-block {
1264 | padding-top: 10px !important;
1265 | padding-bottom: 10px !important;
1266 | }
1267 |
1268 | .navbar {
1269 | position: relative
1270 | }
1271 |
1272 | [v-cloak] {
1273 | display: none !important;
1274 | }
1275 |
1276 | .button-click {
1277 | position: relative;
1278 | border-radius: 10px;
1279 | border: 1px solid transparent;
1280 | display: inline-block;
1281 | -webkit-user-select: none;
1282 | -moz-user-select: none;
1283 | -ms-user-select: none;
1284 | user-select: none;
1285 | cursor: pointer;
1286 | padding: 4px 8px;
1287 | margin: 0 12px 8px 0;
1288 | -webkit-transition: all .3s ease;
1289 | transition: all .3s ease;
1290 | -webkit-box-shadow: 0 1px 4px 0 #ff99e899;
1291 | box-shadow: 0 1px 4px 0 #ff99e899;
1292 | font-weight: bolder;
1293 | }
1294 |
1295 | .checked {
1296 | border: 1px dashed #3effb8;
1297 | }
1298 |
1299 | .button-click:hover {
1300 | border: 1px dashed #3effb8;
1301 | }
1302 |
1303 | .hr-top {
1304 | border-bottom: 1px dashed #e5e5e5;
1305 | padding: 10px 0;
1306 | position: relative;
1307 | }
1308 |
1309 | .empty-commodity {
1310 | background-color: #ced4dadb;
1311 | opacity: 0.6;
1312 | }
1313 |
1314 | .commodity-icon {
1315 | height: 21px;
1316 | margin-top: -3px;
1317 | border-radius: 6px;
1318 | }
1319 |
1320 | .description {
1321 | overflow: hidden;
1322 | }
1323 |
1324 | .anticipation tbody tr {
1325 | position: relative;
1326 | border-radius: 4px;
1327 | border: 1px solid transparent;
1328 | display: inline-block;
1329 | cursor: pointer;
1330 | margin: 0 5px 5px 0;
1331 | padding: 0 8px 0 8px;
1332 | -webkit-transition: all .3s ease;
1333 | transition: all .3s ease;
1334 | -webkit-box-shadow: 0 0 3px 0 rgba(0, 0, 0, .2);
1335 | box-shadow: 0 0 3px 0 rgba(0, 0, 0, .2);
1336 | width: 100%;
1337 | background-color: white;
1338 | /* white-space: nowrap;*/
1339 | overflow: hidden;
1340 | text-overflow: ellipsis;
1341 | font-size: 14px;
1342 | }
1343 |
1344 | .anticipation tbody tr label {
1345 | width: 100%;
1346 | display: inline-block;
1347 | margin: 0;
1348 | }
1349 |
1350 | .anticipation thead th button:focus {
1351 | outline: 1px solid lavender;
1352 | }
1353 |
1354 | .anticipation thead th button {
1355 | overflow: hidden;
1356 | position: relative;
1357 | border-radius: 4px;
1358 | border: 1px solid transparent;
1359 | display: inline-block;
1360 | cursor: pointer;
1361 | margin-bottom: 4px;
1362 | -webkit-transition: all .3s ease;
1363 | transition: all .3s ease;
1364 | -webkit-box-shadow: 0 0 3px 0 rgba(0, 0, 0, .2);
1365 | box-shadow: 0 0 3px 0 rgba(0, 0, 0, .2);
1366 | color: #a3a0a0;
1367 | width: 49.79321%;
1368 | background-color: white;
1369 | font-size: 14px;
1370 | }
1371 |
1372 | table {
1373 | width: 100%;
1374 | }
1375 |
1376 | .price_tips {
1377 | color: #f98ac3;
1378 | font-size: 14px;
1379 | display: inline-block;
1380 | border-radius: 10px;
1381 | background: -moz-linear-gradient(top, #ffdede6e 0%, #ffffff 100%);
1382 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffdede6e), color-stop(100%, #ffffff));
1383 | background: -webkit-linear-gradient(top, #ffdede6e 0%, #ffffff 100%);
1384 | background: -o-linear-gradient(top, #ffdede6e 0%, #ffffff 100%);
1385 | background: -ms-linear-gradient(top, #ffdede6e 0%, #ffffff 100%);
1386 | background: linear-gradient(to bottom, #ffdede6e 0%, #ffffff 100%);
1387 | }
1388 |
1389 | .price {
1390 | font-weight: bolder;
1391 | font-size: 18px;
1392 | }
1393 |
1394 |
1395 | .otaku {
1396 | background-image: -webkit-gradient(linear, left 0, right 0, from(rgb(166, 4, 249)), to(rgb(251, 223, 11)));
1397 | -webkit-background-clip: text;
1398 | -webkit-text-fill-color: transparent;
1399 | }
1400 |
--------------------------------------------------------------------------------
/static/theme/css/layer.css:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 原神玩家后台~
17 |
18 |
19 |
20 |
",success:function(e,i){s.bigimg=e.find(".layui-layer-phimg"),s.imgsee=e.find(".layui-layer-imgbar"),s.event(e),t.tab&&t.tab(u[d],e),"function"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off("keyup",s.keyup)}},t))},function(){r.close(s.loadi),r.msg("当前图片地址异常
是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i("html"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define("jquery",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t("layer",r)})):"function"==typeof define&&define.amd?define(["jquery"],function(){return o.run(e.jQuery),r}):function(){r.ready(),o.run(e.jQuery)}()}(window);
--------------------------------------------------------------------------------
/static/theme/js/pay.js:
--------------------------------------------------------------------------------
1 | var Pay = {
2 | setCache(key, value, expire = 0) {
3 | localStorage.setItem("cache_" + key, JSON.stringify({
4 | data: value,
5 | expire: expire,
6 | time: Math.round(new Date().getTime() / 1000)
7 | }));
8 | },
9 | getCache(key) {
10 | key = "cache_" + key;
11 |
12 | let item = localStorage.getItem(key);
13 | if (!item) {
14 | return null;
15 | }
16 |
17 | item = JSON.parse(item);
18 |
19 | if (item.expire != 0 && Math.round(new Date().getTime() / 1000) > item.time + item.expire) {
20 | localStorage.removeItem(key);
21 | return null;
22 | }
23 |
24 | return item.data;
25 | },
26 |
27 | isPc() {
28 | var userAgentInfo = navigator.userAgent;
29 | var Agents = ["Android", "iPhone",
30 | "SymbianOS", "Windows Phone",
31 | "iPad", "iPod"];
32 | var flag = true;
33 | for (var v = 0; v < Agents.length; v++) {
34 | if (userAgentInfo.indexOf(Agents[v]) > 0) {
35 | flag = false;
36 | break;
37 | }
38 | }
39 | return flag;
40 | }
41 | ,
42 | isIphone() {
43 | var ua = navigator.userAgent;
44 | var ipad = ua.match(/(iPad).*OS\s([\d_]+)/i), ipod = ua.match(/(iPod).*OS\s([\d_]+)/i);
45 | let result = !ipod && !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/i);
46 | return Boolean(result);
47 | }
48 | ,
49 | isIpad() {
50 | var ua = navigator.userAgent;
51 | var ipad = ua.match(/(iPad).*OS\s([\d_]+)/i);
52 | return Boolean(ipad);
53 | }
54 | ,
55 | isAndroid() {
56 | var ua = navigator.userAgent;
57 | var android = ua.match(/(Android)\s+([\d.]+)/i);
58 | return Boolean(android);
59 | }
60 | ,
61 | isMobile() {
62 | return this.isAndroid() || this.isIphone();
63 | }
64 | ,
65 | isAlipay() {
66 | var ua = navigator.userAgent;
67 | var alipay = ua.match(/(AlipayClient)/i);
68 | return Boolean(alipay);
69 | }
70 | ,
71 | isWx() {
72 | var ua = navigator.userAgent;
73 | var wx = ua.match(/(MicroMessenger)/i);
74 | return Boolean(wx);
75 | },
76 | $get(url, done, error = null) {
77 | let loaderIndex = layer.load(2, {shade: ['0.3', '#fff']});
78 | $.get(url, res => {
79 | layer.close(loaderIndex);
80 | if (res.code !== 200) {
81 | layer.msg(res.msg);
82 | typeof error === 'function' && error(res);
83 | return;
84 | }
85 | typeof done === 'function' && done(res.data);
86 | });
87 | },
88 | $post(url, data, done, error = null) {
89 | let loaderIndex = layer.load(2, {shade: ['0.3', '#fff']});
90 | $.post(url, data, res => {
91 | layer.close(loaderIndex);
92 | if (res.code !== 200) {
93 | layer.msg(res.msg);
94 | typeof error === 'function' && error(res);
95 | return;
96 | }
97 | typeof done === 'function' && done(res.data);
98 | });
99 | },
100 | getWebSiteInfo(done) {
101 | let cacheKey = "site_info";
102 | let data = Pay.getCache(cacheKey);
103 | if (data) {
104 | typeof done === 'function' && done(data);
105 | return;
106 | }
107 | this.$get("/user/api/site/info", data => {
108 | if (setting_cache == 1) {
109 | Pay.setCache(cacheKey, data, setting_cache_expire);
110 | }
111 | typeof done === 'function' && done(data);
112 | });
113 | },
114 | getCategory(done) {
115 | let data = Pay.getCache("category");
116 | if (data) {
117 | typeof done === 'function' && done(data);
118 | return;
119 | }
120 | this.$get("/user/api/index/data", data => {
121 | if (setting_cache == 1) {
122 | Pay.setCache("category", data, setting_cache_expire);
123 | }
124 | typeof done === 'function' && done(data);
125 | });
126 | },
127 | getCommodityAll(categoryId, done) {
128 | let cacheKey = "commodity_" + categoryId;
129 | let data = Pay.getCache(cacheKey);
130 | if (data) {
131 | typeof done === 'function' && done(data);
132 | return;
133 | }
134 | this.$get("/user/api/index/commodity?categoryId=" + categoryId, data => {
135 | if (setting_cache == 1) {
136 | Pay.setCache(cacheKey, data, setting_cache_expire);
137 | }
138 | typeof done === 'function' && done(data);
139 | });
140 | },
141 | getCommodityDetail(commodityId, done) {
142 | let cacheKey = "commodityDetail_" + commodityId;
143 | let data = Pay.getCache(cacheKey);
144 | if (data) {
145 | typeof done === 'function' && done(data);
146 | return;
147 | }
148 | this.$get("/user/api/index/commodityDetail?commodityId=" + commodityId, data => {
149 | if (setting_cache == 1) {
150 | Pay.setCache(cacheKey, data, 10);
151 | }
152 | typeof done === 'function' && done(data);
153 | });
154 | },
155 | getDraftCard(commodityId, page, race, done) {
156 | this.$get("/user/api/index/card?commodityId=" + commodityId + "&page=" + page + "&race=" + race, done);
157 | },
158 | getPay(done) {
159 | let cacheKey = "pay";
160 | let data = Pay.getCache(cacheKey);
161 | if (data) {
162 | typeof done === 'function' && done(data);
163 | return;
164 | }
165 | this.$get("/user/api/index/pay", data => {
166 | if (setting_cache == 1) {
167 | Pay.setCache(cacheKey, data, setting_cache_expire);
168 | }
169 | typeof done === 'function' && done(data);
170 | });
171 | },
172 | getTradeAmount(commodityId, coupon, cardId, num, race, done) {
173 | this.$post("/user/api/index/tradeAmount", {
174 | num: num,
175 | cardId: cardId,
176 | coupon: coupon,
177 | commodityId: commodityId,
178 | race: race
179 | }, done);
180 | },
181 | trade(option, done, error) {
182 | this.$post("/user/api/order/trade", option, done, error);
183 | },
184 | getQuery(keywords, done, error) {
185 | this.$post("/user/api/index/query", {
186 | keywords: keywords
187 | }, done, error);
188 | },
189 | getSecret(orderId, password, done, error) {
190 | this.$post("/user/api/index/secret", {
191 | orderId: orderId,
192 | password: password
193 | }, done, error);
194 | },
195 | device() {
196 | let device = 0;
197 | if (this.isAndroid()) {
198 | device = 1;
199 | } else if (this.isIphone()) {
200 | device = 2;
201 | } else if (this.isIpad()) {
202 | device = 3;
203 | }
204 | return device;
205 | },
206 | $_GET(variable) {
207 | var query = window.location.search.substring(1);
208 | var vars = query.split("&");
209 | for (var i = 0; i < vars.length; i++) {
210 | var pair = vars[i].split("=");
211 | if (pair[0] == variable) {
212 | return pair[1];
213 | }
214 | }
215 | return 0;
216 | },
217 | getLangTime(start, end) {
218 | var seconds = 1000;
219 | var minutes = seconds * 60;
220 | var hours = minutes * 60;
221 | var days = hours * 24;
222 | var years = days * 365;
223 | var t1 = start;
224 | var t2 = end;
225 | var diff = t2 - t1;
226 | var diffYears = Math.floor(diff / years);
227 | var diffDays = Math.floor((diff / days) - diffYears * 365);
228 | var diffHours = Math.floor((diff - (diffYears * 365 + diffDays) * days) / hours);
229 | var diffMinutes = Math.floor((diff - (diffYears * 365 + diffDays) * days - diffHours * hours) / minutes);
230 | var diffSeconds = Math.floor((diff - (diffYears * 365 + diffDays) * days - diffHours * hours - diffMinutes * minutes) / seconds);
231 | return {
232 | days: diffDays,
233 | hours: diffHours,
234 | minutes: diffMinutes,
235 | seconds: diffSeconds,
236 | }
237 | },
238 | arrayToObject(serializeArray) {
239 | let paramsToJSONObject = {};
240 | serializeArray.forEach(item => {
241 | if (item.name.match(RegExp(/\[\]/))) {
242 | let name = item.name.replace("[]", "");
243 | if (!paramsToJSONObject.hasOwnProperty(name)) {
244 | paramsToJSONObject[name] = [];
245 | }
246 | paramsToJSONObject[name].push(item.value);
247 | } else {
248 | paramsToJSONObject[item.name] = item.value.replace(/\+/g, "%2B").replace(/\&/g, "%26");
249 | }
250 | });
251 | return paramsToJSONObject;
252 | }
253 | }
--------------------------------------------------------------------------------
/static/theme/js/theme/default/layer.css:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 原神玩家后台~
17 |
18 |
19 |
20 |