feat: 初始化静态镜像站点仓库

This commit is contained in:
2026-04-08 21:44:32 +08:00
commit 9f9dba6289
2514 changed files with 727963 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
{
"language": "zh",
"PToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjQ0IiwiaWF0IjoxNzc1MDQ4NjM4LCJleHAiOjE3NzU2NTM0Mzh9.VPrOYhyqsNwSi7kU34lB4_SWG74PXaFIt4Wk_0hqTMU"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

View File

@@ -0,0 +1,44 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>项目运营平台 - 运行态镜像</title>
<style>
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", sans-serif;
background: #0b1220;
color: #eef4ff;
}
#mirror-loading {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 12px;
letter-spacing: 0.02em;
}
#mirror-loading small {
color: #98a7c2;
}
</style>
</head>
<body>
<div id="mirror-loading">
<div>正在启动项目运营平台运行态镜像…</div>
<small>会预置本地存储并接管接口请求</small>
</div>
<div id="app"></div>
<script>
(function () {
var script = document.createElement("script");
script.src = "./runtime-bootstrap.js" + (location.search || "");
document.body.appendChild(script);
})();
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

File diff suppressed because it is too large Load Diff

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,308 @@
const CAPTURE_FILES = [
"/__mirror/captures/hc-pos-dashboard-apis.json",
"/__mirror/captures/hc-pos-basicsInfo-apis.json"
];
let fixturesPromise = null;
let storageSeedPromise = null;
self.addEventListener("install", (event) => {
self.skipWaiting();
event.waitUntil(loadFixtures());
});
self.addEventListener("activate", (event) => {
event.waitUntil(self.clients.claim());
});
self.addEventListener("fetch", (event) => {
const requestUrl = new URL(event.request.url);
if (!requestUrl.hostname.includes("app-project-be.sqygj.cn")) {
return;
}
event.respondWith(handleApiRequest(event.request));
});
async function loadFixtures() {
if (fixturesPromise) {
return fixturesPromise;
}
fixturesPromise = (async () => {
const fixtureMap = new Map();
for (const file of CAPTURE_FILES) {
const response = await fetch(file, { cache: "no-store" });
if (!response.ok) {
continue;
}
const items = await response.json();
items
.filter((item) => item.resource_type === "XHR")
.forEach((item) => {
fixtureMap.set(item.url, item);
});
}
return fixtureMap;
})();
return fixturesPromise;
}
async function loadStorageSeed() {
if (storageSeedPromise) {
return storageSeedPromise;
}
storageSeedPromise = (async () => {
const response = await fetch("./storage-seed.json", { cache: "no-store" });
if (!response.ok) {
return {};
}
return response.json();
})();
return storageSeedPromise;
}
async function handleApiRequest(request) {
const fixtures = await loadFixtures();
if (request.method === "OPTIONS") {
return new Response("", {
status: 200,
headers: corsHeaders("text/plain;charset=utf-8")
});
}
const fixture = fixtures.get(request.url);
if (fixture) {
return new Response(fixture.body || "", {
status: fixture.status || 200,
headers: corsHeaders(fixture.mime_type || "application/json;charset=utf-8")
});
}
const mockResponse = await buildMockResponse(request);
return new Response(JSON.stringify(mockResponse), {
status: 200,
headers: corsHeaders("application/json;charset=utf-8")
});
}
function corsHeaders(contentType) {
return {
"Content-Type": contentType,
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,POST,PUT,PATCH,DELETE,OPTIONS",
"Access-Control-Allow-Headers": "*"
};
}
function ok(data) {
return {
data,
code: 0,
message: "mock success.",
ok: true
};
}
function paged(records = []) {
return ok({
rowsCount: records.length,
pageNumber: 1,
pageSize: 10,
pageCount: records.length ? 1 : 0,
records
});
}
function basicStats() {
return ok({
total: 0,
num: 0,
count: 0,
value: 0,
amount: 0,
ratio: 0,
rate: 0
});
}
async function buildMockResponse(request) {
const url = new URL(request.url);
const path = url.pathname;
const seed = await loadStorageSeed();
const targetInfo = parseTargetInfo(seed);
const currentProject = parseCurrentProject(seed);
if (path.endsWith("/appproject/account/findProjectByRoleId")) {
return ok(targetInfo.projectList || []);
}
if (path.endsWith("/appproject/account/findByAccount")) {
return ok(targetInfo.accountProfile || {});
}
if (path.endsWith("/appproject/project/findByCode")) {
return ok(mockProjectDetail(currentProject));
}
if (path.endsWith("/appproject/account/findByCompanyId")) {
return ok((targetInfo.projectList || []).filter((item) => item.companyId === currentProject.companyId));
}
if (path.endsWith("/appproject/data/project/serviceCount")) {
return ok({
countryCount: null,
provinceCount: 1,
cityCount: 1,
areaCount: 1,
streetCount: 1,
companyCount: 1,
projectCount: 1,
manageArea: 13848,
contractArea: 41980.48,
serviceArea: 78000,
payArea: 3440.51,
totalHouse: 38,
totalHouseMember: 65,
totalUser: 120,
ownerUser: 25,
status0Count: 0,
status1Count: 0,
status2Count: 0,
status3Count: 1,
status4Count: 10,
status5Count: 0
});
}
if (path.endsWith("/appproject/PlatformMessage/noticePageList")) {
return paged([
{
id: 1,
title: "本地镜像通知",
content: "这是本地 mock 数据,用于运行态镜像演示。",
createTime: "2026-04-01 22:00:00"
}
]);
}
if (path.endsWith("/appproject/OperationalGuidance/pageList")) {
return paged([
{ id: 1, title: "系统配置(项目平台)合集", tag: "项目平台" },
{ id: 2, title: "满意度(公告+问卷+周检)", tag: "满意度" },
{ id: 3, title: "工程管理—计划工单", tag: "工单" }
]);
}
if (path.endsWith("/appproject/AgentConfig/getAgentUrl")) {
return ok("https://example.com/mock-agent");
}
if (path.endsWith("/appproject/WorkOrder/findByProjectUuidAndAccountUuid")) {
return ok([
{ id: 1, status: 1, title: "巡检工单", createTime: "2026-04-01 10:00:00" },
{ id: 2, status: 2, title: "报修工单", createTime: "2026-04-01 11:30:00" }
]);
}
if (/\/check[A-Z]/.test(path) || /\/check[a-zA-Z]/.test(path) || path.includes("/checkTips")) {
return ok(false);
}
if (path.includes("/pageList")) {
return paged([]);
}
if (path.includes("/treeList") || path.includes("/getList") || path.endsWith("/list")) {
return ok([]);
}
if (
path.includes("/create") ||
path.includes("/update") ||
path.includes("/delete") ||
path.includes("/save") ||
path.includes("/edit") ||
path.includes("/bind") ||
path.includes("/sync")
) {
return ok(true);
}
if (
path.includes("/total") ||
path.includes("/statistics") ||
path.includes("/report") ||
path.includes("/chart") ||
path.includes("/count")
) {
return basicStats();
}
if (path.includes("/findById") || path.includes("/detail") || path.includes("/findBy")) {
return ok({});
}
return ok({});
}
function parseTargetInfo(seed) {
try {
const raw = JSON.parse(seed.C_userInfo || "{}");
const targetInfo = JSON.parse(raw.targetInfo || "{}");
return {
accountProfile: targetInfo,
projectList: targetInfo.projectList || [],
menuTree: targetInfo.menuSelectAllResponseByProject || []
};
} catch (_error) {
return {};
}
}
function parseCurrentProject(seed) {
try {
return JSON.parse(seed.store || "{}");
} catch (_error) {
return {};
}
}
function mockProjectDetail(project) {
return {
id: project.id || 426,
code: project.community_uuid || "mock-project-code",
name: project.community_name || "循环花园一期",
nickname: "箭楼下社区",
developer: "腾龙开发商",
floorage: 41980.48,
greeningArea: 78000,
manageArea: 13848,
payArea: 3440.51,
houseCount: 38,
houseMemberCount: 65,
province: "湖北省",
city: "黄石市",
area: "下陆区",
street: "团城山街道",
longitude: "119.919847",
latitude: "31.016537",
architectureType: "高层",
deliverDate: "2010-07-01",
architectureDate: "2008-07-01",
layout: "一室一厅",
address: "下陆区团城山街道龙湾一品小区",
image: "https://sqy-oss-test.oss-cn-guangzhou.aliyuncs.com/20220320/1647777882795_f65e03a8.jpg",
signature: "https://sqy-oss-test.oss-cn-guangzhou.aliyuncs.com/20230414/1681480367954_5c56e2c5.png",
companyId: project.companyId || 421,
companyUuid: project.companyUuid || "92115dc9-09a2-42da-b9bb-60352c900a53",
codeNumber: project.codeNumber || "X39839",
star: project.star || 5,
payMethod: 2,
manageType: 7
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

File diff suppressed because one or more lines are too long