feat: 初始化静态镜像站点仓库
This commit is contained in:
4
__mirror/runtime/hc-pos-dashboard/cookie-seed.json
Normal file
4
__mirror/runtime/hc-pos-dashboard/cookie-seed.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"language": "zh",
|
||||
"PToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjQ0IiwiaWF0IjoxNzc1MDQ4NjM4LCJleHAiOjE3NzU2NTM0Mzh9.VPrOYhyqsNwSi7kU34lB4_SWG74PXaFIt4Wk_0hqTMU"
|
||||
}
|
||||
BIN
__mirror/runtime/hc-pos-dashboard/current-fallback.png
Normal file
BIN
__mirror/runtime/hc-pos-dashboard/current-fallback.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 316 KiB |
44
__mirror/runtime/hc-pos-dashboard/index.html
Normal file
44
__mirror/runtime/hc-pos-dashboard/index.html
Normal 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>
|
||||
BIN
__mirror/runtime/hc-pos-dashboard/party-v2.png
Normal file
BIN
__mirror/runtime/hc-pos-dashboard/party-v2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 186 KiB |
BIN
__mirror/runtime/hc-pos-dashboard/party-v3.png
Normal file
BIN
__mirror/runtime/hc-pos-dashboard/party-v3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 183 KiB |
1038
__mirror/runtime/hc-pos-dashboard/route-map.json
Normal file
1038
__mirror/runtime/hc-pos-dashboard/route-map.json
Normal file
File diff suppressed because it is too large
Load Diff
6922
__mirror/runtime/hc-pos-dashboard/runtime-bootstrap.js
Normal file
6922
__mirror/runtime/hc-pos-dashboard/runtime-bootstrap.js
Normal file
File diff suppressed because it is too large
Load Diff
5
__mirror/runtime/hc-pos-dashboard/storage-seed.json
Normal file
5
__mirror/runtime/hc-pos-dashboard/storage-seed.json
Normal file
File diff suppressed because one or more lines are too long
308
__mirror/runtime/hc-pos-dashboard/sw.js
Normal file
308
__mirror/runtime/hc-pos-dashboard/sw.js
Normal 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
|
||||
};
|
||||
}
|
||||
BIN
__mirror/runtime/hc-pos-dashboard/topbar-hcpos-latest.png
Normal file
BIN
__mirror/runtime/hc-pos-dashboard/topbar-hcpos-latest.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 182 KiB |
1
__mirror/runtime/hc-pos-dashboard/webpack-runtime.js
Normal file
1
__mirror/runtime/hc-pos-dashboard/webpack-runtime.js
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user