feat(topology): add square light canvas
Co-Authored-By: OpenAI Codex <codex@openai.com>
This commit is contained in:
@@ -42,17 +42,17 @@
|
|||||||
.wiki-article .topo-connector { color: #8af; font-weight: bold; font-size: 0.85em; text-align: center; padding: 2px 0; }
|
.wiki-article .topo-connector { color: #8af; font-weight: bold; font-size: 0.85em; text-align: center; padding: 2px 0; }
|
||||||
.wiki-article .topo-power-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; text-align: center; margin-top: 8px; }
|
.wiki-article .topo-power-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; text-align: center; margin-top: 8px; }
|
||||||
.wiki-article .topo-power-inner { border: 1px dashed #666; padding: 12px 8px; border-radius: 4px; background: rgba(255,255,255,0.05); margin-top: 12px; }
|
.wiki-article .topo-power-inner { border: 1px dashed #666; padding: 12px 8px; border-radius: 4px; background: rgba(255,255,255,0.05); margin-top: 12px; }
|
||||||
.wiki-article .topology-embed-shell { margin: 1em 0 1.4em; border: 1px solid #6f7f96; border-radius: 8px; overflow: hidden; background: #07111f; box-shadow: 0 2px 10px rgba(0,0,0,0.18); }
|
.wiki-article .topology-embed-shell { margin: 1em 0 1.4em; border: 1px solid #b8c5d4; border-radius: 8px; overflow: hidden; background: #f4f7fb; box-shadow: 0 2px 10px rgba(50,72,96,0.14); }
|
||||||
.wiki-article #topology { scroll-margin-top: 88px; }
|
.wiki-article #topology { scroll-margin-top: 88px; }
|
||||||
.wiki-article .topology-embed-host { min-height: 420px; overflow: hidden; background: #07111f; color: #a8b8cd; }
|
.wiki-article .topology-embed-host { min-height: 420px; overflow: hidden; background: #f4f7fb; color: #5e6f85; }
|
||||||
.wiki-article .topology-embed-frame { display: block; width: 100%; height: 1760px; border: 0; background: #07111f; }
|
.wiki-article .topology-embed-frame { display: block; width: 100%; height: 1450px; border: 0; background: #f4f7fb; }
|
||||||
.wiki-article .topology-embed-fallback { margin: 0; padding: 12px 16px; border-top: 1px solid #31425a; background: #0d1929; color: #d7e3f4; font-size: 0.9em; }
|
.wiki-article .topology-embed-fallback { margin: 0; padding: 12px 16px; border-top: 1px solid #c7d2de; background: #eef3f8; color: #152033; font-size: 0.9em; }
|
||||||
.wiki-article .topology-embed-fallback a { color: #70b7ff; }
|
.wiki-article .topology-embed-fallback a { color: #0645ad; }
|
||||||
@media (min-width: 821px) and (max-width: 1279px) {
|
@media (min-width: 821px) and (max-width: 1279px) {
|
||||||
.wiki-article .topology-embed-frame { width: 125%; height: 2200px; margin-bottom: -440px; transform: scale(0.8); transform-origin: top left; }
|
.wiki-article .topology-embed-frame { width: 125%; height: 1450px; margin-bottom: -290px; transform: scale(0.8); transform-origin: top left; }
|
||||||
}
|
}
|
||||||
@media (min-width: 1280px) and (max-width: 1500px) {
|
@media (min-width: 1280px) and (max-width: 1500px) {
|
||||||
.wiki-article .topology-embed-frame { width: 170%; height: 1700px; margin-bottom: -700px; transform: scale(0.588235); transform-origin: top left; }
|
.wiki-article .topology-embed-frame { width: 170%; height: 1450px; margin-bottom: -597px; transform: scale(0.588235); transform-origin: top left; }
|
||||||
}
|
}
|
||||||
@media (max-width: 820px) { .wiki-article { padding: 18px 16px 36px; } .wiki-article .infobox { float: none; width: 100%; margin: 0.75em 0 1em; } .wiki-article .topology-grid { grid-template-columns: 1fr; } .wiki-article .topo-node.core { grid-column: 1; grid-row: auto; } }
|
@media (max-width: 820px) { .wiki-article { padding: 18px 16px 36px; } .wiki-article .infobox { float: none; width: 100%; margin: 0.75em 0 1em; } .wiki-article .topology-grid { grid-template-columns: 1fr; } .wiki-article .topo-node.core { grid-column: 1; grid-row: auto; } }
|
||||||
|
|
||||||
|
|||||||
@@ -3,20 +3,21 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="icon" href="data:,">
|
||||||
<title>广寒基地拓扑结构</title>
|
<title>广寒基地拓扑结构</title>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
color-scheme: dark;
|
color-scheme: light;
|
||||||
--bg: #070d18; --panel: #0d1728; --panel-2: #101c30;
|
--bg: #f4f7fb; --panel: #ffffff; --panel-2: #eef3f8;
|
||||||
--text: #eaf2ff; --muted: #91a3bd; --border: #263750;
|
--text: #152033; --muted: #5e6f85; --border: #b8c5d4;
|
||||||
--structural: #8fa1b8; --pressurized: #51e89c; --utility: #b178e6;
|
--structural: #66788e; --pressurized: #168a55; --utility: #7a4fb3;
|
||||||
--core: #ffad42; --habitat: #52baff; --power: #d5b642;
|
--core: #c76b00; --habitat: #1677b8; --power: #9b7900;
|
||||||
--vehicle: #c28cdf; --radiator: #f0d869;
|
--vehicle: #8755a4; --radiator: #9b7900;
|
||||||
}
|
}
|
||||||
* { box-sizing: border-box; }
|
* { box-sizing: border-box; }
|
||||||
body {
|
body {
|
||||||
margin: 0; min-height: 100vh; padding: 30px;
|
margin: 0; min-height: 100vh; padding: 30px;
|
||||||
background: radial-gradient(circle at 50% 0%, rgba(51,88,140,0.18), transparent 36rem), var(--bg);
|
background: radial-gradient(circle at 50% 0%, rgba(89,132,181,0.14), transparent 36rem), var(--bg);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-family: "Microsoft YaHei", "PingFang SC", system-ui, sans-serif;
|
font-family: "Microsoft YaHei", "PingFang SC", system-ui, sans-serif;
|
||||||
}
|
}
|
||||||
@@ -27,42 +28,42 @@
|
|||||||
.toolbar { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 12px; margin: 16px 0; }
|
.toolbar { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 12px; margin: 16px 0; }
|
||||||
.toolbar label { color: var(--muted); font-size: 0.88rem; }
|
.toolbar label { color: var(--muted); font-size: 0.88rem; }
|
||||||
.toolbar select, .toolbar input { padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel); color: var(--text); font-size: 0.88rem; }
|
.toolbar select, .toolbar input { padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel); color: var(--text); font-size: 0.88rem; }
|
||||||
.toolbar button { padding: 6px 16px; border: 1px solid var(--pressurized); border-radius: 6px; background: #0a2e16; color: var(--pressurized); cursor: pointer; font-size: 0.88rem; font-weight: 600; }
|
.toolbar button { padding: 6px 16px; border: 1px solid var(--pressurized); border-radius: 6px; background: #e7f7ee; color: #0e6840; cursor: pointer; font-size: 0.88rem; font-weight: 600; }
|
||||||
.toolbar button:hover { background: #0f3d1f; }
|
.toolbar button:hover { background: #d6f0e1; }
|
||||||
.loading-msg { text-align: center; color: var(--muted); padding: 40px; }
|
.loading-msg { text-align: center; color: var(--muted); padding: 40px; }
|
||||||
.error-msg { text-align: center; color: #f66; padding: 40px; }
|
.error-msg { text-align: center; color: #b42318; padding: 40px; }
|
||||||
.legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 13px 24px; margin: 20px 0; padding: 13px 18px; border: 1px solid var(--border); border-radius: 12px; background: rgba(13,23,40,0.84); }
|
.legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 13px 24px; margin: 20px 0; padding: 13px 18px; border: 1px solid var(--border); border-radius: 12px; background: rgba(255,255,255,0.88); }
|
||||||
.legend-item { display: inline-flex; align-items: center; gap: 9px; color: #c8d5e7; font-size: 0.86rem; }
|
.legend-item { display: inline-flex; align-items: center; gap: 9px; color: var(--text); font-size: 0.86rem; }
|
||||||
.legend-line { display: inline-block; width: 46px; border-top: 4px solid; }
|
.legend-line { display: inline-block; width: 46px; border-top: 4px solid; }
|
||||||
.legend-chip { width: 19px; height: 13px; border: 2px solid var(--radiator); background: #665511; border-radius: 3px; }
|
.legend-chip { width: 19px; height: 13px; border: 2px solid var(--radiator); background: #fff0a8; border-radius: 3px; }
|
||||||
.map-shell { overflow: auto; border: 1px solid var(--border); border-radius: 18px; background: #08101e; box-shadow: 0 24px 70px rgba(0,0,0,0.34); }
|
.map-shell { overflow: auto; border: 1px solid var(--border); border-radius: 18px; background: #f8fbff; box-shadow: 0 18px 45px rgba(50,72,96,0.16); }
|
||||||
.topology-map { display: block; width: 100%; min-width: 1080px; height: auto; background: linear-gradient(rgba(18,36,60,0.21) 1px, transparent 1px), linear-gradient(90deg, rgba(18,36,60,0.21) 1px, transparent 1px), #08101e; background-size: 48px 48px; }
|
.topology-map { display: block; width: 100%; min-width: 1080px; height: auto; background: linear-gradient(rgba(78,105,135,0.12) 1px, transparent 1px), linear-gradient(90deg, rgba(78,105,135,0.12) 1px, transparent 1px), #f8fbff; background-size: 48px 48px; }
|
||||||
.connection { fill: none; vector-effect: non-scaling-stroke; stroke-linecap: square; }
|
.connection { fill: none; vector-effect: non-scaling-stroke; stroke-linecap: square; }
|
||||||
.topology-node { cursor: pointer; outline: none; }
|
.topology-node { cursor: pointer; outline: none; }
|
||||||
.topology-node rect { vector-effect: non-scaling-stroke; transition: filter 150ms ease, stroke-width 150ms ease; }
|
.topology-node rect { vector-effect: non-scaling-stroke; transition: filter 150ms ease, stroke-width 150ms ease; }
|
||||||
.topology-node:hover rect, .topology-node:focus-visible rect { filter: brightness(1.25); stroke-width: 5; }
|
.topology-node:hover rect, .topology-node:focus-visible rect { filter: brightness(0.97) drop-shadow(0 6px 8px rgba(45,66,88,0.18)); stroke-width: 5; }
|
||||||
.node-title { fill: var(--text); font-size: 25px; font-weight: 700; text-anchor: middle; }
|
.node-title { fill: var(--text); font-size: 25px; font-weight: 700; text-anchor: middle; }
|
||||||
.node-meta { fill: #a6b5c9; font-size: 17px; text-anchor: middle; }
|
.node-meta { fill: #435a72; font-size: 17px; text-anchor: middle; }
|
||||||
.node-hint { fill: #71849e; font-size: 14px; text-anchor: middle; }
|
.node-hint { fill: #6f8296; font-size: 14px; text-anchor: middle; }
|
||||||
.radiator { pointer-events: none; }
|
.radiator { pointer-events: none; }
|
||||||
.radiator rect { vector-effect: non-scaling-stroke; }
|
.radiator rect { vector-effect: non-scaling-stroke; }
|
||||||
.radiator line { stroke-width: 1.5; vector-effect: non-scaling-stroke; }
|
.radiator line { stroke-width: 1.5; vector-effect: non-scaling-stroke; }
|
||||||
.radiator-label { font-size: 15px; font-weight: 650; text-anchor: middle; }
|
.radiator-label { font-size: 15px; font-weight: 650; text-anchor: middle; }
|
||||||
.click-note { margin: 13px 0 0; color: var(--muted); font-size: 0.84rem; text-align: center; }
|
.click-note { margin: 13px 0 0; color: var(--muted); font-size: 0.84rem; text-align: center; }
|
||||||
body.modal-open { overflow: hidden; }
|
body.modal-open { overflow: hidden; }
|
||||||
.modal-backdrop { position: fixed; inset: 0; z-index: 20; display: none; align-items: center; justify-content: center; padding: 24px; background: rgba(2,7,14,0.82); backdrop-filter: blur(8px); }
|
.modal-backdrop { position: fixed; inset: 0; z-index: 20; display: none; align-items: center; justify-content: center; padding: 24px; background: rgba(21,32,51,0.38); backdrop-filter: blur(8px); }
|
||||||
.modal-backdrop[aria-hidden="false"] { display: flex; }
|
.modal-backdrop[aria-hidden="false"] { display: flex; }
|
||||||
.detail-dialog { position: relative; width: min(760px, 100%); max-height: min(820px, calc(100vh - 48px)); overflow: auto; padding: 30px; border: 1px solid #405572; border-radius: 18px; outline: none; background: linear-gradient(145deg, #13233a, #0b1424 72%); box-shadow: 0 30px 100px rgba(0,0,0,0.64); }
|
.detail-dialog { position: relative; width: min(760px, 100%); max-height: min(820px, calc(100vh - 48px)); overflow: auto; padding: 30px; border: 1px solid #a8b7c8; border-radius: 18px; outline: none; background: linear-gradient(145deg, #ffffff, #f2f6fa 72%); box-shadow: 0 30px 80px rgba(38,55,74,0.28); }
|
||||||
.detail-dialog:focus-visible { box-shadow: 0 0 0 3px var(--pressurized), 0 30px 100px rgba(0,0,0,0.64); }
|
.detail-dialog:focus-visible { box-shadow: 0 0 0 3px var(--pressurized), 0 30px 80px rgba(38,55,74,0.28); }
|
||||||
.modal-close { position: absolute; top: 14px; right: 14px; width: 40px; height: 40px; border: 1px solid #4e627e; border-radius: 50%; background: #182a43; color: var(--text); font: 500 1.65rem/1 system-ui, sans-serif; cursor: pointer; }
|
.modal-close { position: absolute; top: 14px; right: 14px; width: 40px; height: 40px; border: 1px solid #9aabbd; border-radius: 50%; background: #edf2f7; color: var(--text); font: 500 1.65rem/1 system-ui, sans-serif; cursor: pointer; }
|
||||||
.modal-close:hover, .modal-close:focus-visible { border-color: var(--pressurized); outline: none; background: #203754; }
|
.modal-close:hover, .modal-close:focus-visible { border-color: var(--pressurized); outline: none; background: #e2eaf2; }
|
||||||
.detail-kicker { margin: 0 46px 6px 0; color: var(--pressurized); font-size: 0.77rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; }
|
.detail-kicker { margin: 0 46px 6px 0; color: var(--pressurized); font-size: 0.77rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; }
|
||||||
#detail-title { margin: 0 50px 10px 0; font-size: 1.85rem; }
|
#detail-title { margin: 0 50px 10px 0; font-size: 1.85rem; }
|
||||||
#detail-role { margin: 0 0 22px; color: #c4d2e4; line-height: 1.7; }
|
#detail-role { margin: 0 0 22px; color: #42566e; line-height: 1.7; }
|
||||||
.detail-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 0; }
|
.detail-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 0; }
|
||||||
.detail-grid > div { min-width: 0; padding: 14px; border: 1px solid #293c57; border-radius: 10px; background: rgba(8,18,33,0.7); }
|
.detail-grid > div { min-width: 0; padding: 14px; border: 1px solid #c7d2de; border-radius: 10px; background: rgba(247,249,252,0.9); }
|
||||||
.detail-grid dt { margin-bottom: 7px; color: #7f94b1; font-size: 0.75rem; }
|
.detail-grid dt { margin-bottom: 7px; color: #61758c; font-size: 0.75rem; }
|
||||||
.detail-grid dd { margin: 0; color: #e1ebf8; line-height: 1.55; overflow-wrap: anywhere; }
|
.detail-grid dd { margin: 0; color: #1e2d40; line-height: 1.55; overflow-wrap: anywhere; }
|
||||||
.detail-grid dd span { display: block; }
|
.detail-grid dd span { display: block; }
|
||||||
.detail-grid dd span + span { margin-top: 4px; }
|
.detail-grid dd span + span { margin-top: 4px; }
|
||||||
@media (max-width: 760px) {
|
@media (max-width: 760px) {
|
||||||
@@ -96,7 +97,7 @@
|
|||||||
<div id="error-msg" class="error-msg" style="display:none;"></div>
|
<div id="error-msg" class="error-msg" style="display:none;"></div>
|
||||||
|
|
||||||
<div class="map-shell" id="map-shell" style="display:none;">
|
<div class="map-shell" id="map-shell" style="display:none;">
|
||||||
<svg class="topology-map" viewBox="0 0 1500 1900" role="img" aria-labelledby="topology-title" id="topology-svg">
|
<svg class="topology-map" viewBox="0 0 1900 1900" role="img" aria-labelledby="topology-title" id="topology-svg">
|
||||||
<title id="topology-title">广寒基地拓扑</title>
|
<title id="topology-title">广寒基地拓扑</title>
|
||||||
<desc id="topology-desc">根据所选任务或时间展示广寒基地当时的工程拓扑。</desc>
|
<desc id="topology-desc">根据所选任务或时间展示广寒基地当时的工程拓扑。</desc>
|
||||||
<!-- FUTURE_EXPANSION_ANCHOR:north -->
|
<!-- FUTURE_EXPANSION_ANCHOR:north -->
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 111 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 123 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 141 KiB |
@@ -49,6 +49,13 @@ class GuanghanTopologySourceTests(unittest.TestCase):
|
|||||||
self.assertIn("decorationStyles", self.html)
|
self.assertIn("decorationStyles", self.html)
|
||||||
self.assertIn("legendItems", self.html)
|
self.assertIn("legendItems", self.html)
|
||||||
|
|
||||||
|
def test_canvas_is_square_and_page_defaults_to_light(self) -> None:
|
||||||
|
self.assertIn('viewBox="0 0 1900 1900"', self.html)
|
||||||
|
self.assertIn("payload.layout.canvasWidth", self.html)
|
||||||
|
self.assertIn("payload.layout.canvasHeight", self.html)
|
||||||
|
self.assertIn("color-scheme: light", self.html)
|
||||||
|
self.assertNotIn("color-scheme: dark", self.html)
|
||||||
|
|
||||||
def test_business_visual_semantics_are_not_css_hardcoded(self) -> None:
|
def test_business_visual_semantics_are_not_css_hardcoded(self) -> None:
|
||||||
forbidden = [
|
forbidden = [
|
||||||
".connection.structural",
|
".connection.structural",
|
||||||
|
|||||||
@@ -211,8 +211,10 @@ class TopologyApiQueryTests(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
presentation["theme"]["key"],
|
presentation["theme"]["key"],
|
||||||
"guanghan_dark_engineering_v1",
|
"guanghan_light_engineering_v1",
|
||||||
)
|
)
|
||||||
|
self.assertEqual(layout["layout"]["canvasWidth"], 1900.0)
|
||||||
|
self.assertEqual(layout["layout"]["canvasHeight"], 1900.0)
|
||||||
self.assertIn("nodeStyles", presentation)
|
self.assertIn("nodeStyles", presentation)
|
||||||
self.assertIn("edgeStyles", presentation)
|
self.assertIn("edgeStyles", presentation)
|
||||||
self.assertIn("decorationStyles", presentation)
|
self.assertIn("decorationStyles", presentation)
|
||||||
@@ -239,7 +241,7 @@ class TopologyApiQueryTests(unittest.TestCase):
|
|||||||
presentation["edgeStyles"]["pressurized_passage"],
|
presentation["edgeStyles"]["pressurized_passage"],
|
||||||
{
|
{
|
||||||
"displayName": "加压走道",
|
"displayName": "加压走道",
|
||||||
"strokeColor": "#51e89c",
|
"strokeColor": "#168a55",
|
||||||
"strokeWidth": 9.0,
|
"strokeWidth": 9.0,
|
||||||
"dashArray": None,
|
"dashArray": None,
|
||||||
"lineCap": "square",
|
"lineCap": "square",
|
||||||
@@ -265,15 +267,20 @@ class TopologyApiQueryTests(unittest.TestCase):
|
|||||||
conn.execute("SET search_path TO topology, public")
|
conn.execute("SET search_path TO topology, public")
|
||||||
with conn.cursor() as cur:
|
with conn.cursor() as cur:
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT stroke_color
|
SELECT edge.stroke_color
|
||||||
FROM diagram_edge_styles
|
FROM diagram_edge_styles AS edge
|
||||||
WHERE connection_type = 'pressurized_passage'
|
JOIN diagram_themes AS theme ON theme.id = edge.theme_id
|
||||||
|
WHERE edge.connection_type = 'pressurized_passage'
|
||||||
|
AND theme.theme_key = 'guanghan_light_engineering_v1'
|
||||||
""")
|
""")
|
||||||
original_color = cur.fetchone()["stroke_color"]
|
original_color = cur.fetchone()["stroke_color"]
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
UPDATE diagram_edge_styles
|
UPDATE diagram_edge_styles AS edge
|
||||||
SET stroke_color = '#00ffaa'
|
SET stroke_color = '#00ffaa'
|
||||||
WHERE connection_type = 'pressurized_passage'
|
FROM diagram_themes AS theme
|
||||||
|
WHERE theme.id = edge.theme_id
|
||||||
|
AND edge.connection_type = 'pressurized_passage'
|
||||||
|
AND theme.theme_key = 'guanghan_light_engineering_v1'
|
||||||
""")
|
""")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
try:
|
try:
|
||||||
@@ -290,9 +297,12 @@ class TopologyApiQueryTests(unittest.TestCase):
|
|||||||
finally:
|
finally:
|
||||||
with conn.cursor() as cur:
|
with conn.cursor() as cur:
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
UPDATE diagram_edge_styles
|
UPDATE diagram_edge_styles AS edge
|
||||||
SET stroke_color = %(original)s
|
SET stroke_color = %(original)s
|
||||||
WHERE connection_type = 'pressurized_passage'
|
FROM diagram_themes AS theme
|
||||||
|
WHERE theme.id = edge.theme_id
|
||||||
|
AND edge.connection_type = 'pressurized_passage'
|
||||||
|
AND theme.theme_key = 'guanghan_light_engineering_v1'
|
||||||
""", {"original": original_color})
|
""", {"original": original_color})
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
|||||||
@@ -3,41 +3,44 @@
|
|||||||
import json
|
import json
|
||||||
from topology_api.db import write_cursor
|
from topology_api.db import write_cursor
|
||||||
|
|
||||||
THEME_KEY = "guanghan_dark_engineering_v1"
|
THEME_KEY = "guanghan_light_engineering_v1"
|
||||||
|
CANVAS_WIDTH = 1900
|
||||||
|
CANVAS_HEIGHT = 1900
|
||||||
|
CONTENT_X_OFFSET = 200
|
||||||
|
|
||||||
THEME_TOKENS = {
|
THEME_TOKENS = {
|
||||||
"textColor": "#eaf2ff",
|
"textColor": "#152033",
|
||||||
"mutedTextColor": "#91a3bd",
|
"mutedTextColor": "#5e6f85",
|
||||||
"metaColor": "#a6b5c9",
|
"metaColor": "#435a72",
|
||||||
"hintColor": "#71849e",
|
"hintColor": "#6f8296",
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE_STYLES = [
|
NODE_STYLES = [
|
||||||
("node-card", "普通舱段", "#10263a", "#52baff", 3, 16),
|
("node-card", "普通舱段", "#edf7ff", "#1677b8", 3, 16),
|
||||||
("core-card", "核心舱", "#3b250d", "#ffad42", 5, 16),
|
("core-card", "核心舱", "#fff3e2", "#c76b00", 5, 16),
|
||||||
("power-card", "电力模块分支", "#2a2810", "#d5b642", 3, 16),
|
("power-card", "电力模块分支", "#fff9d9", "#9b7900", 3, 16),
|
||||||
("power-node-card", "电力模块中心", "#393412", "#d5b642", 5, 16),
|
("power-node-card", "电力模块中心", "#fff2b8", "#9b7900", 5, 16),
|
||||||
("vehicle-card", "车辆", "#291c34", "#c28cdf", 3, 16),
|
("vehicle-card", "车辆", "#f7effb", "#8755a4", 3, 16),
|
||||||
]
|
]
|
||||||
|
|
||||||
EDGE_STYLES = [
|
EDGE_STYLES = [
|
||||||
("structural_mount", "结构直连", "#8fa1b8", 6, None, "square", "structural", 10),
|
("structural_mount", "结构直连", "#66788e", 6, None, "square", "structural", 10),
|
||||||
("pressurized_passage", "加压走道", "#51e89c", 9, None, "square", "pressurized", 20),
|
("pressurized_passage", "加压走道", "#168a55", 9, None, "square", "pressurized", 20),
|
||||||
("fuel", "燃料 / 供电", "#b178e6", 4, "13 10", "square", "utility", 30),
|
("fuel", "燃料 / 供电", "#7a4fb3", 4, "13 10", "square", "utility", 30),
|
||||||
("power", "燃料 / 供电", "#b178e6", 4, "13 10", "square", "utility", 30),
|
("power", "燃料 / 供电", "#7a4fb3", 4, "13 10", "square", "utility", 30),
|
||||||
("cooling", "冷却", "#78d6e6", 4, "10 8", "square", "cooling", 40),
|
("cooling", "冷却", "#27809a", 4, "10 8", "square", "cooling", 40),
|
||||||
("docking", "对接口", "#c28cdf", 4, "10 8", "square", "docking", 50),
|
("docking", "对接口", "#8755a4", 4, "10 8", "square", "docking", 50),
|
||||||
]
|
]
|
||||||
|
|
||||||
DECORATION_STYLES = [
|
DECORATION_STYLES = [
|
||||||
(
|
(
|
||||||
"radiator",
|
"radiator",
|
||||||
"大型折叠散热面板",
|
"大型折叠散热面板",
|
||||||
"#6b5814",
|
"#fff0a8",
|
||||||
"#f0d869",
|
"#9b7900",
|
||||||
2,
|
2,
|
||||||
"散热器",
|
"散热器",
|
||||||
"#f4df7b",
|
"#6d5500",
|
||||||
{
|
{
|
||||||
"widthRatio": 0.55,
|
"widthRatio": 0.55,
|
||||||
"maxWidth": 130,
|
"maxWidth": 130,
|
||||||
@@ -64,6 +67,11 @@ def seed():
|
|||||||
cur.execute("SELECT id FROM bases WHERE code = 'guanghan'")
|
cur.execute("SELECT id FROM bases WHERE code = 'guanghan'")
|
||||||
base_id = cur.fetchone()["id"]
|
base_id = cur.fetchone()["id"]
|
||||||
|
|
||||||
|
cur.execute(
|
||||||
|
"UPDATE diagram_themes SET is_default = false WHERE base_id = %(base)s",
|
||||||
|
{"base": base_id},
|
||||||
|
)
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
INSERT INTO diagram_themes
|
INSERT INTO diagram_themes
|
||||||
(id, base_id, theme_key, name, description, tokens, is_default)
|
(id, base_id, theme_key, name, description, tokens, is_default)
|
||||||
@@ -71,8 +79,8 @@ def seed():
|
|||||||
gen_random_uuid(),
|
gen_random_uuid(),
|
||||||
%(base)s,
|
%(base)s,
|
||||||
%(theme_key)s,
|
%(theme_key)s,
|
||||||
'广寒深色工程图',
|
'广寒浅色工程图',
|
||||||
'广寒基地工程总图默认表现层主题',
|
'适配 Wiki.js 与 Dark Reader 的浅色工程总图主题',
|
||||||
%(tokens)s,
|
%(tokens)s,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -96,13 +104,20 @@ def seed():
|
|||||||
INSERT INTO diagram_layouts (id, base_id, layout_key, name,
|
INSERT INTO diagram_layouts (id, base_id, layout_key, name,
|
||||||
canvas_width, canvas_height, is_default, theme_id)
|
canvas_width, canvas_height, is_default, theme_id)
|
||||||
VALUES (gen_random_uuid(), %(base)s, 'engineering_overview_v1',
|
VALUES (gen_random_uuid(), %(base)s, 'engineering_overview_v1',
|
||||||
'工程总图 v1', 1500, 1900, true, %(theme)s)
|
'工程总图 v1', %(canvas_width)s, %(canvas_height)s, true, %(theme)s)
|
||||||
ON CONFLICT (base_id, layout_key) DO UPDATE
|
ON CONFLICT (base_id, layout_key) DO UPDATE
|
||||||
SET name = EXCLUDED.name,
|
SET name = EXCLUDED.name,
|
||||||
|
canvas_width = EXCLUDED.canvas_width,
|
||||||
|
canvas_height = EXCLUDED.canvas_height,
|
||||||
is_default = true,
|
is_default = true,
|
||||||
theme_id = EXCLUDED.theme_id
|
theme_id = EXCLUDED.theme_id
|
||||||
RETURNING id
|
RETURNING id
|
||||||
""", {"base": base_id, "theme": theme_id})
|
""", {
|
||||||
|
"base": base_id,
|
||||||
|
"canvas_width": CANVAS_WIDTH,
|
||||||
|
"canvas_height": CANVAS_HEIGHT,
|
||||||
|
"theme": theme_id,
|
||||||
|
})
|
||||||
layout_id = cur.fetchone()["id"]
|
layout_id = cur.fetchone()["id"]
|
||||||
print(f"Layout: {layout_id}")
|
print(f"Layout: {layout_id}")
|
||||||
|
|
||||||
@@ -278,7 +293,7 @@ def seed():
|
|||||||
""", {
|
""", {
|
||||||
"lid": layout_id, "cid": primary_component_id,
|
"lid": layout_id, "cid": primary_component_id,
|
||||||
"nkey": node_key,
|
"nkey": node_key,
|
||||||
"x": x, "y": y, "w": w, "h": h,
|
"x": x + CONTENT_X_OFFSET, "y": y, "w": w, "h": h,
|
||||||
"style": style, "label": label, "z": z,
|
"style": style, "label": label, "z": z,
|
||||||
"meta": display_meta, "hint": display_hint,
|
"meta": display_meta, "hint": display_hint,
|
||||||
"decorations": json.dumps(decorations),
|
"decorations": json.dumps(decorations),
|
||||||
|
|||||||
Reference in New Issue
Block a user