Initial commit

This commit is contained in:
WIN-VSNMD38DUOC\Administrator
2024-03-07 19:25:30 +08:00
commit 2946829d06
84 changed files with 58318 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
server:
port: 8098
servlet:
context-path: /fmt
spring:
thymeleaf:
enabled: true #开启thymeleaf视图解析
encoding: UTF-8 #编码为UTF-8
cache: false #是否使用缓存开发环境建议使用false线上使用true
mode: HTML #严格执行HTML语法格式
servlet:
content-type: text/html #模式
servlet:
multipart:
max-file-size: 1024MB
max-request-size: 10240MB
somkit:
upload:
path:
windows: D://data/install/upload
linux: /mnt/files
db:
rocks:
path:
windows: D://RocksDB//fmt
linux: /usr/local/rocksdb/fmt
column-family: default
logging:
socket:
#日志文件地址
log-file-path: D:/logs/fmt/fmt-server.log
#最大读取展示行数
max-read-length: 500
#读取间隔时间 毫秒
read-interval: 1000
logging:
config: classpath:logback-spring.xml

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>package</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<!--拷贝application.yml文件到jar包的外部config目录下面-->
<fileSet>
<directory>${basedir}/src/main/resources</directory>
<includes>
<include>*.yml</include>
</includes>
<filtered>true</filtered>
<outputDirectory>${file.separator}config</outputDirectory>
</fileSet>
<!--拷贝执行文件到jar包的外部bin目录下面-->
<fileSet>
<directory>${basedir}/src/main/resources/bin</directory>
<includes>
<include>*.bat</include>
<include>*.sh</include>
</includes>
<filtered>true</filtered>
<outputDirectory>${file.separator}bin</outputDirectory>
</fileSet>
<!--拷贝lib包到jar包的外部lib下面-->
<fileSet>
<directory>${project.build.directory}/lib</directory>
<outputDirectory>${file.separator}lib</outputDirectory>
<!-- 打包需要包含的文件 -->
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<!--如有需要,可以配置多个需要拷贝的文件即可-->
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>${file.separator}</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,5 @@
chcp 65001
SET JAR=D:/fmt/fmt-1.1.0.jar
SET JAR_CONFIG=D:/fmt/config/
SET JAR_LIB=D:/fmt/lib/
java -Dfile.encoding=utf-8 -jar %JAR% --spring.config.location=%JAR_CONFIG% --spring.lib.location=%JAR_LIB%

View File

@@ -0,0 +1,8 @@
#!/bin/bash
JAR=/home/deploy/fmt/fmt-1.1.0.jar
JAR_CONFIG=/home/deploy/fmt/config/
JAR_LIB=/home/deploy/fmt/lib/
JAVA_HOME=/usr/local/jdk-17.0.7
JAVA=$JAVA_HOME/bin/java
nohup $JAVA -jar $JAR --spring.config.location=$JAR_CONFIG --spring.lib.location=$JAR_LIB -Djava.ext.dirs=$JAVA_HOME/lib &
tail -f nohup.out

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!-- Spring Boot 默认日志配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!-- 定义日志的根目录 -->
<property name="LOG_HOME" value="/logs/fmt"/>
<!-- 定义日志文件名称 -->
<property name="APP_NAME" value="fmt-server"/>
<!-- 日志输出到控制台 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定日志文件的名称 -->
<file>${LOG_HOME}/${APP_NAME}.log</file>
<!--
当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
TimeBasedRollingPolicy 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动
%i当文件大小超过maxFileSize时按照i进行文件滚动
-->
<fileNamePattern>${LOG_HOME}/${APP_NAME}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!--
可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
且maxHistory是365则只保存最近365天的文件删除之前的旧文件。注意删除旧文件是
那些为了归档而创建的目录也会被删除。
-->
<MaxHistory>365</MaxHistory>
<!--
当日志文件超过maxFileSize指定的大小是根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的必须配置timeBasedFileNamingAndTriggeringPolicy
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 日志输出格式: -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] [%-5level] [%logger{50}] -> %msg%n</pattern>
<charset>UTF-8</charset>
</layout>
</appender>
<!-- 指定日志输出级别以及启动的Appender -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="160px" height="160px" viewBox="0 0 160 160">
<rect y="0" fill="#FAFAFA" width="80" height="160"/>
<rect x="80" fill="#F2F2F2" width="80" height="160"/>
<path fill="#B2B2B2" d="M98.916,97.252c10.393-6.382,17.34-17.851,17.34-30.916c0-19.992-16.266-36.255-36.257-36.255
c-19.992,0-36.255,16.263-36.255,36.255c0,13.064,6.946,24.534,17.338,30.916C34.114,105.371,14.467,130.387,14.467,160h131.066
C145.533,130.387,125.885,105.371,98.916,97.252z"/>
</svg>

After

Width:  |  Height:  |  Size: 498 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="150"></svg>

After

Width:  |  Height:  |  Size: 71 B

View File

@@ -0,0 +1 @@
<svg t="1589899525104" class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" p-id="2529" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M118.826971 138.409143a7.968041 7.968041 0 0 0 7.920612-7.920612V111.351003a7.920612 7.920612 0 1 0-15.841225 0v19.173099a7.968041 7.968041 0 0 0 7.920613 7.920613z m14.596218 14.596218h19.184956a7.920612 7.920612 0 1 0 0-15.841224H133.435046a7.920612 7.920612 0 1 0 0 15.841224z m-29.192437-15.781938H85.057653a7.920612 7.920612 0 0 0 0 15.841224h19.173099a7.920612 7.920612 0 0 0 0-15.841224z m14.596219 14.584361a7.968041 7.968041 0 0 0-7.920613 7.920612v19.173099a7.920612 7.920612 0 0 0 15.841225 0v-19.149385a7.968041 7.968041 0 0 0-7.920612-7.920612z m788.50407 118.27561a38.725628 38.725628 0 1 0 38.725628 38.725629 38.6782 38.6782 0 0 0-38.7612-38.784915z m0 61.49146a22.884404 22.884404 0 1 1 22.884403-22.884403 22.919975 22.919975 0 0 1-22.884403 22.884403zM692.525932 47.87939a23.500978 23.500978 0 1 0-23.500979-23.500978 23.500978 23.500978 0 0 0 23.500979 23.500978z m0-31.303019a7.671611 7.671611 0 1 1-7.671611 7.671611 7.707183 7.707183 0 0 1 7.671611-7.671611z m0 0" fill="#e6e6e6" p-id="2530"></path><path d="M275.768923 992.815553c0 11.145772 38.156483 21.342967 99.849516 26.963282a1197.186323 1197.186323 0 0 0 199.91246 0c61.906462-5.572886 99.849515-15.81751 99.849516-26.963282s-38.156483-21.342967-99.849516-26.963282a1197.020322 1197.020322 0 0 0-199.91246 0c-61.657461 5.572886-99.849515 15.81751-99.849516 26.963282z m0 0" fill="#f0f0f0" p-id="2531"></path><path d="M571.025162 482.896493a7.766469 7.766469 0 0 0-11.133915 0l-11.99949 11.99949-11.999491-11.99949a7.873183 7.873183 0 1 0-11.133914 11.133914l11.99949 11.999491-11.99949 11.99949a7.956184 7.956184 0 1 0 11.252486 11.252487l11.999491-11.999491 11.99949 11.999491a7.778326 7.778326 0 0 0 5.572886 2.371441 7.576753 7.576753 0 0 0 5.572886-2.371441 7.766469 7.766469 0 0 0 0-11.133915l-11.99949-11.99949 11.99949-11.999491a8.110328 8.110328 0 0 0-0.118572-11.252486z m-154.902514 46.397239a7.873183 7.873183 0 0 0 5.572886 2.371441 7.873183 7.873183 0 0 0 5.572886-13.481641l-11.999491-11.999491 11.999491-11.99949a7.766469 7.766469 0 0 0 0-11.133915 7.991756 7.991756 0 0 0-11.264344 0l-11.999491 11.999491-11.99949-11.999491a7.991756 7.991756 0 0 0-11.264344 0 7.766469 7.766469 0 0 0 0 11.133915l11.999491 11.99949-11.999491 11.999491a7.766469 7.766469 0 0 0 0 11.133915 7.778326 7.778326 0 0 0 5.572886 2.37144 7.576753 7.576753 0 0 0 5.572886-2.37144l11.99949-11.999491z m59.87888 83.391716a107.390697 107.390697 0 0 0-77.451256 32.65474 7.956184 7.956184 0 0 0 0.118572 11.133915 7.837612 7.837612 0 0 0 11.133914-0.118572 92.616621 92.616621 0 0 1 132.385684 0 8.157756 8.157756 0 0 0 5.691457 2.371441 7.825755 7.825755 0 0 0 7.304038-4.825882 8.01547 8.01547 0 0 0-1.61258-8.655759 107.758271 107.758271 0 0 0-77.569829-32.536168z m0 0" fill="#dbdbdb" p-id="2532"></path><path d="M768.601753 313.872049l-82.14671-91.679902a94.229201 94.229201 0 0 0-70.147219-31.303019H246.505344a85.905443 85.905443 0 0 0-85.858015 85.858015v564.651914a85.905443 85.905443 0 0 0 85.858015 85.858015h459.490372a85.905443 85.905443 0 0 0 85.858014-85.858015V374.616505a91.063327 91.063327 0 0 0-23.263834-60.744456z m-94.027628-81.162562l82.14671 91.679902a77.427543 77.427543 0 0 1 14.228645 23.263834h-85.490442a38.962773 38.962773 0 0 1-38.97463-38.97463v-95.877352a77.285256 77.285256 0 0 1 28.089717 19.920103z m101.450238 608.701428a70.123505 70.123505 0 0 1-70.028647 70.028647H246.505344a70.123505 70.123505 0 0 1-70.028647-70.028647V276.747143a70.123505 70.123505 0 0 1 70.028647-70.028647h369.80248a79.443267 79.443267 0 0 1 14.347217 1.363578v100.584662a54.910712 54.910712 0 0 0 54.803997 54.803997h89.699749a84.35215 84.35215 0 0 1 0.865576 11.133915v466.794409z m0 0" fill="#dbdbdb" p-id="2533"></path></svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,16 @@
<svg width="18" height="18" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" stroke="#ffffff">
<g fill="none" fill-rule="evenodd">
<g transform="translate(1 1)" stroke-width="1">
<circle stroke-opacity=".2" cx="14" cy="14" r="12"/>
<path d="M14,26C7.372,26,2,20.629,2,14">
<animateTransform
attributeName="transform"
type="rotate"
from="0 14 14"
to="360 14 14"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 623 B

View File

@@ -0,0 +1,16 @@
<svg width="18" height="18" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" stroke="#198cff">
<g fill="none" fill-rule="evenodd">
<g transform="translate(1 1)" stroke-width="1">
<circle stroke-opacity=".2" cx="14" cy="14" r="12"/>
<path d="M14,26C7.372,26,2,20.629,2,14">
<animateTransform
attributeName="transform"
type="rotate"
from="0 14 14"
to="360 14 14"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 623 B

View File

@@ -0,0 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="160px" height="160px" viewBox="0 0 160 160">
<rect fill="#FFFFFF" width="160" height="160"/>
<g>
<g>
<g>
<path fill="#C9CACA" d="M79.087,87.86H61.983c-1.717,0-3.108-1.223-3.109-2.73v-2.111l9.163-6.958l3.284,2.841
c1.708,1.486,4.422,1.585,6.262,0.228L93.07,67.625l6.226,5.479c0.628,0.591,0.892,0.858,1.58,0.858
c0.493,0,0.904-0.244,1.219-0.587c0.333-0.363,0.311-1.238,0.311-1.672V57.81c0-3.018-2.783-5.465-6.218-5.465H61.983
c-3.435,0-6.218,2.447-6.218,5.465v27.32c0,1.448,0.655,2.839,1.821,3.863c1.167,1.023,2.749,1.601,4.397,1.601h17.071
c0.795,0,1.525-0.567,1.582-1.265c0.065-0.8-0.653-1.467-1.547-1.467L79.087,87.86z M58.875,57.81
c0-1.509,1.392-2.732,3.109-2.732h34.203c1.718,0,3.109,1.223,3.109,2.732v11.434l-4.123-3.629
c-1.152-0.857-2.84-0.86-3.996-0.008L75.587,77.029c-0.613,0.449-1.513,0.417-2.082-0.075l-3.287-2.84
c-1.159-0.993-2.989-1.044-4.216-0.121l-7.127,5.42L58.875,57.81L58.875,57.81z M67.004,64.215c0,1.658,0.999,3.153,2.53,3.787
c1.532,0.635,3.295,0.285,4.467-0.888c1.173-1.172,1.522-2.935,0.889-4.466c-0.635-1.531-2.129-2.531-3.787-2.531
c-1.087,0-2.13,0.432-2.898,1.2C67.436,62.086,67.004,63.127,67.004,64.215L67.004,64.215z M102.338,79.737
c3.737,3.733,3.737,9.786,0,13.52c-3.735,3.735-9.789,3.736-13.523,0c-3.682-3.744-3.655-9.754,0.057-13.463
C92.583,76.082,98.595,76.056,102.338,79.737L102.338,79.737z M90.745,91.325c2.295,2.294,5.886,2.657,8.593,0.869l-9.462-9.464
c-1.787,2.706-1.424,6.298,0.869,8.592V91.325z M101.272,90.259c1.782-2.708,1.416-6.295-0.875-8.585
c-2.293-2.29-5.879-2.657-8.587-0.875L101.272,90.259z M101.272,90.259"/>
</g>
</g>
<text transform="matrix(1 0 0 1 54.8237 110.5508)" fill="#C9CACA" font-family="'MicrosoftYaHei'" font-size="12.5877">暂无图片</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,88 @@
@charset "utf-8";
/*!
*Last modified: 2022-11-23 11:33:09
*名称: ax-rate.css
*简介: 评星插件的css文件
*用法: new axRate('#id',{参数})
*版本: v1.0.0
*演示: https://www.axui.cn/v2.0/ax-tree.php
*客服: 3217728223@qq.com
*交流: QQ群952502085
*作者: AXUI团队
*/
.ax-rate {
display: flex;
justify-content: flex-start;
align-items: center;
}
.ax-rate ul {
display: inline-flex;
}
.ax-rate li.ax-item {
width: 1.8rem;
height: 1.8rem;
line-height: 1.8rem;
margin: 0 0.2rem;
cursor: pointer;
position: relative;
}
.ax-rate li.ax-item i {
font-size: 1.8rem;
text-align: left;
height: 100%;
overflow: hidden;
position: absolute;
left: 0;
top: 0;
}
.ax-rate li.ax-item i:first-child {
width: 0%;
z-index: 2;
transition: width 100ms linear;
}
.ax-rate li.ax-item i:first-child:before {
color: #ff8400;
transition: color 100ms linear;
}
.ax-rate li.ax-item i.ax-half:first-child {
width: 50%;
}
.ax-rate li.ax-item i.ax-full:first-child {
width: 100%;
}
.ax-rate li.ax-item i:last-child {
width: 100%;
}
.ax-rate li.ax-item i:last-child:before {
color: #f5e7d7;
}
.ax-rate[size=md] li.ax-item {
width: 2.8rem;
height: 2.8rem;
line-height: 2.8rem;
}
.ax-rate[size=md] li.ax-item i {
font-size: 2.8rem;
}
.ax-rate[size=lg] li.ax-item {
width: 3.8rem;
height: 3.8rem;
line-height: 3.8rem;
}
.ax-rate[size=lg] li.ax-item i {
font-size: 3.8rem;
}
.ax-rate [clear] {
font-size: 1.4rem;
color: #ccc;
margin-right: 0.4rem;
transition: all 100ms linear;
}
.ax-rate [clear]:hover {
cursor: pointer;
color: #dc3545;
}
.ax-rate .ax-tips {
font-size: 1.4rem;
margin-left: 0.4rem;
}

View File

@@ -0,0 +1,263 @@
/*!
*Last modified: 2023-06-04 21:01:53
*名称: axRate.js
*简介: 评星插件的js文件
*用法: new axRate('#id',{参数})
*版本: v1.0.3
*演示: https://www.axui.cn/v2.0/ax-rate.php
*客服: 3217728223@qq.com
*交流: QQ群952502085
*作者: AXUI团队
*/
class axRate {
constructor(elem, options) {
this.targetDom = axIdToDom(elem);
this.options = axExtend({
insName: '',
half: false,
icon: 'ax-iconfont ax-icon-star-f',
count: 5,
multiplier: 1,
value: 0,
readonly: false,
popShow: false,
popTheme: 'ad',
popFormat: '<i stars></i>星,总分:<i value></i>',
tipsShow: false,
tipsFormat: '<i stars></i>星,总分:<i value></i>',
clearShow: false,
size: '',
rendered: '',
getValue: '',
setValue: '',
}, options, this.targetDom, this.constructor.name);
this.handlers = {};
if (!this.targetDom || this.targetDom.nodeName == 'INPUT') {
this.parent = axAddElem('div', { class: 'ax-rate' });
if (this.targetDom.nodeName == 'INPUT') {
this.hidden = this.targetDom;
this.hidden.insertAdjacentElement('beforeBegin', this.parent);
this.hidden.type != 'hidden' ? this.hidden.style.display = 'none' : null;
}
} else {
this.parent = this.targetDom;
}
this.value = 0;
this.stars = 0;
this.items = [];
this.init();
return this;
}
init() {
axInstance.push(this, this.options.insName, 'rate');
this.renderRate();
this.set(this.options.value);
let pop;
if (this.options.popShow) {
pop = axAddElem('div', { class: 'ax-rate-popcon' }, this.options.popFormat);
this.tooltip = new axTooltip(this.items[0].dom, {
trigger: 'none',
theme: this.options.popTheme,
content: pop,
});
new axHover(this.ul, {
enter: () => {
this.tooltip.popup.show()
},
leave: () => {
this.tooltip.popup.hide();
},
hold: this.tooltip.popup.targetDom,
});
}
if (!this.options.readonly) {
this.clear.onclick = () => {
this.set(0);
}
this.items.forEach((item) => {
let itemDom = item.dom,
firstChild = itemDom.firstElementChild,
before = this.items.filter(i => i.id < item.id),
after = this.items.filter(i => i.id > item.id);
if (this.options.popShow) {
new axHover(itemDom, {
enter: () => {
this.tooltip.popup.updatePosition(itemDom);
},
});
}
itemDom.onmousemove = (e) => {
let place = this.movePlace(e, itemDom);
before.forEach(i => {
i.dom.firstElementChild.classList.add('ax-full');
i.value = 1;
});
if (place == 'half') {
firstChild.classList.remove('ax-full');
firstChild.classList.add('ax-half');
} else if (place == 'full') {
firstChild.classList.remove('ax-half');
firstChild.classList.add('ax-full');
}
after.forEach(i => {
i.dom.firstElementChild.classList.remove('ax-half');
i.dom.firstElementChild.classList.remove('ax-full');
});
if (this.options.popShow) {
this.calculate(item, place, pop);
}
itemDom.onclick = () => {
if (place == 'half') {
item.value = 0.5;
} else if (place == 'full') {
item.value = 1;
} else {
item.value = 0;
}
this.calculate(item, place);
if (this.options.tipsShow) {
this.tipsValue ? this.tipsValue.innerHTML = this.value : null;
this.tipsStars ? this.tipsStars.innerHTML = this.stars : null;
}
this.options.getValue && this.options.getValue.call(this, this.value, this.stars);
this.handlers.hasOwnProperty('getValue') ? this.emit('getValue', this.value, this.stars) : null;
}
}
});
this.ul.onmouseleave = () => {
this.set(this.value);
this.options.setValue && this.options.setValue.call(this, this.value, this.stars);
this.handlers.hasOwnProperty('setValue') ? this.emit('setValue', this.value, this.stars) : null;
}
}
}
set(val) {
if (val <= 0) {
val = 0;
}
if (val >= this.options.multiplier * this.options.count) {
val = this.options.multiplier * this.options.count;
}
let stars = val / this.options.multiplier,
beforeStars = Math.floor(stars),
currentStar = stars - beforeStars;
if (!this.options.half) {
currentStar = 0;
}
if (!val) {
this.items.forEach(i => {
let dom = i.dom.firstElementChild;
dom.classList.remove('ax-half');
dom.classList.remove('ax-full');
i.value = 0;
});
} else {
for (let i = 0; i <= beforeStars - 1; i++) {
let dom = this.items[i].dom.firstElementChild;
dom.classList.remove('ax-half');
dom.classList.add('ax-full');
this.items[i].value = 1;
}
}
this.stars = beforeStars;
if (currentStar == 0.5) {
let dom = this.items[beforeStars].dom.firstElementChild;
dom.classList.remove('ax-full');
dom.classList.add('ax-half');
this.items[beforeStars].value = 0.5;
this.stars += 0.5;
beforeStars++;
}
for (let i = beforeStars; i < this.items.length; i++) {
let dom = this.items[i].dom.firstElementChild;
dom.classList.remove('ax-half');
dom.classList.remove('ax-full');
this.items[i].value = 0;
}
this.value = val;
this.tipsValue ? this.tipsValue.innerHTML = val : null;
this.tipsStars ? this.tipsStars.innerHTML = this.stars : null;
this.hidden ? this.hidden.value = val : null;
}
get(attr) {
let obj = { stars: this.stars, value: this.value, count: this.options.count, multiplier: this.options.multiplier };
return obj[attr];
}
calculate(item, place, pop) {
let before = this.items.filter(i => i.id < item.id),
stars = before.length;
if (place == 'half') {
stars += 0.5;
} else if (place == 'full') {
stars++;
}
if (pop) {
pop.querySelector('[stars]').innerHTML = stars;
pop.querySelector('[value]').innerHTML = this.options.multiplier * stars;
} else {
this.value = this.options.multiplier * stars;
this.stars = stars;
}
}
renderRate() {
let fragment = document.createDocumentFragment(),
star = `<i class="${this.options.icon}"></i>`,
itemHTML = `<li class="ax-item">
${star.repeat(2)}
</li>`;
this.ul = axAddElem('ul');
this.tips = axAddElem('div', { class: 'ax-tips' }, this.options.tipsFormat);
this.tipsStars = this.tips.querySelector('[stars]');
this.tipsValue = this.tips.querySelector('[value]');
this.clear = axAddElem('i', { class: 'ax-iconfont ax-icon-close-o-f', clear: '' });
this.options.clearShow ? fragment.appendChild(this.clear) : null;
for (let i = 1; i <= this.options.count; i++) {
let itemDom = axStrToDom(itemHTML),
obj = {
id: i,
value: 0,
dom: itemDom,
};
this.items.push(obj);
this.ul.appendChild(itemDom);
}
fragment.appendChild(this.ul);
this.options.tipsShow ? fragment.appendChild(this.tips) : null;
if (this.options.size) {
this.parent.setAttribute('size', this.options.size);
}
this.parent.appendChild(fragment);
this.options.rendered && this.options.rendered.call(this);
'rendered' in this.handlers ? this.emit('rendered', '') : null;
}
movePlace(e, node) {
if (!this.options.half) {
return 'full';
}
let leftOffset = node.getBoundingClientRect().left,
rightOffset = node.getBoundingClientRect().right,
half = ((rightOffset - leftOffset) / 2),
halfOffset = leftOffset + ~~half,
placement = 'full';
if (e.clientX < halfOffset) {
placement = 'half';
}
return placement;
}
on(type, handler) {
axAddPlan(type, handler, this);
return this;
}
emit(type, ...params) {
axExePlan(type, this, ...params);
}
off(type, handler) {
axDelPlan(type, handler, this);
return this;
}
}
(() => {
document.querySelectorAll('[axRate]').forEach(element => {
new axRate(element);
});
})();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,283 @@
@charset "utf-8";
/*!
*Last modified: 2023-06-11 12:34:54
*名称: ax-tree.css
*简介: tree树菜单的css文件
*用法: new axTree('#id',{参数})
*版本: v1.0.8
*演示: https://www.axui.cn/v2.0/ax-tree.php
*客服: 3217728223@qq.com
*交流: QQ群952502085
*作者: AXUI团队
*/
.ax-tree ul {
display: none;
}
.ax-tree .ax-node {
display: flex;
justify-content: flex-start;
align-items: center;
height: 2.8rem;
transition: all 200ms linear;
}
.ax-tree .ax-node:hover {
background-color: #f5f5f5;
}
.ax-tree [arrow] {
text-align: center;
width: 2.2rem;
height: 2.8rem;
line-height: 2.8rem;
background-position: center;
background-repeat: no-repeat;
background-size: 1.4rem;
position: relative;
}
.ax-tree [arrow]:not(.ax-none) {
cursor: pointer;
transition: all 200ms linear;
}
.ax-tree [arrow]:not(.ax-none).ax-different {
transform: none!important;
transition: none!important;
}
.ax-tree [arrow].ax-expand {
background-image: url(icons/expand.svg);
}
.ax-tree [arrow].ax-collapse {
background-image: url(icons/collapse.svg);
}
.ax-tree [arrow][loading]:before {
content: "";
display: inline-block;
width: 1.4rem;
height: 1.4rem;
background: var(--load) no-repeat scroll center;
background-size: cover;
}
.ax-tree [check] {
color: #666;
width: 2.2rem;
height: 2.2rem;
line-height: 2.2rem;
text-align: center;
cursor: pointer;
background-position: center;
background-size: 1.4rem;
background-repeat: no-repeat;
}
.ax-tree [check].ax-checkbox-unchecked {
background-image: url(icons/checkbox-unchecked.svg);
}
.ax-tree [check].ax-checkbox-checking {
background-image: url(icons/checkbox-checking.svg);
}
.ax-tree [check].ax-checkbox-checked {
background-image: url(icons/checkbox-checked.svg);
}
.ax-tree [check].ax-radio-unchecked {
background-image: url(icons/radio-unchecked.svg);
}
.ax-tree [check].ax-radio-checking {
background-image: url(icons/radio-checking.svg);
}
.ax-tree [check].ax-radio-checked {
background-image: url(icons/radio-checked.svg);
}
.ax-tree [legend] {
color: #666;
width: 2.2rem;
height: 2.2rem;
line-height: 2.2rem;
text-align: center;
background-position: center;
background-size: 1.4rem;
background-repeat: no-repeat;
}
.ax-tree [legend].ax-fold {
background-image: url(icons/fold.svg);
}
.ax-tree [legend].ax-unfold {
background-image: url(icons/unfold.svg);
}
.ax-tree [legend].ax-childless {
background-image: url(icons/childless.svg);
}
.ax-tree [label] {
line-height: 2.2rem;
padding: 0 0.4rem;
margin-right: 0.4rem;
white-space: nowrap;
position: relative;
cursor: pointer;
}
/*keyword highlighting搜索关键字高亮*/
.ax-tree [label] i {
color: #ff8400;
}
.ax-tree [toolsAction="hover"] [tools],
.ax-tree [toolsAction="click"] [tools] {
display: none;
}
.ax-tree [toolsAction="hover"]:hover [tools] {
display: inline-block;
}
.ax-tree [tools] {
height: 2.2rem;
line-height: 2.2rem;
}
.ax-tree [tools] i {
color: #666;
width: 2.2rem;
border-radius: 0.3rem;
text-align: center;
cursor: pointer;
transition: all 200ms linear;
}
.ax-tree [tools] i:hover {
color: #fff;
background-color: #198cff;
}
.ax-tree li select {
width: 9.2rem;
height: 2.2rem;
line-height: 2.2rem;
padding: 0 0 0 0.4rem;
}
.ax-tree .ax-node input[type*='text'] {
width: 9.2rem;
height: 2.2rem;
line-height: 2.2rem;
padding: 0 0.4rem;
}
.ax-tree [indent] i {
width: 2.2rem;
}
/*edit编辑*/
.ax-tree [editing] [label] {
padding: 0;
}
.ax-tree [editing] [tools] {
position: absolute;
left: -100000px;
}
/*expand展开*/
.ax-tree [expanded="true"] > [arrow]:not(.ax-none) {
color: #198cff;
transform: rotate(90deg);
}
/*checked勾选*/
.ax-tree [checked="true"] [check] {
color: #198cff;
}
/*selected已选择*/
.ax-tree [selected]:not([editing]) [label] {
color: #fff;
border-radius: 0.3rem;
background: #198cff;
}
/*disabled禁止勾选*/
.ax-tree [disabled] [check],
.ax-tree [disabled] [legend] {
cursor: not-allowed;
color: #b3b3b3;
}
/*draggable可拖拽*/
.ax-tree [draggable="true"] > div:hover {
cursor: grab;
}
/*readonly只读禁止编辑*/
.ax-tree [readonly] [tools] i,
.ax-tree [readonly] [tools] i:hover {
cursor: not-allowed;
color: #b3b3b3;
background: transparent;
}
/*focus聚焦新增和拖拽成为焦点如果本身是已选择状态则不做改变*/
.ax-tree .ax-node:focus:not([selected="true"]) [label] {
color: #198cff;
}
/*line节点连线*/
.ax-tree[line] [arrow].ax-none:before,
.ax-tree[line] [arrow].ax-none:after {
content: '';
width: calc(2.2rem / 2);
height: calc(2.8rem / 2);
position: absolute;
right: 0;
}
.ax-tree[line] [arrow].ax-none:before {
box-shadow: inset 1px -1px 0 0 #999;
top: 0;
}
.ax-tree[line] [arrow].ax-none:after {
box-shadow: inset 1px 0 0 0 #999;
bottom: 0;
}
.ax-tree[line] ul > li:last-child > div [arrow].ax-none:after {
display: none;
}
.ax-tree[line] > li:first-child > div [arrow].ax-none:before {
box-shadow: inset 0 -1px 0 0 #999;
}
.ax-tree[line] > li:last-child > div [arrow].ax-none:after {
display: none;
}
.ax-tree[line] ul > li [indent] {
line-height: 2.8rem;
position: relative;
}
.ax-tree[line] ul > li [indent] i {
line-height: 2.8rem;
height: 2.8rem;
position: relative;
}
.ax-tree[line] > li [indent] i:before,
.ax-tree[line] ul > li [indent] i:before {
content: '';
width: calc(2.2rem / 2);
height: 100%;
box-shadow: inset 1px 0 0 0 #999;
position: absolute;
top: 0;
right: 0;
}
/*drag拖拽节点*/
.ax-tree .ax-dragging > div [label] {
color: #198cff;
background: transparent;
}
.ax-tree .ax-dragging > div [label]:before {
content: '';
width: 0;
height: 0;
border-width: 4px;
border-style: solid;
border-color: transparent transparent transparent #198cff;
position: absolute;
left: -4px;
display: none;
}
.ax-tree .ax-dragging[insert="up"] > div [label]:before {
display: block;
top: -6px;
}
.ax-tree .ax-dragging[insert="down"] > div [label]:before {
display: block;
bottom: -6px;
}
.ax-tree .ax-dragging[insert="child"] > div [label]:before {
display: block;
top: 7px;
}
.ax-tree .ax-dragging[insert="child"] > div [label]:after {
content: '';
border: 1px solid #198cff;
border-radius: 0.3rem;
width: 100%;
height: 100%;
box-sizing: border-box;
position: absolute;
left: 0;
top: 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="1em" height="1em" viewBox="0 0 1024 1024">
<g>
<path fill="#198cff" d="M960,920c0,22.092-17.908,40-40,40H104c-22.091,0-40-17.908-40-40V104c0-22.091,17.909-40,40-40h816
c22.092,0,40,17.909,40,40V920z"/>
</g>
<path fill="#ffffff" d="M451.216,708.784c-10.609,0-20.783-4.214-28.284-11.716l-181.019-181.02
c-15.621-15.621-15.621-40.948,0-56.568c15.622-15.621,40.949-15.621,56.568,0l152.735,152.735l288.5-288.5
c15.621-15.621,40.947-15.621,56.568,0c15.621,15.621,15.621,40.947,0,56.568L479.5,697.068
C471.999,704.57,461.825,708.784,451.216,708.784z"/>
</svg>

After

Width:  |  Height:  |  Size: 623 B

View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="1em" height="1em" viewBox="0 0 1024 1024">
<rect x="96" y="96" fill="#EFF6FC" width="832" height="832"/>
<path fill="#198cff" d="M880,144v736H144V144H880 M920,64H104c-22.091,0-40,17.909-40,40v816c0,22.092,17.909,40,40,40h816
c22.092,0,40-17.908,40-40V104C960,81.909,942.092,64,920,64L920,64z"/>
<path fill="#198cff" d="M451.216,708.784c-10.609,0-20.783-4.214-28.284-11.716l-181.019-181.02
c-15.621-15.621-15.621-40.948,0-56.568c15.622-15.621,40.949-15.621,56.568,0l152.735,152.735l288.5-288.5
c15.621-15.621,40.947-15.621,56.568,0c15.621,15.621,15.621,40.947,0,56.568L479.5,697.068
C471.999,704.57,461.825,708.784,451.216,708.784z"/>
</svg>

After

Width:  |  Height:  |  Size: 709 B

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="1em" height="1em" viewBox="0 0 1024 1024">
<rect x="96" y="96" fill="#FFFFFF" width="832" height="832"/>
<path fill="#666666" d="M880,144v736H144V144H880 M920,64H104c-22.091,0-40,17.909-40,40v816c0,22.092,17.909,40,40,40h816
c22.092,0,40-17.908,40-40V104C960,81.909,942.092,64,920,64L920,64z"/>
</svg>

After

Width:  |  Height:  |  Size: 366 B

View File

@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="1em" height="1em" viewBox="0 0 1024 1024">
<polygon fill="#FEF9EB" points="672,96 864,288 864,928 160,928 160,96 "/>
<g>
<path fill="#ffc107" d="M670.862,144L816,289.138V880H208V144H670.862 M704,64H164.923C144.531,64,128,83.286,128,107.077v809.846
C128,940.714,144.531,960,164.923,960h694.154C879.47,960,896,940.714,896,916.923V256L704,64L704,64z"/>
</g>
<g>
<rect x="320" y="376" fill="#ffc107" width="288" height="80"/>
<rect x="320" y="536" fill="#ffc107" width="384" height="80"/>
<rect x="320" y="696" fill="#ffc107" width="384" height="80"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 629 B

View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="1em" height="1em" viewBox="0 0 1024 1024">
<rect x="96" y="96" fill="#FFFFFF" width="832" height="832"/>
<path fill="#666666" d="M880,144v736H144V144H880 M920,64H104c-22.091,0-40,17.909-40,40v816c0,22.092,17.909,40,40,40h816
c22.092,0,40-17.908,40-40V104C960,81.909,942.092,64,920,64L920,64z"/>
<polygon fill="#666666" points="776,472 552,472 552,248 472,248 472,472 248,472 248,552 472,552 472,776 552,776 552,552 776,552
"/>
</svg>

After

Width:  |  Height:  |  Size: 500 B

View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="1em" height="1em" viewBox="0 0 1024 1024">
<rect x="96" y="96" fill="#FFFFFF" width="832" height="832"/>
<path fill="#666666" d="M880,144v736H144V144H880 M920,64H104c-22.091,0-40,17.909-40,40v816c0,22.092,17.909,40,40,40h816
c22.092,0,40-17.908,40-40V104C960,81.909,942.092,64,920,64L920,64z"/>
<rect x="248" y="472" fill="#666666" width="528" height="80"/>
</svg>

After

Width:  |  Height:  |  Size: 429 B

View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="1em" height="1em" viewBox="0 0 1024 1024">
<path fill="#F3EBD5" d="M928,232c0-22.091-16.629-40-37.143-40H133.143C112.629,192,96,209.909,96,232v528
c0,22.092,16.629,40,37.143,40h757.714C911.371,800,928,782.092,928,760V232z"/>
<path fill="#E09F22" d="M928,504c0,22.092-16.629,40-37.143,40H133.143C112.629,544,96,526.092,96,504V169.484
c0-22.091,16.629-40,37.143-40c0,0,241.739,0,260,0c18.261,0,25.38,12.85,33.428,30.183C434.619,177,482.286,256,482.286,256
h408.572C911.371,256,928,273.909,928,296V504z"/>
<path fill="#F5BB1C" d="M928,298.105C928,274.851,911.371,256,890.857,256H133.143C112.629,256,96,274.851,96,298.105v555.789
C96,877.149,112.629,896,133.143,896h757.714C911.371,896,928,877.149,928,853.895V298.105z"/>
</svg>

After

Width:  |  Height:  |  Size: 792 B

View File

@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="1em" height="1em" viewBox="0 0 1024 1024">
<circle fill="#EFF6FC" cx="512" cy="512" r="416"/>
<path fill="#198cff" d="M512,144c49.715,0,97.9,9.719,143.218,28.886c43.812,18.531,83.176,45.076,116.997,78.898
c33.822,33.822,60.368,73.186,78.898,116.998C870.281,414.1,880,462.285,880,512s-9.719,97.9-28.887,143.218
c-18.53,43.812-45.076,83.176-78.898,116.997c-33.821,33.822-73.186,60.368-116.997,78.898C609.9,870.281,561.715,880,512,880
s-97.9-9.719-143.218-28.887c-43.812-18.53-83.175-45.076-116.998-78.898c-33.822-33.821-60.368-73.186-78.898-116.997
C153.719,609.9,144,561.715,144,512s9.719-97.9,28.886-143.218c18.531-43.812,45.076-83.175,78.898-116.998
s73.186-60.368,116.998-78.898C414.1,153.719,462.285,144,512,144 M512,64C264.576,64,64,264.576,64,512s200.576,448,448,448
s448-200.576,448-448S759.424,64,512,64L512,64z"/>
<g>
<circle fill="#198cff" cx="512" cy="512" r="224"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 959 B

View File

@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
width="1em" height="1em" viewBox="0 0 1024 1024" >
<circle fill="#EFF6FC" cx="512" cy="512" r="416"/>
<path fill="#198cff" d="M512,144c49.715,0,97.9,9.719,143.218,28.886c43.812,18.531,83.176,45.076,116.997,78.898
c33.822,33.822,60.368,73.186,78.898,116.998C870.281,414.1,880,462.285,880,512s-9.719,97.9-28.887,143.218
c-18.53,43.812-45.076,83.176-78.898,116.997c-33.821,33.822-73.186,60.368-116.997,78.898C609.9,870.281,561.715,880,512,880
s-97.9-9.719-143.218-28.887c-43.812-18.53-83.175-45.076-116.998-78.898c-33.822-33.821-60.368-73.186-78.898-116.997
C153.719,609.9,144,561.715,144,512s9.719-97.9,28.886-143.218c18.531-43.812,45.076-83.175,78.898-116.998
s73.186-60.368,116.998-78.898C414.1,153.719,462.285,144,512,144 M512,64C264.576,64,64,264.576,64,512s200.576,448,448,448
s448-200.576,448-448S759.424,64,512,64L512,64z"/>
<path fill="#198cff" d="M512,368c38.464,0,74.626,14.979,101.824,42.177C641.021,437.375,656,473.536,656,512
c0,38.465-14.979,74.626-42.176,101.824C586.626,641.021,550.465,656,512,656c-38.464,0-74.625-14.979-101.823-42.176
C382.979,586.626,368,550.464,368,512s14.979-74.625,42.177-101.823S473.536,368,512,368 M512,288c-123.711,0-224,100.289-224,224
c0,123.713,100.289,224,224,224c123.713,0,224-100.287,224-224C736,388.289,635.713,288,512,288L512,288z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
width="1em" height="1em" viewBox="0 0 1024 1024">
<circle fill="#FFFFFF" cx="512" cy="512" r="416"/>
<path fill="#666666" d="M512,144c49.715,0,97.9,9.719,143.218,28.886c43.812,18.531,83.176,45.076,116.997,78.898
c33.822,33.822,60.368,73.186,78.898,116.998C870.281,414.1,880,462.285,880,512s-9.719,97.9-28.887,143.218
c-18.53,43.812-45.076,83.176-78.898,116.997c-33.821,33.822-73.186,60.368-116.997,78.898C609.9,870.281,561.715,880,512,880
s-97.9-9.719-143.218-28.887c-43.812-18.53-83.175-45.076-116.998-78.898c-33.822-33.821-60.368-73.186-78.898-116.997
C153.719,609.9,144,561.715,144,512s9.719-97.9,28.886-143.218c18.531-43.812,45.076-83.175,78.898-116.998
s73.186-60.368,116.998-78.898C414.1,153.719,462.285,144,512,144 M512,64C264.576,64,64,264.576,64,512s200.576,448,448,448
s448-200.576,448-448S759.424,64,512,64L512,64z"/>
</svg>

After

Width:  |  Height:  |  Size: 900 B

View File

@@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
width="1em" height="1em" viewBox="0 0 1024 1024">
<path fill="#F3EBD5" d="M928,232c0-22.091-16.629-40-37.143-40H133.143C112.629,192,96,209.909,96,232v528
c0,22.092,16.629,40,37.143,40h757.714C911.371,800,928,782.092,928,760V232z"/>
<path fill="#E09F22" d="M928,504c0,22.092-16.629,40-37.143,40H133.143C112.629,544,96,526.092,96,504V169.484
c0-22.091,16.629-40,37.143-40c0,0,241.739,0,260,0c18.261,0,25.38,12.85,33.428,30.183C434.619,177,482.286,256,482.286,256
h408.572C911.371,256,928,273.909,928,296V504z"/>
<path fill="#F5BB1C" d="M1024,447.579c0-17.441-16.629-31.579-37.143-31.579H101.143C80.629,416,64,430.138,64,447.579l32,416.843
C96,881.861,112.629,896,133.143,896h757.714C911.371,896,928,881.861,928,864.422L1024,447.579z"/>
</svg>

After

Width:  |  Height:  |  Size: 804 B

View File

@@ -0,0 +1,120 @@
@charset "utf-8";
/*!
*Last modified: 2022-09-06 15:56:28
*名称: ax-scrollnav.css
*简介: scrollnav的css文件
*用法: scrollnav.init('#id',{参数})
*版本: v3.0.2
*演示: https://www.axui.cn/v2.0/ax-scrollnav.php
*客服: 3217728223@qq.com
*交流: QQ群952502085
*作者: AXUI团队
*/
.ax-scrollnav-v {
font-size: 1.2rem;
background-color: rgba(255, 255, 255, 0.1);
padding: 1.4rem;
line-height: 2.8rem;
max-height: calc(100vh - 12rem);
overflow: inherit;
position: fixed;
top: 6rem;
right: 1.4rem;
z-index: 610;
}
.ax-scrollnav-v .ax-close {
color: #198cff;
width: 3.8rem;
height: 3.8rem;
line-height: 3.8rem;
text-align: center;
border-radius: 3.8rem;
border: 1px solid #ebebeb;
background-color: rgba(255, 255, 255, 0.9);
box-sizing: border-box;
transition: all 200ms linear;
position: absolute;
right: 0;
bottom: calc(-3.8rem - 1.4rem);
}
.ax-scrollnav-v.ax-hide {
border-color: transparent;
background: transparent;
padding-left: 0;
padding-right: 0;
}
.ax-scrollnav-v.ax-hide .ax-scrollnav {
width: 0;
visibility: hidden;
}
.ax-scrollnav-v.ax-hide .ax-close {
color: #fff;
border-width: 0;
background-color: #198cff;
transform: rotate(180deg);
}
.ax-scrollnav-v:not(.ax-hide) .ax-close:hover {
border-color: #198cff;
background-color: #f0f7ff;
}
.ax-scrollnav-v li {
position: relative;
padding-left: 1.4rem;
white-space: nowrap;
border-left: 1px solid #f0f0f0;
}
.ax-scrollnav-v li.ax-active > a {
color: #198cff;
}
.ax-scrollnav-v li:before {
content: '';
height: 2.8rem;
width: 1px;
position: absolute;
left: -0.1rem;
top: 0;
}
.ax-scrollnav-v li.ax-active:before {
background-color: #198cff;
}
.ax-scrollnav-h {
background-color: #fff;
line-height: 3.8rem;
text-align: center;
position: relative;
z-index: 4;
}
.ax-scrollnav-h li {
margin: 0 1.4rem;
white-space: nowrap;
display: inline-block;
position: relative;
}
.ax-scrollnav-h li.ax-active > a {
color: #198cff;
}
.ax-scrollnav-h li:before {
content: '';
height: 0.2rem;
width: 100%;
transition: all 200ms linear;
position: absolute;
bottom: 0;
}
.ax-scrollnav-h li.ax-active:before {
background-color: #198cff;
}
/*Telephone & iPad*/
@media screen and (max-width: 900px) {
.ax-scrollnav-v {
background-color: rgba(255, 255, 255, 0.9);
border: 1px solid #ebebeb;
border-radius: 0.3rem;
top: auto;
bottom: 1.4rem;
}
.ax-scrollnav-v .ax-close {
top: calc(-3.8rem - 1.4rem);
bottom: auto;
}
}

View File

@@ -0,0 +1,146 @@
/*!
*Last modified: 2022-09-06 15:56:28
*名称: ax-scrollnav.css
*简介: scrollnav的css文件
*用法: scrollnav.init('#id',{参数})
*版本: v3.0.2
*演示: https://www.axui.cn/v2.0/ax-scrollnav.php
*客服: 3217728223@qq.com
*交流: QQ群952502085
*作者: AXUI团队
*/
@charset "utf-8";
@import (optional, reference) "../../../css/ax-fun.less";
.ax-scrollnav {}
.ax-scrollnav-v {
font-size: 1.2rem;
background-color: rgba(255, 255, 255, .1);
padding: @gutter-md;
line-height: @lineheight-body;
max-height: calc(100vh - 12.0rem);
overflow: inherit;
position: fixed;
top: 6.0rem;
right: @gutter-md;
z-index: 610;
}
.ax-scrollnav-v .ax-close {
color: @color-primary;
width: @height-input;
height: @height-input;
line-height: @height-input;
text-align: center;
border-radius: @height-input;
border: 1px solid @color-border;
background-color: rgba(255, 255, 255, 0.9);
box-sizing: border-box;
.tranNormal();
position: absolute;
right: 0;
bottom: calc(-@height-input - @break-md);
}
.ax-scrollnav-v.ax-hide {
border-color: transparent;
background: transparent;
padding-left: 0;
padding-right: 0;
}
.ax-scrollnav-v.ax-hide .ax-scrollnav {
width: 0;
visibility: hidden;
}
.ax-scrollnav-v.ax-hide .ax-close {
color: #fff;
border-width: 0;
background-color: @color-primary;
transform: rotate(180deg);
}
.ax-scrollnav-v:not(.ax-hide) .ax-close:hover {
border-color: @color-primary;
background-color: @color-primary-bg;
}
.ax-scrollnav-v ol {}
.ax-scrollnav-v li {
position: relative;
padding-left: @gutter-md;
white-space: nowrap;
border-left: 1px solid @color-ignbg;
}
.ax-scrollnav-v li.ax-active>a {
color: @color-primary;
}
.ax-scrollnav-v li:before {
content: '';
height: @lineheight-body;
width: 1px;
position: absolute;
left: -0.1rem;
top: 0;
}
.ax-scrollnav-v li.ax-active:before {
background-color: @color-primary;
}
.ax-scrollnav-h {
background-color: #fff;
line-height: @height-input;
text-align: center;
position: relative;
z-index: 4;
}
.ax-scrollnav-h ol {}
.ax-scrollnav-h li {
margin: 0 @gutter-md;
white-space: nowrap;
display: inline-block;
position: relative;
}
.ax-scrollnav-h li.ax-active>a {
color: @color-primary;
}
.ax-scrollnav-h li:before {
content: '';
height: .2rem;
width: 100%;
.tranNormal();
position: absolute;
bottom: 0;
}
.ax-scrollnav-h li.ax-active:before {
background-color: @color-primary;
}
/*Telephone & iPad*/
@media screen and (max-width: 900px) {
.ax-scrollnav-v {
background-color: rgba(255, 255, 255, 0.9);
.border-outer();
border-radius: @radius;
top: auto;
bottom: @gutter-md;
}
.ax-scrollnav-v .ax-close {
top: calc(-@height-input - @gutter-md);
bottom: auto;
}
}

View File

@@ -0,0 +1,255 @@
/*!
* 插件scrollnav使用方法scrollnav.init('#id',{参数})
* AXUI改版
* 1、插件中的样式均增加ax-前缀样式中的下划线_均替换为了短横线-。
* 2、支持两级锚点菜单分别是h2和h3。
* 3、修改了默认参数insertLocation为append。
*/
//对ax-scrollnav-v执行插件
const V_SCROLLNAV = document.querySelectorAll('.ax-scrollnav-v');
for (let i = 0; i < V_SCROLLNAV.length; i++) {
let _this = V_SCROLLNAV[i],
close = _this.querySelector('.ax-close');
if (close) {
close.addEventListener('click', () => {
if (_this.classList.contains('ax-hide')) {
_this.classList.remove('ax-hide');
axCookie.set('scrollnav', 'show');
} else {
_this.classList.add('ax-hide');
axCookie.set('scrollnav', 'hide');
}
}, false);
}
if (axCookie.get("scrollnav") === 'hide') {
_this.classList.add("ax-hide");
} else {
_this.classList.remove("ax-hide");
}
}
//
!function(f, h) {
"object" == typeof exports && "undefined" != typeof module ? module.exports = h() : "function" == typeof define && define.amd ? define(h) : f.scrollnav = h()
} (this,
function() {
function f(f, h) {
var y, w = {};
for (y in f) Object.prototype.hasOwnProperty.call(f, y) && (w[y] = f[y]);
for (y in h) Object.prototype.hasOwnProperty.call(h, y) && (w[y] = h[y]);
return w
}
function h(f, h) {
if ("object" != typeof f) return Promise.reject(new Error("First argument must be an object"));
if ("object" != typeof(h = h || document.body)) return Promise.reject(new Error("Second argument must be an object"));
var y = h.getBoundingClientRect();
return f.getBoundingClientRect().top - y.top
}
function y(f, w, E) {
void 0 === E && (E = "ax-scrollnav");
var L = [];
return E += "-",
f.forEach(function(f, O) {
var x = [],
j = function(f, h) {
if ("object" != typeof f) return Promise.reject(new Error("First argument must be an object"));
var y = f.id;
if (!y) {
if ("string" != typeof h) return Promise.reject(new Error("Second argument must be a string"));
f.id = y = h
}
return y
} (f, E + (O + 1));
w.subSections && f.matches(w.sections) && (x = y(function(f, h, y) {
var w = [];
for (f = f.nextElementSibling; f && !f.matches(h);) ! y || f.matches(y) ? (w.push(f), f = f.nextElementSibling) : f = f.nextElementSibling;
return w
} (f, w.sections, w.subSections), w, j));
L.push({
id: j,
text: f.innerText || f.textContent,
offsetTop: h(f),
subSections: x
})
}),
L
}
function w(f) {
var h = document.createElement("div");//axui
return h.className = "ax-scrollnav",//axui
h.innerHTML = function f(h, y) {
void 0 === y && (y = !1);
var w = "ax-scrollnav" + (y ? "-sub-": "-"),
E = "\n " + h.map(function(h) {
return '<li class="' + w + 'item" data-section="' + h.id + '">\n <a class="' + w + 'link" href="#' + h.id + '">' + h.text + "</a>\n " + (h.subSections && h.subSections.length ? "" + f(h.subSections, !0) : "") + "\n </li>"
}).join("") + "\n ";
return '\n <ol class="' + w + 'list">\n ' + E + "\n </ol>\n " ;
} (f),
h
}
function E(f) {
return f.forEach(function(f) {
var y = document.querySelector("#" + f.id);
f.offsetTop = h(y),
f.subSections.length && (f.subSections = E(f.subSections))
}),
f
}
function L(f, h) {
var y = f.getAttribute("href");
return "#" === y.charAt(0) && (y = y.substr(1)),
function f(h, y) {
var w;
h.forEach(function(h) {
h.id === y && (w = h),
h.subSections && void 0 === w && (w = f(h.subSections, y))
});
return w
} (h, y).offsetTop
}
var O, x, j, _ = function(f) {
return function(h) {
return Math.pow(h, f)
}
},
I = function(f) {
return function(h) {
return 1 - Math.abs(Math.pow(h - 1, f))
}
},
Q = function(f) {
return function(h) {
return h < .5 ? _(f)(2 * h) / 2 : I(f)(2 * h - 1) / 2 + .5
}
},
C = {
linear: Q(1),
easeInQuad: _(2),
easeOutQuad: I(2),
easeInOutQuad: Q(2),
easeInCubic: _(3),
easeOutCubic: I(3),
easeInOutCubic: Q(3),
easeInQuart: _(4),
easeOutQuart: I(4),
easeInOutQuart: Q(4),
easeInQuint: _(5),
easeOutQuint: I(5),
easeInOutQuint: Q(5)
};
function M(f, h) {
return new Promise(function(y, w) {
if ("number" != typeof f) return w(new Error("First argument must be a number"));
if ("string" != typeof(h = h || "linear")) return w(new Error("Second argument must be a string"));
var E, L = window.pageYOffset,
O = f - L,
x = function(f) {
var h = Math.abs(f / 2);
return Math.min(Math.max(h, 250), 1200)
} (O),
j = 20,
_ = 0; !
function f() {
E = C[h]((_ += j) / x),
window.scroll(0, E * O + L),
_ < x ? setTimeout(f, j) : y(window.pageYOffset)
} ()
})
}
function q(f) {
function h() {
var h = window.scrollY || window.pageYOffset || document.body.scrollTop,
y = h + .4 * window.innerHeight,
w = function f(h, y, w) {
var E, L;
h.forEach(function(f) {
f.offsetTop > w ? !E && f.offsetTop < y && (E = f) : E = f
}),
E && E.subSections.length && (L = f(E.subSections, y, w)) && (E = L);
return E
} (f.data, h, y);
return function(f, h) {
var y = h.querySelector("[data-active]");
if (f) {
var w = h.querySelector("[data-section=" + f.id + "]");
w && w !== y && (y && (y.classList.remove("ax-active"), y.removeAttribute("data-active")), w.classList.add("ax-active"), w.setAttribute("data-active", !0))
} else y && (y.classList.remove("ax-active"), y.removeAttribute("data-active"))
} (w, f.nav),
w
}
return window.addEventListener("scroll", h),
h
}
function B(f) {
return f instanceof Element
}
return {
init: function(h, _) {
if (this.settings = f({
sections: "h2",
subSections: "h3",//axui
insertTarget: h,
insertLocation: "append",
easingStyle: "easeOutQuad",
updateHistory: !0
},
_), B(h)) if (!this.settings.insertTarget || B(this.settings.insertTarget)) if (["append", "prepend", "after", "before"].includes(this.settings.insertLocation)) {
var I, Q, C, F, R = h.querySelectorAll(this.settings.sections);
if (R.length) return this.data = y(R, this.settings),
this.nav = w(this.data),
Q = (I = this).settings.insertTarget,
"append" === (C = I.settings.insertLocation) ? Q.appendChild(I.nav) : "prepend" === C ? Q.insertBefore(I.nav, Q.firstChild) : "before" === C ? Q.parentNode.insertBefore(I.nav, Q) : "after" === C && Q.parentNode.insertBefore(I.nav, Q.nextSibling),
O = function(f) {
var h = f.settings;
function y(y) {
y.preventDefault();
var w = .39 * window.innerHeight;
return M(L(y.target, f.data) - w, h.easingStyle).then(function() {
h.updateHistory && history.replaceState({},
"", y.target.getAttribute("href")),
h.onScroll && h.onScroll()
})
}
return f.nav.querySelectorAll("a").forEach(function(f) {
f.addEventListener("click", y)
}),
y
} (this),
x = q(this),
j = function(f) {
function h() {
f.data = E(f.data)
}
return window.addEventListener("resize", h),
h
} (this),
this.settings.debug && ((F = document.createElement("div")).className = "snDebugger", F.setAttribute("style", "\n position: fixed;\n top: 40%;\n height: 0px;\n border-bottom:5px solid red;\n border-top: 5px solid blue;\n width: 100%;\n opacity: .5;\n pointer-events: none;\n "), document.body.appendChild(F)),
this.settings.onInit ? this.settings.onInit() : void 0;
this.settings.debug && console.error('\n scrollnav build failed, could not find any "' + this.settings.sections + '"\n elements inside of "' + h + '"\n ')
} else this.settings.debug && console.error('\n scrollnav build failed, options.insertLocation "' + this.settings.insertLocation + '" is not a valid option\n ');
else this.settings.debug && console.error('\n scrollnav build failed, options.insertTarget "' + h + '" is not an HTML Element\n ');
else this.settings.debug && console.error('\n scrollnav build failed, content argument "' + h + '" is not an HTML Element\n ')
},
destroy: function(h) {
if (this.settings = f(this.settings, h),
function(f, h) {
f.querySelectorAll("a").forEach(function(f) {
f.removeEventListener("click", h)
})
} (this.nav, O),
function(f) {
window.removeEventListener("scroll", f)
} (x),
function(f) {
window.removeEventListener("resize", f)
} (j), this.nav.remove(), this.settings.onDestroy) return this.settings.onDestroy()
},
updatePositions: function(h) {
if (this.settings = f(this.settings, h), this.data = E(this.data), this.settings.onUpdatePositions) return this.settings.onUpdatePositions()
}
}
});
//# sourceMappingURL=scrollnav.min.umd.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,182 @@
(function(global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory(global) : typeof define === "function" && define.amd ? define(factory) : factory(global)
}((typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : this), function(global) {
global = global || {};
var _Base64 = global.Base64;
var version = "2.6.3";
var b64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var b64tab = function(bin) {
var t = {};
for (var i = 0, l = bin.length; i < l; i++) {
t[bin.charAt(i)] = i
}
return t
}(b64chars);
var fromCharCode = String.fromCharCode;
var cb_utob = function(c) {
if (c.length < 2) {
var cc = c.charCodeAt(0);
return cc < 128 ? c : cc < 2048 ? (fromCharCode(192 | (cc >>> 6)) + fromCharCode(128 | (cc & 63))) : (fromCharCode(224 | ((cc >>> 12) & 15)) + fromCharCode(128 | ((cc >>> 6) & 63)) + fromCharCode(128 | (cc & 63)))
} else {
var cc = 65536 + (c.charCodeAt(0) - 55296) * 1024 + (c.charCodeAt(1) - 56320);
return (fromCharCode(240 | ((cc >>> 18) & 7)) + fromCharCode(128 | ((cc >>> 12) & 63)) + fromCharCode(128 | ((cc >>> 6) & 63)) + fromCharCode(128 | (cc & 63)))
}
};
var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
var utob = function(u) {
return u.replace(re_utob, cb_utob)
};
var cb_encode = function(ccc) {
var padlen = [0, 2, 1][ccc.length % 3]
, ord = ccc.charCodeAt(0) << 16 | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8) | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0))
, chars = [b64chars.charAt(ord >>> 18), b64chars.charAt((ord >>> 12) & 63), padlen >= 2 ? "=" : b64chars.charAt((ord >>> 6) & 63), padlen >= 1 ? "=" : b64chars.charAt(ord & 63)];
return chars.join("")
};
var btoa = global.btoa && typeof global.btoa == "function" ? function(b) {
return global.btoa(b)
}
: function(b) {
if (b.match(/[^\x00-\xFF]/)) {
throw new RangeError("The string contains invalid characters.")
}
return b.replace(/[\s\S]{1,3}/g, cb_encode)
}
;
var _encode = function(u) {
return btoa(utob(String(u)))
};
var mkUriSafe = function(b64) {
return b64.replace(/[+\/]/g, function(m0) {
return m0 == "+" ? "-" : "_"
}).replace(/=/g, "")
};
var encode = function(u, urisafe) {
return urisafe ? mkUriSafe(_encode(u)) : _encode(u)
};
var encodeURI = function(u) {
return encode(u, true)
};
var fromUint8Array;
if (global.Uint8Array) {
fromUint8Array = function(a, urisafe) {
var b64 = "";
for (var i = 0, l = a.length; i < l; i += 3) {
var a0 = a[i]
, a1 = a[i + 1]
, a2 = a[i + 2];
var ord = a0 << 16 | a1 << 8 | a2;
b64 += b64chars.charAt(ord >>> 18) + b64chars.charAt((ord >>> 12) & 63) + (typeof a1 != "undefined" ? b64chars.charAt((ord >>> 6) & 63) : "=") + (typeof a2 != "undefined" ? b64chars.charAt(ord & 63) : "=")
}
return urisafe ? mkUriSafe(b64) : b64
}
}
var re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;
var cb_btou = function(cccc) {
switch (cccc.length) {
case 4:
var cp = ((7 & cccc.charCodeAt(0)) << 18) | ((63 & cccc.charCodeAt(1)) << 12) | ((63 & cccc.charCodeAt(2)) << 6) | (63 & cccc.charCodeAt(3))
, offset = cp - 65536;
return (fromCharCode((offset >>> 10) + 55296) + fromCharCode((offset & 1023) + 56320));
case 3:
return fromCharCode(((15 & cccc.charCodeAt(0)) << 12) | ((63 & cccc.charCodeAt(1)) << 6) | (63 & cccc.charCodeAt(2)));
default:
return fromCharCode(((31 & cccc.charCodeAt(0)) << 6) | (63 & cccc.charCodeAt(1)))
}
};
var btou = function(b) {
return b.replace(re_btou, cb_btou)
};
var cb_decode = function(cccc) {
var len = cccc.length
, padlen = len % 4
, n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0) | (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0) | (len > 2 ? b64tab[cccc.charAt(2)] << 6 : 0) | (len > 3 ? b64tab[cccc.charAt(3)] : 0)
, chars = [fromCharCode(n >>> 16), fromCharCode((n >>> 8) & 255), fromCharCode(n & 255)];
chars.length -= [0, 0, 2, 1][padlen];
return chars.join("")
};
var _atob = global.atob && typeof global.atob == "function" ? function(a) {
return global.atob(a)
}
: function(a) {
return a.replace(/\S{1,4}/g, cb_decode)
}
;
var atob = function(a) {
return _atob(String(a).replace(/[^A-Za-z0-9\+\/]/g, ""))
};
var _decode = function(a) {
return btou(_atob(a))
};
var _fromURI = function(a) {
return String(a).replace(/[-_]/g, function(m0) {
return m0 == "-" ? "+" : "/"
}).replace(/[^A-Za-z0-9\+\/]/g, "")
};
var decode = function(a) {
return _decode(_fromURI(a))
};
var toUint8Array;
if (global.Uint8Array) {
toUint8Array = function(a) {
return Uint8Array.from(atob(_fromURI(a)), function(c) {
return c.charCodeAt(0)
})
}
}
var noConflict = function() {
var Base64 = global.Base64;
global.Base64 = _Base64;
return Base64
};
global.Base64 = {
VERSION: version,
atob: atob,
btoa: btoa,
fromBase64: decode,
toBase64: encode,
utob: utob,
encode: encode,
encodeURI: encodeURI,
btou: btou,
decode: decode,
noConflict: noConflict,
fromUint8Array: fromUint8Array,
toUint8Array: toUint8Array
};
if (typeof Object.defineProperty === "function") {
var noEnum = function(v) {
return {
value: v,
enumerable: false,
writable: true,
configurable: true
}
};
global.Base64.extendString = function() {
Object.defineProperty(String.prototype, "fromBase64", noEnum(function() {
return decode(this)
}));
Object.defineProperty(String.prototype, "toBase64", noEnum(function(urisafe) {
return encode(this, urisafe)
}));
Object.defineProperty(String.prototype, "toBase64URI", noEnum(function() {
return encode(this, true)
}))
}
}
if (global["Meteor"]) {
Base64 = global.Base64
}
if (typeof module !== "undefined" && module.exports) {
module.exports.Base64 = global.Base64
} else {
if (typeof define === "function" && define.amd) {
define([], function() {
return global.Base64
})
}
}
return {
Base64: global.Base64
}
}));

View File

@@ -0,0 +1,15 @@
class Fmt{
constructor() {
}
/**
* @returns {string}
*/
static ctx(){
const pathName = window.location.pathname.substring(1);
const webName = pathName === '' ? '' : pathName.substring(0, pathName.indexOf('/'));
if(!webName){
return window.location.protocol + '//' + window.location.host;
}
return window.location.protocol + '//' + window.location.host + '/' + webName;
}
}

View File

@@ -0,0 +1,251 @@
/**
* WebSocket封装工具类
* <pre>
* 代码示例:
* let FmtSocket = new FmtSocket(
* {url:'websocket服务器地址',id:'唯一标识',timeout:心跳检测间隔时间(毫秒)}
* );
* //调用初始化方法
* FmtSocket.init((data) => {
* //初始化完成之后的回调函数 ata为监听到的数据
* //可以在这里做接收到消息后的逻辑处理
* console.log(data);
* });
* //调用发送消息方法 message 消息字符串或对象
* FmtSocket.sendMsg(message, () => {
* //发送消息成功之后的回调函数
* });
* </pre>
*/
class FmtSocket {
id;
#options;
#ws;
#entity;
#deepProxyObj;
#proxyMsg;
/**
* 构造函数
* @param {Object} options
*/
constructor(options) {
this.#options = this.#extend({
url: 'http://127.0.0.1/socket/ws',//后台websocket服务地址
id: this.#uuid(),//如果没传此参数创建一个随机的UUID传给后台服务作为标识
timeout: 30000 //心跳检测间隔时间 默认30秒
}, options);
this.id = this.#options.id;
this.#ws = null;
//send:发送类型 HeartBeat:心跳 Logging:消息
this.#entity = {send: null, data: null};
}
/**
* 初始化websocket
* @param {Function} callback (type, data) 回调函数
*/
init(callback){
if(callback && typeof callback === 'function'){
this.#proxyMsg = [];
this.#deepProxyObj = this.#deepProxy(this.#proxyMsg,callback);
}
this.#createWebSocket();
}
/**
* 对象、数组变化监听(增删改)
* @param {Object} obj
* @param {Function} callback
* @return {Object}
*/
#deepProxy(obj, callback){
if (typeof obj === 'object') {
for (let key in obj) {
if (typeof obj[key] === 'object') {
obj[key] = this.#deepProxy(obj[key], callback);
}
}
}
return new Proxy(obj, {
/**
* @param {Object, Array} target 设置值的对象
* @param {String} key 属性
* @param {any} value 值
* @param {Object} receiver this
*/
set: (target, key, value, receiver)=> {
if (typeof value === 'object') {
value = this.#deepProxy(value, callback);
}
let cbType = target[key] === undefined ? 'create' : 'modify';
//排除数组修改length回调
if (!(Array.isArray(target) && key === 'length')) {
if (cbType === 'create') {
callback(value);
}
}
return Reflect.set(target, key, value, receiver);
},
deleteProperty(target, key) {
return Reflect.deleteProperty(target, key);
}
});
}
#createWebSocket(){
try {
if ('WebSocket' in window) {
this.#ws = new WebSocket((this.#options.url + "?id=" + this.#options.id)
.replace("http", "ws")
.replace("https", "wss"));
} else {
alert('浏览器不支持WebSocket通讯');
return false;
}
this.#onopen();
this.#onmessage();
this.#onerror();
this.#onclose();
//监听窗口关闭事件当窗口关闭时主动去关闭websocket连接防止连接还没断开就关闭窗口server端会抛异常。
window.onbeforeunload = ()=> {
this.#ws.close();
};
} catch (e) {
console.log("WebSocket:链接失败", e);
alert('WebSocket:链接失败');
}
}
/**
* 关闭websocket链接
* @param {Function} callback
*/
closeWebSocket(callback){
if(this.#ws){
this.#ws.close();
}
if(callback && typeof callback === 'function'){
callback();
}
}
/**
* 发送消息
* @param {String, Object} message
* @param {Function} callback
*/
sendMsg(message, callback){
if(!message || typeof message !== 'string' || typeof message !== 'object'){
alert("FmtSocket sendMsg message is not null or message is not a string or object");
return false;
}
if(callback && typeof callback !== 'function'){
alert("FmtSocket sendMsg callback is not a function");
return false;
}
this.#emptyObjectPropertyValues(this.#entity);
this.#entity.send = 'Message';
this.#entity.data = message;
if (this.#ws.readyState === this.#ws.CONNECTING) {
// 正在开启状态等待1s后重新调用
let socket = this;
setTimeout(function () {
socket.#ws.send(JSON.stringify(socket.#entity));
callback();
}, 1000)
}else{
this.#ws.send(JSON.stringify(this.#entity));
callback();
}
}
#onopen(){
this.#ws.onopen = (event) => {
console.log("WebSocket:链接开启");
}
}
#onmessage(){
this.#ws.onmessage = (event) => {
this.#emptyObjectPropertyValues(this.#entity);
this.#entity = JSON.parse(event.data);
//心跳检测
if(this.#entity.send === 'HeartBeat'){
this.#heartBeat();
}
if(this.#deepProxyObj){
this.#deepProxyObj.splice(0);//赋值前先清空,保证消息数组里只有一条最新的数据
let data = JSON.parse(JSON.stringify(this.#entity));
this.#deepProxyObj.push(data);
}
}
}
#onerror(){
this.#ws.onerror = (event) => {
console.log("WebSocket:发生错误", event);
}
}
#onclose(){
this.#ws.onclose = (event) => {
console.log("WebSocket:链接关闭");
}
}
#heartBeat(){
setTimeout(()=> {
this.#emptyObjectPropertyValues(this.#entity);
if (this.#ws.readyState === this.#ws.CLOSING
|| this.#ws.readyState === this.#ws.CLOSED){
alert("WebSocket通讯服务链接已关闭");
return false;
}
this.#entity.send = 'HeartBeat';
this.#entity.data = '心跳检测';
if (this.#ws.readyState === this.#ws.CONNECTING) {
// 正在开启状态等待1s后重新调用
setTimeout(()=> {
this.#ws.send(JSON.stringify(this.#entity));
}, 1000)
}else{
this.#ws.send(JSON.stringify(this.#entity));
}
},this.#options.timeout);
}
/**
* 扩展source相同属性的值去覆盖target, target如果没有这个属性就新增
* @param {Object} target
* @param {Object} source
* @returns {Object}
*/
#extend(target, source){
if(typeof target !== 'object') return null;
if(typeof source !== 'object') return null;
for (const key in source) {
// 使用for in会遍历数组所有的可枚举属性包括原型。
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
return target;
}
#uuid(len, radix){
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
let uuid = [], i;
radix = radix || chars.length;
if (len) {
// Compact form
for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
} else {
// rfc4122, version 4 form
let r;
// rfc4122 requires these characters
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4';
// Fill in random data. At i==19 set the high bits of clock sequence as
// per rfc4122, sec. 4.1.5
for (i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random() * 16;
uuid[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r];
}
}
}
return uuid.join('');
}
#emptyObjectPropertyValues(person){
Object.keys(person).forEach(key => (person[key] = null));
}
}

View File

@@ -0,0 +1,169 @@
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="https://www.thymeleaf.org">
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="apple-touch-fullscreen" content="yes"/>
<meta name="format-detection" content="email=no" />
<meta name="wap-font-scale" content="no" />
<meta name="viewport" content="user-scalable=no, width=device-width" />
<meta content="telephone=no" name="format-detection" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>文件列表</title>
<link th:href="@{/axui-v2.0.14/css/ax.css}" rel="stylesheet" type="text/css" >
<link th:href="@{/axui-v2.0.14/css/ax-response.css}" rel="stylesheet" type="text/css" >
</head>
<body>
<header class="ax-header">
<div class="ax-row">
<div class="ax-col">
<a th:href="@{/download/index}" class="ax-logo">
<img th:src="@{/common/images/logo.png}" alt="File Management"/>
</a>
</div>
<div class="ax-nav">
<div class="ax-search">
<form name="search">
<label for="keyboard"></label>
<input name="keyboard" id="keyboard" placeholder="关键字..." th:value="${keyboard}" type="text">
<a href="javascript:void(0);" id="search" class="ax-iconfont ax-icon-search"></a>
</form>
</div>
<div class="ax-item ax-selected">
<a th:href="@{/download/index}" class="ax-text">文件列表</a>
<span class="ax-line"></span>
</div>
<div class="ax-item">
<a th:href="@{/upload/index}" class="ax-text">文件上传</a>
<span class="ax-line"></span>
</div>
<div class="ax-item">
<a th:href="@{/logging/index}" class="ax-text">在线日志</a>
<span class="ax-line"></span>
</div>
</div>
</div>
</header>
<div class="ax-space-header"></div>
<div class="ax-border ax-margin ax-radius-md" axCheckAll="checkDom:'#checkBtn',clearDom:'#clearBtn'">
<div th:if="${#lists.isEmpty(files)} eq false" th:each="file,fileStat:${files}">
<label class="ax-checkbox ax-bulletin">
<input name="apple" th:value="${file.filename}" type="checkbox">
<i class="ax-iconfont ax-icon-file" legend></i>
<span class="ax-bulletin-body">
<i caption><span th:text="${file.filename}"></span></i>
</span>
<i count class="ax-margin-right">
<span th:text="${file.filetime}"></span>
</i>
<i count class="ax-margin-right">
<span th:text="${file.filesize}"></span>MB
</i>
<a href="javascript:void(0);" onclick="fileDel(this);"
th:value="${file.filepath}" class="ax-btn ax-sm ax-margin-right">
<span class="ax-iconfont ax-icon-trash-alt"></span>删除
</a>
<a href="javascript:void(0);" onclick="fileDown(this);"
th:name="${file.filename}" th:value="${file.filepath}" class="ax-btn ax-sm">
<span class="ax-iconfont ax-icon-arrow-down-o"></span>下载
</a>
</label>
<hr class="ax-margin-lr"/>
</div>
<div th:if="${#lists.isEmpty(files)} eq true">
<div class="ax-empty">
<div class="ax-icon"><span class="ax-iconfont ax-icon-empty"></span></div>
<div class="ax-title">暂无文件,请去上传!</div>
</div>
</div>
<div class="ax-break"></div>
<a href="###" class="ax-btn ax-margin-left" id="checkBtn">全选</a>
<a href="###" class="ax-btn" id="clearBtn">取消全选</a>
<a href="###" class="ax-btn" id="zipDownBtn">打包下载</a>
<a href="###" class="ax-btn" id="batchDelBtn">批量删除</a>
<div class="ax-break"></div>
</div>
<script th:src="@{/axui-v2.0.14/js/ax.js}" type="text/javascript" charset="utf-8"></script>
<script th:src="@{/common/js/basic.js}" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" th:inline="javascript" charset="utf-8">
let fileDel = (obj) => {
const path = obj.getAttribute("value");
let formData = {path: path};
axAjax({
url: '/fmt/download/delete',
data: formData,
type: 'post',
success: function (result) {
window.location.href = '/fmt/download/index';
}
});
}
let fileDown = (obj) => {
const path = obj.getAttribute("value");
window.open(Fmt.ctx() + '/download/execute?path=' + encodeURIComponent(path) + '&temp=' + false);
};
window.onload = () => {
document.getElementById("search").onclick = () => {
const keyboard = document.getElementById("keyboard").value;
window.location.href = '/fmt/download/index?keyboard=' + keyboard;
}
document.getElementById("zipDownBtn").onclick = () => {
const list = document.getElementsByName("apple");
const filenames = [];
for (let key in list) {
if(list[key].checked){
const filename = list[key].getAttribute("value");
filenames.push(filename);
}
}
if(filenames.length === 0){
new axMessage({content: '请选择要下载的文件',result: 'warning',iconShow: true}).show();
return false;
}
let formData = {filenames: filenames.join(",")};
let message = new axMessage({content: '',result: 'success',iconShow: true});
message.update({content: '正在根据所选文件创建压缩包......', result: 'success'}).show();
axAjax({
url: '/fmt/download/packZip',
data: formData,
type: 'post',
success: function (result) {
const data = result.content;
message.update({content: '压缩包' + data.filename + "创建完成,准备下载文件......", result: 'success'}).show();
window.open(Fmt.ctx() + '/download/execute?path=' + encodeURIComponent(data.path) + '&temp=' + true);
}
});
}
document.getElementById("batchDelBtn").onclick = () => {
const list = document.getElementsByName("apple");
const filenames = [];
for (let key in list) {
if(list[key].checked){
const filename = list[key].getAttribute("value");
filenames.push(filename);
}
}
if(filenames.length === 0){
new axMessage({content: '请选择要删除的文件',result: 'warning',iconShow: true}).show();
return false;
}
let formData = {filenames: filenames.join(",")};
axAjax({
url: '/fmt/download/batchDel',
data: formData,
type: 'post',
success: function (result) {
window.location.href = '/fmt/download/index';
}
});
}
}
</script>
</body>
</html>

View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="https://www.thymeleaf.org">
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="apple-touch-fullscreen" content="yes"/>
<meta name="format-detection" content="email=no" />
<meta name="wap-font-scale" content="no" />
<meta name="viewport" content="user-scalable=no, width=device-width" />
<meta content="telephone=no" name="format-detection" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>在线日志</title>
<link th:href="@{/axui-v2.0.14/css/ax.css}" rel="stylesheet" type="text/css" >
<link th:href="@{/axui-v2.0.14/css/ax-response.css}" rel="stylesheet" type="text/css" >
</head>
<body>
<header class="ax-header">
<div class="ax-row">
<div class="ax-col">
<a th:href="@{/download/index}" class="ax-logo">
<img th:src="@{/common/images/logo.png}" alt="File Management"/>
</a>
</div>
<div class="ax-nav">
<div class="ax-item">
<a th:href="@{/download/index}" class="ax-text">文件列表</a>
<span class="ax-line"></span>
</div>
<div class="ax-item">
<a th:href="@{/upload/index}" class="ax-text">文件上传</a>
<span class="ax-line"></span>
</div>
<div class="ax-item ax-selected">
<a th:href="@{/logging/index}" class="ax-text">在线日志</a>
<span class="ax-line"></span>
</div>
</div>
</div>
</header>
<div class="ax-space-header"></div>
<div id="RootDiv" class="ax-border ax-margin">
</div>
<script th:src="@{/axui-v2.0.14/js/ax.js}" type="text/javascript" charset="utf-8"></script>
<script th:src="@{/common/js/basic.js}" type="text/javascript" charset="utf-8"></script>
<script th:src="@{/common/js/fmt-socket.js}" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" th:inline="javascript" charset="utf-8">
window.onload = () => {
const socket = new FmtSocket({url: Fmt.ctx() + '/socket/ws'});
socket.init((data) => {
if (data.send === 'Logging') {
const log = data.data;
const logDiv = document.createElement('div');
logDiv.innerHTML = '<pre><strong>' + log + '</strong></pre>';
document.querySelector('#RootDiv').appendChild(logDiv);
}
});
}
</script>
</body>
</html>

View File

@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="https://www.thymeleaf.org">
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="apple-touch-fullscreen" content="yes"/>
<meta name="format-detection" content="email=no" />
<meta name="wap-font-scale" content="no" />
<meta name="viewport" content="user-scalable=no, width=device-width" />
<meta content="telephone=no" name="format-detection" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>文件上传</title>
<link th:href="@{/axui-v2.0.14/css/ax.css}" rel="stylesheet" type="text/css" >
<link th:href="@{/axui-v2.0.14/css/ax-response.css}" rel="stylesheet" type="text/css" >
</head>
<body>
<header class="ax-header">
<div class="ax-row">
<div class="ax-col">
<a th:href="@{/download/index}" class="ax-logo">
<img th:src="@{/common/images/logo.png}" alt="File Management"/>
</a>
</div>
<div class="ax-nav">
<div class="ax-item">
<a th:href="@{/download/index}" class="ax-text">文件列表</a>
<span class="ax-line"></span>
</div>
<div class="ax-item ax-selected">
<a th:href="@{/upload/index}" class="ax-text">文件上传</a>
<span class="ax-line"></span>
</div>
<div class="ax-item">
<a th:href="@{/logging/index}" class="ax-text">在线日志</a>
<span class="ax-line"></span>
</div>
</div>
</div>
</header>
<div class="ax-space-header"></div>
<div>
<div class="ax-form-group">
<div class="ax-flex-row">
<div class="ax-col">
<input type="hidden" multiple id="upload"/>
</div>
</div>
</div>
</div>
<script th:src="@{/axui-v2.0.14/js/ax.js}" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
window.onload = () => {
let accept = "jpg,jpeg,gif,png,svg,doc,docx,xls,xlsx,txt,mp4,mp3,pdf,exe,msi,jar,zip," +
"rar,tar,gz,conf,sql,sh,bat,log,out,ico,rpm,deb,dmg,avi,m3u8,ts";
let upload = new axUpload('#upload', {
type: 'gallery',
url: 'execute',
action: 'manual',
clearBtn: { show: true },
uploadBtn: { show: true },
max: 0,
size: 0,
summaryShow: true,
accept: accept
});
}
</script>
</body>
</html>