new
This commit is contained in:
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/icons/icon-192x192.png
Normal file
BIN
public/icons/icon-192x192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
BIN
public/icons/icon-512x512.png
Normal file
BIN
public/icons/icon-512x512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
1
public/logo.svg
Normal file
1
public/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1766318220539" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7296" width="200" height="200" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M581.818182 572.509091m-328.610909 0a328.610909 328.610909 0 1 0 657.221818 0 328.610909 328.610909 0 1 0-657.221818 0Z" fill="#FB8339" p-id="7297"></path><path d="M899.258182 470.109091c19.549091 0 35.374545-15.825455 35.374545-35.374546V158.254545c0-15.825455-11.170909-29.789091-26.996363-33.512727-1.861818-0.930909-3.723636-1.861818-6.516364-2.792727l-380.741818-83.781818c-3.723636-0.930909-6.516364-0.930909-9.309091 0h-13.032727l-374.225455 83.781818c-2.792727 0.930909-4.654545 1.861818-6.516364 2.792727-15.825455 3.723636-26.996364 17.687273-26.996363 33.512727v393.774546c0 2.792727 0.930909 4.654545 0.930909 5.585454 11.170909 243.898182 216.901818 400.290909 415.185454 429.149091h10.24c177.803636-25.134545 383.534545-159.185455 413.323637-391.912727 2.792727-19.549091-11.170909-37.236364-30.72-39.098182-9.309091-0.930909-18.618182 0.930909-26.065455 7.447273S861.090909 577.163636 860.16 586.472727c-25.134545 194.56-197.352727 307.2-349.090909 330.472728-175.010909-26.996364-351.883636-165.701818-351.883636-378.88V185.250909l349.090909-78.196364 354.676363 78.196364v249.483636c0.930909 19.549091 16.756364 35.374545 36.305455 35.374546z" p-id="7298"></path><path d="M692.596364 413.323636c-5.585455-81.92-57.716364-124.741818-156.392728-127.534545H336.058182V716.8h80.989091V545.512727h80.058182L623.709091 715.869091h104.261818L585.541818 538.065455c70.749091-13.032727 107.054545-54.923636 107.054546-124.741819zM417.047273 353.745455h105.192727c76.334545 0 84.712727 34.443636 84.712727 61.44 0.930909 17.687273-3.723636 30.72-13.032727 40.02909-13.032727 13.963636-37.236364 20.48-71.68 20.48H417.047273V353.745455z" p-id="7299"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
18
public/manifest.json
Normal file
18
public/manifest.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "RiskGuard",
|
||||
"short_name": "RiskGuard",
|
||||
"display": "standalone",
|
||||
"start_url": "./?utm_source=homescreen",
|
||||
"theme_color": "#002140",
|
||||
"background_color": "#001529",
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/icon-192x192.png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "icons/icon-512x512.png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
public/pdf/en_US/Lark_push_configuration.pdf
Normal file
BIN
public/pdf/en_US/Lark_push_configuration.pdf
Normal file
Binary file not shown.
BIN
public/pdf/en_US/Slack_push_configuration.pdf
Normal file
BIN
public/pdf/en_US/Slack_push_configuration.pdf
Normal file
Binary file not shown.
BIN
public/pdf/en_US/Teams_push_configuration.pdf
Normal file
BIN
public/pdf/en_US/Teams_push_configuration.pdf
Normal file
Binary file not shown.
BIN
public/pdf/en_US/Telegram_push_configuration.pdf
Normal file
BIN
public/pdf/en_US/Telegram_push_configuration.pdf
Normal file
Binary file not shown.
BIN
public/pdf/zh_CN/Lark_push_configuration.pdf
Normal file
BIN
public/pdf/zh_CN/Lark_push_configuration.pdf
Normal file
Binary file not shown.
BIN
public/pdf/zh_CN/Slack_push_configuration.pdf
Normal file
BIN
public/pdf/zh_CN/Slack_push_configuration.pdf
Normal file
Binary file not shown.
BIN
public/pdf/zh_CN/Teams_push_configuration.pdf
Normal file
BIN
public/pdf/zh_CN/Teams_push_configuration.pdf
Normal file
Binary file not shown.
BIN
public/pdf/zh_CN/Telegram_push_configuration.pdf
Normal file
BIN
public/pdf/zh_CN/Telegram_push_configuration.pdf
Normal file
Binary file not shown.
208
public/scripts/loading.js
Normal file
208
public/scripts/loading.js
Normal file
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* loading placeholder
|
||||
* Solve the problem that the white background will be displayed first when refreshing the page under the dark theme
|
||||
*/
|
||||
(function () {
|
||||
const _root = document.querySelector('#root');
|
||||
const theme = localStorage.getItem('navTheme');
|
||||
|
||||
// Solve the problem that the white background will be displayed first when refreshing the page under the dark theme
|
||||
try {
|
||||
const html = document.documentElement;
|
||||
if(theme === 'realDark') {
|
||||
html.dataset.theme = 'dark';
|
||||
}else {
|
||||
html.removeAttribute('data-theme');
|
||||
}
|
||||
} catch (error) {}
|
||||
|
||||
if (_root && _root.innerHTML === '') {
|
||||
_root.innerHTML = `
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#root {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
}
|
||||
|
||||
.loading-title {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.loading-sub-title {
|
||||
margin-top: 20px;
|
||||
font-size: 1rem;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.page-loading-warp {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 26px;
|
||||
}
|
||||
.ant-spin {
|
||||
position: absolute;
|
||||
display: none;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
color: #1890ff;
|
||||
font-size: 14px;
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
list-style: none;
|
||||
opacity: 0;
|
||||
-webkit-transition: -webkit-transform 0.3s
|
||||
cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||
transition: -webkit-transform 0.3s
|
||||
cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||
transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||
transition: transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86),
|
||||
-webkit-transform 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||
-webkit-font-feature-settings: "tnum";
|
||||
font-feature-settings: "tnum";
|
||||
}
|
||||
|
||||
.ant-spin-spinning {
|
||||
position: static;
|
||||
display: inline-block;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.ant-spin-dot {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.ant-spin-dot-item {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
background-color: #1890ff;
|
||||
border-radius: 100%;
|
||||
-webkit-transform: scale(0.75);
|
||||
-ms-transform: scale(0.75);
|
||||
transform: scale(0.75);
|
||||
-webkit-transform-origin: 50% 50%;
|
||||
-ms-transform-origin: 50% 50%;
|
||||
transform-origin: 50% 50%;
|
||||
opacity: 0.3;
|
||||
-webkit-animation: antspinmove 1s infinite linear alternate;
|
||||
animation: antSpinMove 1s infinite linear alternate;
|
||||
}
|
||||
|
||||
.ant-spin-dot-item:nth-child(1) {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.ant-spin-dot-item:nth-child(2) {
|
||||
top: 0;
|
||||
right: 0;
|
||||
-webkit-animation-delay: 0.4s;
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.ant-spin-dot-item:nth-child(3) {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
-webkit-animation-delay: 0.8s;
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
|
||||
.ant-spin-dot-item:nth-child(4) {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
-webkit-animation-delay: 1.2s;
|
||||
animation-delay: 1.2s;
|
||||
}
|
||||
|
||||
.ant-spin-dot-spin {
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
-webkit-animation: antrotate 1.2s infinite linear;
|
||||
animation: antRotate 1.2s infinite linear;
|
||||
}
|
||||
|
||||
.ant-spin-lg .ant-spin-dot {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.ant-spin-lg .ant-spin-dot i {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
|
||||
.ant-spin-blur {
|
||||
background: #fff;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes antSpinMove {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antSpinMove {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes antRotate {
|
||||
to {
|
||||
-webkit-transform: rotate(405deg);
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes antRotate {
|
||||
to {
|
||||
-webkit-transform: rotate(405deg);
|
||||
transform: rotate(405deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div style="
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
min-height: 362px;
|
||||
">
|
||||
<div class="page-loading-warp">
|
||||
<div class="ant-spin ant-spin-lg ant-spin-spinning">
|
||||
<span class="ant-spin-dot ant-spin-dot-spin">
|
||||
<i class="ant-spin-dot-item"></i>
|
||||
<i class="ant-spin-dot-item"></i>
|
||||
<i class="ant-spin-dot-item"></i>
|
||||
<i class="ant-spin-dot-item"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
})();
|
||||
BIN
public/sounds/notification.mp3
Normal file
BIN
public/sounds/notification.mp3
Normal file
Binary file not shown.
131
public/sw.js
Normal file
131
public/sw.js
Normal file
@@ -0,0 +1,131 @@
|
||||
// Parse the parameters in the current script's own URL
|
||||
const scriptUrl = new URL(self.location);
|
||||
// Get the incoming version, and provide a default value if it doesn't exist
|
||||
const version = scriptUrl.searchParams.get("v") || "default-version";
|
||||
|
||||
// Dynamically concatenate CACHE_NAME
|
||||
const CACHE_NAME = `risk-guard-cache-${version}`;
|
||||
|
||||
console.log("Current Service Worker CACHE_NAME:", CACHE_NAME);
|
||||
|
||||
// 例如:umi.1a2b3c4d.js, logo.7b3e198f.png
|
||||
const HASH_REGEX =
|
||||
/\.[0-9a-f]{8}\.(js|css|png|jpe?g|gif|webp|svg|ico|woff2?|eot|ttf)$/i;
|
||||
|
||||
// 1. Installation phase: forcibly skip waiting and directly enter the activation state
|
||||
self.addEventListener("install", (event) => {
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
// 2. Activation phase: clean up old caches and immediately take control of the page
|
||||
self.addEventListener("activate", (event) => {
|
||||
event.waitUntil(
|
||||
caches.keys().then((cacheNames) => {
|
||||
return Promise.all(
|
||||
cacheNames.map((cache) => {
|
||||
if (cache !== CACHE_NAME) {
|
||||
console.log("Cleaning old cache:", cache);
|
||||
return caches.delete(cache);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
self.clients.claim(); // Immediately control all open clients (tabs)
|
||||
});
|
||||
|
||||
// 3. Fetch event: this is the key to trigger the installation icon to be displayed
|
||||
self.addEventListener("fetch", (event) => {
|
||||
const { request } = event;
|
||||
const url = new URL(request.url);
|
||||
|
||||
// If not a GET request, skip processing and go straight to the cache
|
||||
if (request.method !== "GET") return;
|
||||
|
||||
// If not an http or https protocol (like chrome-extension), skip processing and go straight to the cache
|
||||
if (!(url.protocol === "http:" || url.protocol === "https:")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore HMR (hot module replacement) and API requests (you can adjust according to your actual API prefix)
|
||||
if (
|
||||
url.pathname.includes("/api/") ||
|
||||
url.pathname.includes("/sockjs-node/")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Handle navigation requests: fetch from network first, then cache if successful
|
||||
if (request.mode === "navigate") {
|
||||
event.respondWith(
|
||||
fetch(request).catch(() => {
|
||||
return caches.match(request);
|
||||
}),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Handle static assets (js, css, images) - cache first
|
||||
const isStaticAsset = url.pathname.match(
|
||||
/\.(js|css|png|jpg|jpeg|svg|gif|woff2?|otf|ttf)$/,
|
||||
);
|
||||
|
||||
const isHashed = HASH_REGEX.test(url.pathname);
|
||||
|
||||
if (isStaticAsset) {
|
||||
if (isHashed) {
|
||||
// ==========================================
|
||||
// Strategy A: Resources with Hash -> Cache First
|
||||
// ==========================================
|
||||
event.respondWith(
|
||||
caches.match(request).then((response) => {
|
||||
// If cache hit, return the cached response immediately
|
||||
if (response) return response;
|
||||
|
||||
// Otherwise, fetch from network first
|
||||
return fetch(request).then((networkResponse) => {
|
||||
if (
|
||||
!networkResponse ||
|
||||
networkResponse.status !== 200 ||
|
||||
(networkResponse.type !== "basic" &&
|
||||
networkResponse.type !== "cors")
|
||||
) {
|
||||
return networkResponse;
|
||||
}
|
||||
|
||||
// Clone the response to allow multiple requests
|
||||
const responseToCache = networkResponse.clone();
|
||||
caches.open(CACHE_NAME).then((cache) => {
|
||||
cache.put(request, responseToCache);
|
||||
});
|
||||
|
||||
return networkResponse;
|
||||
});
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
// ==========================================
|
||||
// Strategy B: Resources without Hash (such as index.html) -> Network First
|
||||
// Ensure that the latest code is always retrieved, only fall back to cache when offline
|
||||
// ==========================================
|
||||
event.respondWith(
|
||||
fetch(request)
|
||||
.then((networkResponse) => {
|
||||
// Network request successful, updating cache
|
||||
if (networkResponse && networkResponse.status === 200) {
|
||||
const responseToCache = networkResponse.clone();
|
||||
caches.open(CACHE_NAME).then((cache) => {
|
||||
cache.put(request, responseToCache);
|
||||
});
|
||||
}
|
||||
return networkResponse;
|
||||
})
|
||||
.catch(() => {
|
||||
// Network request failed (for example, the user disconnected from the Internet), try reading the historical version from the cache
|
||||
console.log("[SW] Network offline, try reading cache:", request.url);
|
||||
return caches.match(request);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user