Compare commits

...

11 Commits

135 changed files with 1704996 additions and 605 deletions

View File

@ -0,0 +1,73 @@
<mxfile host="Electron" modified="2024-06-15T09:44:05.779Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="l_XHyQoo0jxDyFOtKOVr" version="24.5.3" type="device">
<diagram name="Page-1" id="2ca16b54-16f6-2749-3443-fa8db7711227">
<mxGraphModel dx="1434" dy="1636" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="1100" pageHeight="850" background="none" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="FxUzmvchmmA6vyn3PMC0-4" value="Passenger" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="160" y="-680" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-8" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="FxUzmvchmmA6vyn3PMC0-5" target="FxUzmvchmmA6vyn3PMC0-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-5" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;u style=&quot;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;ID&lt;/font&gt;&lt;/u&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry y="-740" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-9" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="FxUzmvchmmA6vyn3PMC0-6" target="FxUzmvchmmA6vyn3PMC0-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-6" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Name&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry y="-680" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-10" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="FxUzmvchmmA6vyn3PMC0-7" target="FxUzmvchmmA6vyn3PMC0-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-7" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Phone Number&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry y="-620" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-11" value="User" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="160" y="-480" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-14" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="FxUzmvchmmA6vyn3PMC0-13" target="FxUzmvchmmA6vyn3PMC0-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-13" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;&lt;u&gt;Phone Number&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry y="-540" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="FxUzmvchmmA6vyn3PMC0-15" target="FxUzmvchmmA6vyn3PMC0-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-15" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Username&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry y="-480" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-18" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="FxUzmvchmmA6vyn3PMC0-16" target="FxUzmvchmmA6vyn3PMC0-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-16" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Password&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry y="-420" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-19" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Airports&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="160" y="-260" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-20" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="FxUzmvchmmA6vyn3PMC0-21" target="FxUzmvchmmA6vyn3PMC0-19">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-21" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;u&gt;ID&lt;/u&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry y="-320" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="FxUzmvchmmA6vyn3PMC0-23" target="FxUzmvchmmA6vyn3PMC0-19">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-23" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Name&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry y="-260" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-24" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;endArrow=none;endFill=0;" edge="1" parent="1" source="FxUzmvchmmA6vyn3PMC0-25" target="FxUzmvchmmA6vyn3PMC0-19">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-25" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;City&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry y="-200" width="120" height="40" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -0,0 +1,167 @@
<mxfile host="Electron" modified="2024-06-15T08:22:31.671Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="NZqlYl_qx6IwzZGkF9m9" version="24.5.3" type="device">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="2234" dy="436" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="zLuWL_6ofhKRcWFHb-xI-0" value="Passenger" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="200" y="600" width="160" height="120" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-1" value="ID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-0">
<mxGeometry y="26" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-2" value="Name" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-0">
<mxGeometry y="52" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-3" value="Phone Number" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-0">
<mxGeometry y="78" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-4" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-0">
<mxGeometry y="104" width="160" height="8" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-8" value="User" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-160" y="600" width="160" height="120" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-9" value="Phone Number" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-8">
<mxGeometry y="26" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-10" value="Username" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-8">
<mxGeometry y="52" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-11" value="Password" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-8">
<mxGeometry y="78" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-12" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-8">
<mxGeometry y="104" width="160" height="8" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-13" value="Airport" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-520" y="960" width="160" height="120" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-14" value="ID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-13">
<mxGeometry y="26" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-15" value="Name" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-13">
<mxGeometry y="52" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-16" value="City" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-13">
<mxGeometry y="78" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-17" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-13">
<mxGeometry y="104" width="160" height="8" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-18" value="book tickets for" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="zLuWL_6ofhKRcWFHb-xI-10" target="zLuWL_6ofhKRcWFHb-xI-2">
<mxGeometry y="15" relative="1" as="geometry">
<mxPoint x="360" y="570" as="sourcePoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-19" value="n" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-18">
<mxGeometry x="-0.74" y="-1" relative="1" as="geometry">
<mxPoint x="-6" y="-14" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-20" value="m" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-18">
<mxGeometry x="0.68" y="3" relative="1" as="geometry">
<mxPoint x="12" y="-12" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-21" value="Flight" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-160" y="960" width="200" height="390" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-22" value="ID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="26" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-23" value="Airline" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="52" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-24" value="Departure Airport" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="78" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-28" value="Arrival Airport" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="104" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-29" value="Departure Time" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="130" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-30" value="Arrival Time" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="156" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-31" value="First Class Seats Remaining" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="182" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-32" value="Business Class Seats Remaining" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="208" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-33" value="Economy Class Seats Remaining" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="234" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-34" value="First Class Price" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="260" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-35" value="Business Class Price" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="286" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-36" value="Economy Class Price" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="312" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-37" value="Status" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="338" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-25" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="364" width="200" height="6" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-38" value="Order" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="480" y="760" width="160" height="138" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-39" value="ID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry y="26" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-40" value="Order Time" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry y="52" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-41" value="Paid" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry y="78" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-43" value="User Phone Number" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry y="104" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-42" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry y="130" width="160" height="8" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-44" value="Ticket" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="200" y="960" width="160" height="164" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-45" value="ID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="26" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-46" value="Price" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="52" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-47" value="FlightID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="78" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-48" value="Seat Class" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="104" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-50" value="PassengerID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="130" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-49" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="156" width="160" height="8" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -0,0 +1,78 @@
<mxfile host="Electron" modified="2024-06-15T07:48:17.195Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="UQOt4T8w8XaLFkogghZr" version="24.5.3" type="device">
<diagram name="Page-1" id="0783ab3e-0a74-02c8-0abd-f7b4e66b4bec">
<mxGraphModel dx="1434" dy="836" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" background="none" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="1c1d494c118603dd-1" value="Pool" style="swimlane;html=1;childLayout=stackLayout;startSize=20;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;" parent="1" vertex="1">
<mxGeometry x="40" y="20" width="500" height="500" as="geometry" />
</mxCell>
<mxCell id="1c1d494c118603dd-2" value="管理员" style="swimlane;html=1;startSize=20;" parent="1c1d494c118603dd-1" vertex="1">
<mxGeometry y="20" width="250" height="480" as="geometry" />
</mxCell>
<mxCell id="1c1d494c118603dd-3" value="用户" style="swimlane;html=1;startSize=20;" parent="1c1d494c118603dd-1" vertex="1">
<mxGeometry x="250" y="20" width="250" height="480" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-1" value="新建航班" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="-180" y="180" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-3" target="VOh0G463oaxQBEEBO385-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-3" value="登录" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="-180" y="60" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-2" target="VOh0G463oaxQBEEBO385-7">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-2" value="注册" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="75" y="60" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-5" target="VOh0G463oaxQBEEBO385-8">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-5" value="查询航班" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="75" y="180" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-7" target="VOh0G463oaxQBEEBO385-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-7" target="VOh0G463oaxQBEEBO385-13">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="230" y="135" />
<mxPoint x="230" y="365" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-7" value="登录" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="75" y="120" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-8" value="" style="whiteSpace=wrap;html=1;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fillColor=#000000;fontFamily=Verdana;fontSize=12;align=center;rotation=0;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="51.5" y="240" width="147" height="10" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-13" target="VOh0G463oaxQBEEBO385-20">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-13" value="查看订单" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="75" y="350" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-1" target="VOh0G463oaxQBEEBO385-8">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-20" value="修改订单" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="75" y="410" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="VOh0G463oaxQBEEBO385-16" target="VOh0G463oaxQBEEBO385-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-16" value="创建订单" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1">
<mxGeometry x="365" y="330" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="VOh0G463oaxQBEEBO385-8" target="VOh0G463oaxQBEEBO385-16">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -0,0 +1,280 @@
<mxfile host="Electron" modified="2024-06-15T10:24:59.977Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="9sNisp8YeVg9tpPKz7NX" version="24.5.3" type="device">
<diagram name="Page-1" id="2ca16b54-16f6-2749-3443-fa8db7711227">
<mxGraphModel dx="1434" dy="1636" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="1100" pageHeight="850" background="none" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="FxUzmvchmmA6vyn3PMC0-96" value="1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-4" target="FxUzmvchmmA6vyn3PMC0-95" edge="1">
<mxGeometry y="10" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-4" value="Passenger" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="240" y="-440" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-8" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-5" target="FxUzmvchmmA6vyn3PMC0-4" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="210" y="-430" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-5" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;u style=&quot;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;ID&lt;/font&gt;&lt;/u&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="-500" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-9" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-6" target="FxUzmvchmmA6vyn3PMC0-4" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="210" y="-420" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-6" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Name&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="-440" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-10" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-7" target="FxUzmvchmmA6vyn3PMC0-4" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="210" y="-410" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-7" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Phone Number&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="-380" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-93" value="1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-11" target="FxUzmvchmmA6vyn3PMC0-92" edge="1">
<mxGeometry y="10" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-11" value="User" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="240" y="-640" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-14" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-13" target="FxUzmvchmmA6vyn3PMC0-11" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-13" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;&lt;u&gt;Phone Number&lt;/u&gt;&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="-700" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-15" target="FxUzmvchmmA6vyn3PMC0-11" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-15" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Username&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="-640" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-18" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-16" target="FxUzmvchmmA6vyn3PMC0-11" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-16" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Password&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="-580" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-82" value="1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-19" target="FxUzmvchmmA6vyn3PMC0-79" edge="1">
<mxGeometry x="0.0122" y="-10" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-19" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Airport&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="240" y="-240" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-20" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-21" target="FxUzmvchmmA6vyn3PMC0-19" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-21" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;u&gt;ID&lt;/u&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="-300" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-23" target="FxUzmvchmmA6vyn3PMC0-19" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-23" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Name&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="-240" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-24" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-25" target="FxUzmvchmmA6vyn3PMC0-19" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-25" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;City&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="80" y="-180" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-43" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-79" target="FxUzmvchmmA6vyn3PMC0-38" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="390" y="-120" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-45" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-26" target="FxUzmvchmmA6vyn3PMC0-36" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-46" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-26" target="FxUzmvchmmA6vyn3PMC0-40" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-52" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-26" target="FxUzmvchmmA6vyn3PMC0-47" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-53" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-26" target="FxUzmvchmmA6vyn3PMC0-39" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-54" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-26" target="FxUzmvchmmA6vyn3PMC0-49" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-26" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Flight&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="680" y="-240" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-27" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-28" target="FxUzmvchmmA6vyn3PMC0-26" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-28" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;u&gt;ID&lt;/u&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="840" y="-300" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-29" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-30" target="FxUzmvchmmA6vyn3PMC0-26" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-30" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Airline&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="840" y="-240" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-42" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;endArrow=none;endFill=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-35" target="FxUzmvchmmA6vyn3PMC0-78" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="580" y="-370" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-35" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Departure Time&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="460" y="-340" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-36" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Business Class Seats Remaining&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="790" y="-30" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-44" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-37" target="FxUzmvchmmA6vyn3PMC0-26" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-37" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;First &lt;/span&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Class Seats Remaining&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="820" y="-90" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-38" value="&lt;font style=&quot;font-size: 12px;&quot;&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Arrival&lt;/span&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt; Time&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="460" y="-140" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-39" value="&lt;span style=&quot;white-space-collapse: preserve; color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left;&quot;&gt;First &lt;/span&gt;&lt;span style=&quot;white-space-collapse: preserve; color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left;&quot;&gt;Class Price&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="540" y="-90" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-40" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Economy&lt;/span&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Class Seats Remaining&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="750" y="30" width="160" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-47" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Business&lt;/span&gt;&lt;span style=&quot;white-space-collapse: preserve; color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;white-space-collapse: preserve; color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left;&quot;&gt;Class Price&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="570" y="-30" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-49" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Economy&lt;/span&gt;&lt;span style=&quot;white-space-collapse: preserve; color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;white-space-collapse: preserve; color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left;&quot;&gt;Class Price&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="610" y="30" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-56" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-55" target="FxUzmvchmmA6vyn3PMC0-26" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-55" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Status&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="840" y="-180" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-67" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-57" target="FxUzmvchmmA6vyn3PMC0-65" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-90" value="1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-57" target="FxUzmvchmmA6vyn3PMC0-89" edge="1">
<mxGeometry y="10" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-57" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Order&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="680" y="-640" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-58" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-59" target="FxUzmvchmmA6vyn3PMC0-57" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-59" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;u&gt;ID&lt;/u&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="840" y="-700" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-62" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-63" target="FxUzmvchmmA6vyn3PMC0-57" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-63" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Paid&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="840" y="-580" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-65" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Order Time&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="840" y="-640" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-68" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-69" target="FxUzmvchmmA6vyn3PMC0-76" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="480" y="-460" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-86" value="n" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-69" target="FxUzmvchmmA6vyn3PMC0-85" edge="1">
<mxGeometry y="10" relative="1" as="geometry">
<mxPoint x="740" y="-460" as="targetPoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-69" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Ticket&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="680" y="-440" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-70" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-71" target="FxUzmvchmmA6vyn3PMC0-69" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-71" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;u&gt;ID&lt;/u&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="840" y="-500" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-72" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-73" target="FxUzmvchmmA6vyn3PMC0-69" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-73" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Price&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="840" y="-380" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-76" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;Seat Class&lt;/font&gt;&lt;/span&gt;" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="840" y="-440" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-80" value="1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-78" target="FxUzmvchmmA6vyn3PMC0-19" edge="1">
<mxGeometry x="-0.0122" y="-10" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-81" value="n" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-78" target="FxUzmvchmmA6vyn3PMC0-26" edge="1">
<mxGeometry x="-0.0122" y="10" relative="1" as="geometry">
<mxPoint x="500" y="-250" as="sourcePoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-78" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;Departure&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="460" y="-270" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-83" value="n" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-79" target="FxUzmvchmmA6vyn3PMC0-26" edge="1">
<mxGeometry x="-0.0122" y="-10" relative="1" as="geometry">
<mxPoint x="500" y="-190" as="sourcePoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-79" value="&lt;span style=&quot;white-space-collapse: preserve; color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left;&quot;&gt;Arrival&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="460" y="-210" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-87" value="1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-85" target="FxUzmvchmmA6vyn3PMC0-26" edge="1">
<mxGeometry y="10" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-85" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;in&lt;/font&gt;&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="680" y="-340" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-91" value="n" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;endArrow=none;endFill=0;" parent="1" source="FxUzmvchmmA6vyn3PMC0-89" target="FxUzmvchmmA6vyn3PMC0-69" edge="1">
<mxGeometry y="10" relative="1" as="geometry">
<mxPoint x="740" y="-560" as="sourcePoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-89" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;include&lt;/font&gt;&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="680" y="-540" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-94" value="n" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" target="FxUzmvchmmA6vyn3PMC0-57" edge="1" source="FxUzmvchmmA6vyn3PMC0-92">
<mxGeometry y="10" relative="1" as="geometry">
<mxPoint x="500" y="-620" as="sourcePoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-92" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;book&lt;/font&gt;&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="460" y="-640" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-97" value="1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;endArrow=none;endFill=0;" parent="1" target="FxUzmvchmmA6vyn3PMC0-69" edge="1" source="FxUzmvchmmA6vyn3PMC0-95">
<mxGeometry y="10" relative="1" as="geometry">
<mxPoint x="500" y="-420" as="sourcePoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FxUzmvchmmA6vyn3PMC0-95" value="&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &amp;quot;Open Sans&amp;quot;, &amp;quot;Clear Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;Segoe UI Emoji&amp;quot;, sans-serif; orphans: 4; text-align: left; white-space-collapse: preserve;&quot;&gt;&lt;font style=&quot;font-size: 12px;&quot;&gt;hold&lt;/font&gt;&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="460" y="-440" width="120" height="40" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 361 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 75 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 104 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 77 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 240 KiB

View File

@ -29,24 +29,24 @@
>
>将以上内容形成系统规划与可行性分析报告,找两位同学当业务专家帮你论证方案的可行性,并在报告上列出专家姓名、专家论证建议和结论。
**12306系统规划与可行性分析报告**
**航空订票系统规划与可行性分析报告**
1. **系统名称**
1. 系统名称
**12306铁路票务系统**
**飞行订票系统 (FlyBooking System)**
2. **组织架构图及相关业务部门**
2. 组织架构图及相关业务部门
**组织架构图**
**组织架构图**
```
铁路运营公司
├── 铁路运营部门
│ ├── 车次管理
│ ├── 车站管理
航空公司
├── 运营部门
│ ├── 航班管理
│ ├── 机场管理
│ └── 票务管理
├── 系统中台
│ ├── 用户管理
├── IT 部门
│ ├── 系统开发
│ ├── 数据库管理
│ ├── 应用支持
│ └── 安全与合规
@ -54,96 +54,81 @@
├── 客服中心
└── 技术支持
```
**涉及的相关业务部门:**
- **铁路运营部门**:负责车次数据和车站数据的添加、修改、维护
- **系统中台**:负责系统的整体控制、用户管理、数据库管理、应用支持、安全与合规
- **运营部门**:负责航班和机场数据的管理、维护和更新
- **IT 部门**:负责系统的开发、维护和安全管理,确保系统稳定运行
- **客户服务部门**:提供客户支持,解决用户在使用系统过程中遇到的问题。
3. **用户使用系统开展业务的场景**
3. 用户使用系统开展业务的场景
**用户(旅客):**
1. **注册**:用户在12306系统的注册页面填写个人信息,完成账号注册。
2. **查询车票**:登录后,用户在系统中输入出发地、目的地和日期,查询可用车次和座位信息。
3. **购买车票**:选定车次和座位后,用户通过系统完成支付,生成电子车票,并在行程日期前往车站使用电子车票乘车
1. **注册**:用户在飞行订票系统的注册页面填写个人信息,完成账号注册。**
2. **查询航班**:登录后,用户在系统中输入出发地、目的地和日期,查询可用航班和座位级别信息。
3. **预订机票**:选定航班和座位级别后,用户通过系统完成支付,生成电子机票,并在行程日期前往机场使用电子机票登机
**铁路运营部门员工:**
**运营部门员工:**
1. **登录**:员工使用分配的账号登录系统。
2. **添加车次和车站信息**:员工进入后台管理界面,添加或修改车次信息(如车次编号、发车时间、到达时间、座位类型等)和车站信息(如车站名称、所在省市等)。
2. **管理航班和机场信息**:员工进入后台管理界面,添加或修改航班信息(如航班编号、起飞时间、到达时间、座位级别等)和机场信息(如机场名称、所在国家和城市等)。
4. **系统性能指标**
4. 系统性能指标
- **并发用户数**:支持同时在线用户数量 50,000 人。
- **总用户数**:系统应支持注册用户数量 10,000,000 人。
- **核心业务响应时间**:查询航班和预订机票的响应时间应不超过 1 秒。
- **数据更新频率**航班和机场数据应能在5分钟内更新。
- **并发用户数**:支持同时在线用户数量 100,000 人。
5. 系统的战略地位
- **总用户数**:系统应支持注册用户数量 100,000,000 人。
- **核心业务响应时间**:查询车票和购买车票的响应时间应不超过 2 秒。
- **数据更新频率**车次和车站数据应能在10分钟内更新。
5. **系统的战略地位**
12306系统作为铁路票务系统战略地位体现在以下几个方面
- **客户服务**:提供便捷的在线购票服务,提高客户满意度,增强客户忠诚度。
- **运营效率**:通过电子化管理车次和车站数据,提高铁路运营的效率和准确性。
- **市场地位**:占据全国铁路票务的主要市场,增强在交通出行领域的市场竞争力。
飞行订票系统作为航空公司的核心业务系统,其战略地位体现在以下几个方面:
- **客户服务**:提供便捷的在线订票服务,提高客户满意度,增强客户忠诚度。
- **运营效率**:通过电子化管理航班和机场数据,提高航空运营的效率和准确性。
- **市场地位**:占据航空票务市场的主要份额,增强在交通出行领域的市场竞争力。
- **收益**:通过在线售票获得直接收益,同时通过提升运营效率间接节约成本。
6. **投资和运营成本及收益分析**
6. 投资和运营成本及收益分析
**投资成本:**
- **硬件投入**:服务器、存储设备、网络设备等。
- **软件投入**:数据库软件、应用服务器软件、安全防护软件等。
- **开发投入**:系统开发费用,包括需求分析、设计、编码、测试等。
- **培训费用**:对员工的培训费用。
**运营成本:**
- **维护成本**:系统的日常维护,包括硬件维护、软件升级、数据备份等。
- **人力成本**:技术支持人员、客户服务人员、运营管理人员等的工资。
- **安全成本**:系统安全防护,包括防火墙、入侵检测、防病毒等。
**收益分析:**
- **直接收益**:车票销售收入。
- **直接收益**:机票销售收入。
- **间接收益**:提高运营效率,降低人力成本和错误率,提升客户满意度和忠诚度。
7. **技术选型规划**
- **数据库**:选用高性能的关系型数据库,如 MySQL ,用于存储车次、车站、用户等数据。
7. 技术选型规划
- **数据库**:选用高性能的关系型数据库,如 MySQL、PostgreSQL用于存储用户、机场、航班和机票数据。
- **应用服务器**:采用分布式架构,使用 Java EE、Spring Boot 等技术实现系统的业务逻辑。
- **前端技术**:使用 React、Vue.js 等框架开发用户界面,提供良好的用户体验。
- **安全技术**:部署 SSL 证书,采用 OAuth 2.0 进行用户认证,使用防火墙、入侵检测系统等保护系统安全。
**业务专家论证**
专家姓名:阮蓬辉
**专家姓名:李清林**
建议和结论:
**建议和结论:**
李明认为该系统的架构设计合理,能够有效支持铁路票务业务的需求。建议在技术选型上考虑使用云计算平台如阿里云、AWS以提高系统的扩展性和可靠性。此外需加强用户数据保护确保系统的合规性。
李明认为该系统的架构设计合理,能够有效支持航空订票业务的需求。建议在技术选型上考虑使用云计算平台如阿里云、AWS以提高系统的扩展性和可靠性。此外需加强用户数据保护确保系统的合规性。
专家姓名:李桦炅
**专家姓名:李桦炅**
建议和结论****
**建议和结论:**
张华认为系统在性能指标上的设定符合大规模用户访问的需求,但需特别注意并发访问的处理,建议采用缓存技术(如 Redis和消息队列如 Kafka来提升系统的响应速度和可靠性。同时应建立完善的监控系统实时监控系统性能和安全。
通过上述论证,12306系统的规划和可行性分析得到了进一步确认和优化。
通过上述论证,飞行订票系统的规划和可行性分析得到了进一步确认和优化。
@ -161,7 +146,80 @@
>
> 将以上内容形成系统的需求规格说明书。
1. 用例图
![用例图.drawio](images\用例图.drawio.svg)
2. 泳道图
![泳道图.drawio](images\泳道图.drawio.svg)
3. 数据结构
![数据结构类图.drawio](images\数据结构类图.drawio.svg)
**数据字典**
- **Passengers 表**
- ID: 身份证号主键18位正则验证。
- Name: 姓名必填长度255。
- Phone_number: 手机号必填长度11正则验证。
- **Users 表**
- Phone_number: 手机号主键长度11正则验证。
- Username: 用户名必填长度255。
- Password: 密码必填长度255。
- **Airports 表**
- ID: 机场三字码主键长度3。
- Name: 机场名称必填唯一长度255。
- City: 城市必填长度255。
- **Flights 表**
- ID: 航班编号主键长度255。
- Airline: 航空公司必填长度255。
- Departure_airport: 出发机场必填长度3外键。
- Arrival_airport: 到达机场必填长度3外键。
- Departure_time: 出发时间,必填,日期时间格式。
- Arrival_time: 到达时间,必填,日期时间格式。
- First_class_seats_remaining: 头等舱剩余座位数,必填,整数。
- Business_class_seats_remaining: 商务舱剩余座位数,必填,整数。
- Economy_class_seats_remaining: 经济舱剩余座位数,必填,整数。
- First_class_price: 头等舱票价,必填,数值格式。
- Business_class_price: 商务舱票价,必填,数值格式。
- Economy_class_price: 经济舱票价,必填,数值格式。
- Status: 航班状态必填长度255。
- **Orders 表**
- ID: 订单编号,自增,主键。
- Order_time: 订单时间,必填,日期时间格式。
- Paid: 是否支付,必填,布尔值。
- User_phone_number: 用户手机号必填长度11外键。
- **Tickets 表**
- ID: 机票编号,自增,主键。
- Price: 票价,必填,数值格式。
- FlightID: 航班编号必填长度255外键。
- Seat_class: 座位等级必填长度255。
- PassengerID: 乘客身份证号必填长度18外键。
- OrderID: 订单编号,必填,整数,外键。
4. 数据流图
![数据流图.drawio](images\数据流图.drawio.svg)
5. 非功能性需求
**业务处理性能**
- **响应时间**: 系统必须在用户请求操作后的2秒内做出响应。
- **并发处理能力**: 系统需支持至少1000个并发用户。
#### 安全性
- **数据加密**: 所有传输的数据必须使用HTTPS协议加密。
- **身份验证**: 系统必须实现多因素身份验证MFA
- **权限控制**: 不同用户角色拥有不同的操作权限,确保数据的访问安全。
#### 完整性
- **数据备份**: 系统需实现每日数据备份,防止数据丢失。
- **数据校验**: 系统在数据录入时需进行校验,确保数据的准确性和一致性。
@ -176,7 +234,14 @@
>
>以上内容形成第一版的系统设计规格说明,以后持续完善。
- Passengers(<u>ID</u>, Name, Phone_number)
- Users(<u>Phone_number</u>, Username, Password)
- Airports(<u>ID</u>, Name, City)
- Flights(<u>ID</u>, Airline, Departure_airport, Arrival_airport, Departure_time, Arrival_time, First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining, First_class_price, Business_class_price, Economy_class_price, Status)
- Orders(<u>ID</u>, Order_time, Paid, User_phone_number)
- Tickets(<u>ID</u>, Price, FlightID, Seat_class, PassengerID, OrderID)
![E-R图.drawio](images\E-R图.drawio.svg)
@ -197,10 +262,37 @@
>- 原材料:原材料号,原材料名,类别
>- 仓库:仓库号,仓库名
<img src="images\7.png" alt="7" style="zoom: 50%;" />
<img src="images\8.png" alt="8" style="zoom: 50%;" />
# 5. 补充作业 2
>将上题的E-R图转换成关系模型指明每个关系模式的主键和外键在函数依赖的范畴分析关系模式满足第几范式并将不满足BCNF的关系模式分解成BCNF。
第 7 题:
- 系(<u>系编号</u>,系名,学校名);
- 班级(<u>班级号</u>,班级名,系编号);
- 教研室(<u>教研室编号</u>,教研室名,系编号);
- 学生(<u>学号</u>,姓名,学历,班级号,导师职工号);
- 课程(<u>课程号</u>,课程名);
- 教员(<u>职工号</u>,姓名,职称,教研室编号);
- 选课(<u>学号,课程号</u>,成绩)。
已满足 BCNF。
第 8 题:
- 产品(<u>产品号</u>,产品名,仓库号);
- 零件(<u>零件号</u>,零件名);
- 材料(<u>材料号</u>,材料名,类别,仓库号,存放量);
- 仓库(<u>仓库号</u>,仓库名);
- 产品组成(<u>产品名,零件号</u>,使用零件量);
- 零件储存(<u>零件号,仓库号</u>,存储量);
- 零件制造(<u>零件号,材料号</u>,使用材料量)。
已满足 BCNF。

View File

@ -0,0 +1,70 @@
<mxfile host="Electron" modified="2024-06-15T08:52:28.021Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="glt3bJqBRxIXr6deJDB9" version="24.5.3" type="device">
<diagram id="prtHgNgQTEPvFCAcTncT" name="Page-1">
<mxGraphModel dx="1434" dy="836" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="dNxyNK7c78bLwvsdeMH5-11" value="用户系统 " style="swimlane;html=1;startSize=20;horizontal=1;containerType=tree;glass=0;" parent="1" vertex="1">
<mxGeometry x="160" y="80" width="360" height="240" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="dNxyNK7c78bLwvsdeMH5-11" source="egr6nfyeFeLvQp72Hrg7-1" target="egr6nfyeFeLvQp72Hrg7-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-1" value="订单" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="dNxyNK7c78bLwvsdeMH5-11">
<mxGeometry x="200" y="40" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-3" value="机票" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="dNxyNK7c78bLwvsdeMH5-11">
<mxGeometry x="40" y="160" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="dNxyNK7c78bLwvsdeMH5-11" source="egr6nfyeFeLvQp72Hrg7-2" target="egr6nfyeFeLvQp72Hrg7-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="dNxyNK7c78bLwvsdeMH5-11" source="egr6nfyeFeLvQp72Hrg7-2" target="egr6nfyeFeLvQp72Hrg7-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-2" value="用户" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="dNxyNK7c78bLwvsdeMH5-11">
<mxGeometry x="40" y="40" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-14" value="用户系统 " style="swimlane;html=1;startSize=20;horizontal=1;containerType=tree;glass=0;" vertex="1" parent="1">
<mxGeometry x="160" y="360" width="520" height="360" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-16" value="订单" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="egr6nfyeFeLvQp72Hrg7-14">
<mxGeometry x="200" y="40" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="egr6nfyeFeLvQp72Hrg7-14" source="egr6nfyeFeLvQp72Hrg7-17" target="egr6nfyeFeLvQp72Hrg7-22">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="egr6nfyeFeLvQp72Hrg7-14" source="egr6nfyeFeLvQp72Hrg7-17" target="egr6nfyeFeLvQp72Hrg7-25">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-17" value="创建订单" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="egr6nfyeFeLvQp72Hrg7-14">
<mxGeometry x="40" y="160" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="egr6nfyeFeLvQp72Hrg7-14" source="egr6nfyeFeLvQp72Hrg7-20" target="egr6nfyeFeLvQp72Hrg7-16">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="egr6nfyeFeLvQp72Hrg7-14" source="egr6nfyeFeLvQp72Hrg7-20" target="egr6nfyeFeLvQp72Hrg7-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-20" value="用户" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="egr6nfyeFeLvQp72Hrg7-14">
<mxGeometry x="40" y="40" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-21" value="机票" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="egr6nfyeFeLvQp72Hrg7-14">
<mxGeometry x="360" y="40" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="egr6nfyeFeLvQp72Hrg7-14" source="egr6nfyeFeLvQp72Hrg7-22" target="egr6nfyeFeLvQp72Hrg7-16">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-22" value="修改订单状态" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="egr6nfyeFeLvQp72Hrg7-14">
<mxGeometry x="200" y="160" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="egr6nfyeFeLvQp72Hrg7-14" source="egr6nfyeFeLvQp72Hrg7-17" target="egr6nfyeFeLvQp72Hrg7-21">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="egr6nfyeFeLvQp72Hrg7-25" value="支付" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="egr6nfyeFeLvQp72Hrg7-14">
<mxGeometry x="40" y="280" width="120" height="60" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -0,0 +1,256 @@
<mxfile host="Electron" modified="2024-06-15T08:33:24.325Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="Rf2dxf5CFPEMCp9shdLA" version="24.5.3" type="device">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="1834" dy="436" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="zLuWL_6ofhKRcWFHb-xI-0" value="Passenger" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="200" y="600" width="160" height="110" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-1" value="ID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-0">
<mxGeometry y="26" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-2" value="Name" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-0">
<mxGeometry y="52" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-3" value="Phone Number" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-0">
<mxGeometry y="78" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-4" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-0">
<mxGeometry y="104" width="160" height="6" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-8" value="User" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-160" y="600" width="160" height="110" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-9" value="Phone Number" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-8">
<mxGeometry y="26" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-10" value="Username" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-8">
<mxGeometry y="52" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-11" value="Password" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-8">
<mxGeometry y="78" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-12" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-8">
<mxGeometry y="104" width="160" height="6" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-13" value="Airport" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="520" y="600" width="160" height="110" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-14" value="ID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-13">
<mxGeometry y="26" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-15" value="Name" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-13">
<mxGeometry y="52" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-16" value="City" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-13">
<mxGeometry y="78" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-17" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-13">
<mxGeometry y="104" width="160" height="4" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-18" value="book tickets for" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="zLuWL_6ofhKRcWFHb-xI-10" target="zLuWL_6ofhKRcWFHb-xI-2">
<mxGeometry y="15" relative="1" as="geometry">
<mxPoint x="360" y="570" as="sourcePoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-19" value="n" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-18">
<mxGeometry x="-0.74" y="-1" relative="1" as="geometry">
<mxPoint x="-6" y="-14" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-20" value="m" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-18">
<mxGeometry x="0.68" y="3" relative="1" as="geometry">
<mxPoint x="12" y="-12" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-69" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="zLuWL_6ofhKRcWFHb-xI-21" target="zLuWL_6ofhKRcWFHb-xI-13">
<mxGeometry relative="1" as="geometry">
<mxPoint x="590" y="770" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-70" value="takes off or lands on" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-69">
<mxGeometry x="0.0471" y="-2" relative="1" as="geometry">
<mxPoint x="58" y="9" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-71" value="n" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-69">
<mxGeometry x="0.7647" y="-2" relative="1" as="geometry">
<mxPoint x="18" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-72" value="m" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-69">
<mxGeometry x="-0.8118" y="-1" relative="1" as="geometry">
<mxPoint x="19" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-21" value="Flight" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="500" y="880" width="200" height="370" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-22" value="ID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="26" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-23" value="Airline" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="52" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-24" value="Departure Airport" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="78" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-28" value="Arrival Airport" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="104" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-29" value="Departure Time" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="130" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-30" value="Arrival Time" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="156" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-31" value="First Class Seats Remaining" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="182" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-32" value="Business Class Seats Remaining" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="208" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-33" value="Economy Class Seats Remaining" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="234" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-34" value="First Class Price" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="260" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-35" value="Business Class Price" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="286" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-36" value="Economy Class Price" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="312" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-37" value="Status" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="338" width="200" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-25" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-21">
<mxGeometry y="364" width="200" height="6" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="zLuWL_6ofhKRcWFHb-xI-8" target="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry relative="1" as="geometry">
<mxPoint x="-80" y="800" as="targetPoint" />
<mxPoint x="-250" y="800" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-53" value="makes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-52">
<mxGeometry x="0.0941" y="3" relative="1" as="geometry">
<mxPoint x="27" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-54" value="n" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-52">
<mxGeometry x="0.7647" y="1" relative="1" as="geometry">
<mxPoint x="19" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-55" value="1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-52">
<mxGeometry x="-0.7882" y="-3" relative="1" as="geometry">
<mxPoint x="23" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-38" value="Order" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-160" y="880" width="160" height="138" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-39" value="ID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry y="26" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-40" value="Order Time" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry y="52" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-41" value="Paid" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry y="78" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-43" value="User Phone Number" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry y="104" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-42" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-38">
<mxGeometry y="130" width="160" height="8" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-64" value="belongs to" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="zLuWL_6ofhKRcWFHb-xI-44" target="zLuWL_6ofhKRcWFHb-xI-0">
<mxGeometry x="-0.0588" y="-30" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-65" value="1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-64">
<mxGeometry x="0.7765" relative="1" as="geometry">
<mxPoint x="20" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-68" value="n" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-64">
<mxGeometry x="-0.8" y="2" relative="1" as="geometry">
<mxPoint x="22" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-44" value="Ticket" style="swimlane;fontStyle=2;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;rounded=0;shadow=0;strokeWidth=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="200" y="880" width="160" height="190" as="geometry">
<mxRectangle x="230" y="140" width="160" height="26" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-45" value="ID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="26" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-46" value="Price" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="52" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-47" value="FlightID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="78" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-48" value="Seat Class" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="104" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-50" value="PassengerID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="130" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-51" value="OrderID" style="text;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rounded=0;shadow=0;html=0;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="156" width="160" height="26" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-49" value="" style="line;html=1;strokeWidth=1;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="zLuWL_6ofhKRcWFHb-xI-44">
<mxGeometry y="182" width="160" height="8" as="geometry" />
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-56" value="includes" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="zLuWL_6ofhKRcWFHb-xI-40" target="zLuWL_6ofhKRcWFHb-xI-46">
<mxGeometry y="15" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-57" value="1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-56">
<mxGeometry x="-0.8" y="-1" relative="1" as="geometry">
<mxPoint y="-14" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-58" value="n" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-56">
<mxGeometry x="0.74" y="2" relative="1" as="geometry">
<mxPoint y="-13" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-59" value="of" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="zLuWL_6ofhKRcWFHb-xI-46" target="zLuWL_6ofhKRcWFHb-xI-23">
<mxGeometry y="15" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-60" value="1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-59">
<mxGeometry x="0.7125" relative="1" as="geometry">
<mxPoint y="-15" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="zLuWL_6ofhKRcWFHb-xI-61" value="n" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="zLuWL_6ofhKRcWFHb-xI-59">
<mxGeometry x="-0.7" relative="1" as="geometry">
<mxPoint y="-15" as="offset" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -0,0 +1,83 @@
<mxfile host="Electron" modified="2024-06-15T07:49:22.717Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="ElBiXbBcuabTAEYZT727" version="24.5.3" type="device">
<diagram name="Page-1" id="0783ab3e-0a74-02c8-0abd-f7b4e66b4bec">
<mxGraphModel dx="1434" dy="836" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" background="none" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="1c1d494c118603dd-1" value="Pool" style="swimlane;html=1;childLayout=stackLayout;startSize=20;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;" parent="1" vertex="1">
<mxGeometry x="40" y="20" width="500" height="500" as="geometry" />
</mxCell>
<mxCell id="1c1d494c118603dd-2" value="管理员" style="swimlane;html=1;startSize=20;" parent="1c1d494c118603dd-1" vertex="1">
<mxGeometry y="20" width="250" height="480" as="geometry" />
</mxCell>
<mxCell id="1c1d494c118603dd-3" value="用户" style="swimlane;html=1;startSize=20;" parent="1c1d494c118603dd-1" vertex="1">
<mxGeometry x="250" y="20" width="250" height="480" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-1" target="VOh0G463oaxQBEEBO385-8">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="-130" y="230" />
<mxPoint x="88" y="230" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-1" value="新建航班" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="-180" y="180" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-3" target="VOh0G463oaxQBEEBO385-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-3" value="登录" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="-180" y="60" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-2" target="VOh0G463oaxQBEEBO385-7">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-2" value="注册" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="75" y="60" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-5" target="VOh0G463oaxQBEEBO385-8">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-5" value="查询航班" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="75" y="180" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-7" target="VOh0G463oaxQBEEBO385-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-7" target="VOh0G463oaxQBEEBO385-13">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="230" y="135" />
<mxPoint x="230" y="365" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-7" value="登录" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="75" y="120" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-8" value="" style="whiteSpace=wrap;html=1;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fillColor=#000000;fontFamily=Verdana;fontSize=12;align=center;rotation=0;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="51.5" y="240" width="147" height="10" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1c1d494c118603dd-3" source="VOh0G463oaxQBEEBO385-13" target="VOh0G463oaxQBEEBO385-20">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-13" value="查看订单" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="75" y="350" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-20" value="删除/确认订单" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1c1d494c118603dd-3">
<mxGeometry x="75" y="410" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="VOh0G463oaxQBEEBO385-16" target="VOh0G463oaxQBEEBO385-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-16" value="创建订单" style="rounded=1;whiteSpace=wrap;html=1;shadow=0;comic=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Verdana;fontSize=12;align=center;arcSize=50;" vertex="1" parent="1">
<mxGeometry x="365" y="330" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="VOh0G463oaxQBEEBO385-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="VOh0G463oaxQBEEBO385-8" target="VOh0G463oaxQBEEBO385-16">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -1,32 +1,147 @@
<mxfile host="Electron" modified="2024-06-10T07:33:52.533Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.1 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="VInC7AW9LVvjQGWzSf6g" version="24.5.1" type="device">
<mxfile host="Electron" modified="2024-06-15T07:20:30.564Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="T057kvN53-FB1htcEguo" version="24.5.3" type="device">
<diagram name="第 1 页" id="3B1iCcji8M7D98_Schui">
<mxGraphModel dx="1434" dy="836" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="k9E8UJ5gUlcifJo20EVi-13" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="k9E8UJ5gUlcifJo20EVi-1" target="k9E8UJ5gUlcifJo20EVi-9">
<mxCell id="k9E8UJ5gUlcifJo20EVi-2" value="航班订票系统" style="shape=umlFrame;whiteSpace=wrap;html=1;pointerEvents=0;recursiveResize=0;container=1;collapsible=0;width=160;" parent="1" vertex="1">
<mxGeometry x="160" y="80" width="440" height="620" as="geometry" />
</mxCell>
<mxCell id="k9E8UJ5gUlcifJo20EVi-13" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="k9E8UJ5gUlcifJo20EVi-1" target="k9E8UJ5gUlcifJo20EVi-9" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="k9E8UJ5gUlcifJo20EVi-14" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="k9E8UJ5gUlcifJo20EVi-1" target="k9E8UJ5gUlcifJo20EVi-11">
<mxCell id="k9E8UJ5gUlcifJo20EVi-14" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="k9E8UJ5gUlcifJo20EVi-1" target="k9E8UJ5gUlcifJo20EVi-11" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="k9E8UJ5gUlcifJo20EVi-15" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="k9E8UJ5gUlcifJo20EVi-1" target="k9E8UJ5gUlcifJo20EVi-12">
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-8" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="k9E8UJ5gUlcifJo20EVi-1" target="FOyGFu5lgkxIsMJ1ngSE-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="k9E8UJ5gUlcifJo20EVi-1" value="乘客" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;" vertex="1" parent="1">
<mxGeometry x="50" y="240" width="30" height="60" as="geometry" />
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-28" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="k9E8UJ5gUlcifJo20EVi-1" target="FOyGFu5lgkxIsMJ1ngSE-21">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="k9E8UJ5gUlcifJo20EVi-2" value="Diagram Heading" style="shape=umlFrame;whiteSpace=wrap;html=1;pointerEvents=0;recursiveResize=0;container=1;collapsible=0;width=160;" vertex="1" parent="1">
<mxGeometry x="160" y="80" width="560" height="760" as="geometry" />
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-29" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="k9E8UJ5gUlcifJo20EVi-1" target="FOyGFu5lgkxIsMJ1ngSE-22">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="k9E8UJ5gUlcifJo20EVi-9" value="注册" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="k9E8UJ5gUlcifJo20EVi-2">
<mxGeometry x="40" y="80" width="120" height="40" as="geometry" />
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-30" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="k9E8UJ5gUlcifJo20EVi-1" target="FOyGFu5lgkxIsMJ1ngSE-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="k9E8UJ5gUlcifJo20EVi-11" value="修改用户信息" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="k9E8UJ5gUlcifJo20EVi-2">
<mxGeometry x="40" y="160" width="120" height="40" as="geometry" />
<mxCell id="k9E8UJ5gUlcifJo20EVi-1" value="用户" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;" parent="1" vertex="1">
<mxGeometry x="90" y="280" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="k9E8UJ5gUlcifJo20EVi-12" value="删除账户" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="k9E8UJ5gUlcifJo20EVi-2">
<mxGeometry x="40" y="240" width="120" height="40" as="geometry" />
<mxCell id="k9E8UJ5gUlcifJo20EVi-9" value="注册" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="200" y="130" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="k9E8UJ5gUlcifJo20EVi-11" value="修改用户信息" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="200" y="250" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="k9E8UJ5gUlcifJo20EVi-12" value="删除账户" style="ellipse;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="440" y="160" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-2" value="&amp;lt;&amp;lt;include&amp;gt;&amp;gt;" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;dashed=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="k9E8UJ5gUlcifJo20EVi-12" target="k9E8UJ5gUlcifJo20EVi-11">
<mxGeometry x="-0.1" y="-19" relative="1" as="geometry">
<mxPoint x="320" y="230" as="sourcePoint" />
<mxPoint x="440" y="190" as="targetPoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-11" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;dashed=1;" edge="1" parent="1" source="FOyGFu5lgkxIsMJ1ngSE-3">
<mxGeometry relative="1" as="geometry">
<mxPoint x="320" y="270" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-20" value="&amp;lt;&amp;lt;include&amp;gt;&amp;gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="FOyGFu5lgkxIsMJ1ngSE-11">
<mxGeometry x="0.051" relative="1" as="geometry">
<mxPoint x="23" y="16" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-3" value="修改密码" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="440" y="280" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-9" value="&lt;span style=&quot;color: rgb(0, 0, 0); font-family: Helvetica; font-size: 11px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: center; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: nowrap; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;&quot;&gt;&amp;lt;&amp;lt;include&amp;gt;&amp;gt;&lt;/span&gt;" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="FOyGFu5lgkxIsMJ1ngSE-4" target="k9E8UJ5gUlcifJo20EVi-11">
<mxGeometry x="-0.3725" y="-10" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-4" value="修改手机号" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="440" y="220" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-5" value="登录" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="200" y="190" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-16" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="FOyGFu5lgkxIsMJ1ngSE-15" target="k9E8UJ5gUlcifJo20EVi-11">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-17" value="&amp;lt;&amp;lt;include&amp;gt;&amp;gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="FOyGFu5lgkxIsMJ1ngSE-16">
<mxGeometry x="-0.2373" relative="1" as="geometry">
<mxPoint x="-24" y="4" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-15" value="修改用户名" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="440" y="340" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-21" value="查询航班信息" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="200" y="310" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-22" value="为乘客订票" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="200" y="370" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-23" value="支付订单" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="440" y="400" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-25" value="取消订单" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="440" y="460" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-24" value="维护订单信息" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="200" y="430" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-26" value="&amp;lt;&amp;lt;include&amp;gt;&amp;gt;" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="FOyGFu5lgkxIsMJ1ngSE-23" target="FOyGFu5lgkxIsMJ1ngSE-24">
<mxGeometry x="0.2308" y="-9" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-27" value="&amp;lt;&amp;lt;include&amp;gt;&amp;gt;" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="FOyGFu5lgkxIsMJ1ngSE-25" target="FOyGFu5lgkxIsMJ1ngSE-24">
<mxGeometry x="0.2308" y="9" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-32" value="登录" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="440" y="520" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-33" value="修改航班信息" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="440" y="580" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-39" value="&amp;lt;&amp;lt;include&amp;gt;&amp;gt;" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="FOyGFu5lgkxIsMJ1ngSE-36" target="FOyGFu5lgkxIsMJ1ngSE-33">
<mxGeometry x="-0.3333" y="10" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-36" value="删除单次航班" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="200" y="580" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-42" value="&amp;lt;&amp;lt;include&amp;gt;&amp;gt;" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="FOyGFu5lgkxIsMJ1ngSE-37" target="FOyGFu5lgkxIsMJ1ngSE-33">
<mxGeometry x="0.0667" y="13" relative="1" as="geometry">
<mxPoint y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-37" value="修改单次航班信息" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="200" y="520" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-40" value="&amp;lt;&amp;lt;include&amp;gt;&amp;gt;" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;" edge="1" parent="1" source="FOyGFu5lgkxIsMJ1ngSE-38" target="FOyGFu5lgkxIsMJ1ngSE-33">
<mxGeometry x="0.0667" y="-13" relative="1" as="geometry">
<mxPoint y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-38" value="批量添加航班" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="200" y="640" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-34" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="FOyGFu5lgkxIsMJ1ngSE-31" target="FOyGFu5lgkxIsMJ1ngSE-32">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-35" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="FOyGFu5lgkxIsMJ1ngSE-31" target="FOyGFu5lgkxIsMJ1ngSE-33">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="FOyGFu5lgkxIsMJ1ngSE-31" value="管理员" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;" vertex="1" parent="1">
<mxGeometry x="640" y="550" width="30" height="60" as="geometry" />
</mxCell>
</root>
</mxGraphModel>

Binary file not shown.

Binary file not shown.

View File

@ -58,9 +58,20 @@ CREATE PROCEDURE RegisterPassenger(
OUT result_message VARCHAR(255)
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
GET DIAGNOSTICS CONDITION 1 result_message = MESSAGE_TEXT;
END;
START TRANSACTION;
INSERT INTO passengers (ID, `Name`, Phone_number, `Password`)
VALUES (p_id, p_name, p_phone_number, p_password);
SET result_message = '注册成功';
COMMIT;
END;
//
@ -101,6 +112,14 @@ CREATE PROCEDURE ModifyPassengerInfo(
OUT result_message VARCHAR(255)
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
GET DIAGNOSTICS CONDITION 1 result_message = MESSAGE_TEXT;
END;
START TRANSACTION;
IF p_modify_type = 'delete account' THEN
DELETE FROM passengers WHERE ID = p_id;
SET result_message = '删除账户成功';
@ -113,6 +132,8 @@ BEGIN
ELSE
SET result_message = '无效的修改类型';
END IF;
COMMIT;
END;
//

View File

@ -10,7 +10,7 @@ app.secret_key = os.environ.get('SECRET_KEY', 'OPTIONALSECRETKEY')
def get_db():
return pymysql.connect(
host='localhost', user='kejingfan',
password='xxxxxxxx', database='DBLab_7_1',
password='KJF2811879', database='DBLab_7_1',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
@ -34,33 +34,31 @@ def signup():
cursor = db.cursor()
try:
cursor.callproc('RegisterPassenger', (id, name, phone_number, password, "@result_message"))
cursor.fetchall()
cursor.callproc('RegisterPassenger', (id, name, phone_number, password, ""))
result = cursor.fetchall()
cursor.execute("SELECT @_RegisterPassenger_4;")
result_message = cursor.fetchone()['@_RegisterPassenger_4']
result_message = cursor.fetchone()
print(result_message)
flash(result_message)
if type(result_message) is dict:
flash(result_message['@_RegisterPassenger_4'])
else:
flash(result_message[1])
db.commit()
except pymysql.MySQLError as e:
db.rollback()
if e.args[0] == 1644: # SQLSTATE 45000 corresponds to error code 1644
flash("乘客已存在,无法重复注册")
else:
print(e)
flash("数据库异常,注册失败")
finally:
db.close()
return redirect(url_for('index'))
def verify_user(cursor: Cursor, id: str, password: str) -> str:
try:
cursor.callproc('VerifyUser', (id, password, "@verify_status"))
cursor.callproc('VerifyUser', (id, password, ""))
cursor.fetchall()
cursor.execute("SELECT @_VerifyUser_2;")
verify_status = cursor.fetchone()['@_VerifyUser_2']
except pymysql.MySQLError as e:
print(e)
if e.args[0] == 1644: # SQLSTATE 45000 corresponds to error code 1644
return "NO_USER"
return "DB_ERROR"
return verify_status
@ -78,11 +76,16 @@ class ModifyInfo:
self.command = modifyType2command[modifyType]
def get_args(self):
return (self.id, self.command, self.new_password, self.phone_number, "@result_message")
return (self.id, self.command, self.new_password, self.phone_number, "")
def get_ok_message(self, cursor):
cursor.execute("SELECT @_ModifyPassengerInfo_4;")
return cursor.fetchone()['@_ModifyPassengerInfo_4']
result_message = cursor.fetchone()
print(result_message)
if type(result_message) is dict:
return result_message['@_ModifyPassengerInfo_4']
else:
return result_message[1]
@app.route("/modify.html", methods=('GET', 'POST'))
def modify():
@ -105,6 +108,7 @@ def modify():
db.close()
return redirect(url_for('modify'))
elif verify_info == "DB_ERROR":
flash("数据库异常,验证失败")
db.close()
return redirect(url_for('modify'))
@ -116,11 +120,9 @@ def modify():
flash(modifyInfo.get_ok_message(cursor))
except pymysql.MySQLError as e:
db.rollback()
if e.args[0] == 1644: # SQLSTATE 45000 corresponds to error code 1644
flash("用户不存在,无法修改")
else:
print(e)
flash("数据库异常,修改失败")
print(e)
finally:
db.close()
return redirect(url_for('index'))

View File

@ -1 +1,3 @@
SECRET_KEY='ILOVEDATABASETECH' FLASK_APP=main FLASK_ENV=development flask run --host 0.0.0.0 --port 5000
SECRET_KEY='ILOVEDATABASETECH' FLASK_APP=main FLASK_ENV=development flask run \
--host 0.0.0.0 \
--port 8888 # default 5000

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

103218
Courseware/11-并发控制.pdf Normal file

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 it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

124801
Courseware/9-查询优化.pdf Normal file

File diff suppressed because one or more lines are too long

486
Project/README.md Normal file
View File

@ -0,0 +1,486 @@
<h1><center>数据库系统原理课程设计说明书</center></h1>
<div style="text-align: center;">
<div><span style="display: inline-block; width: 65px; text-align: center;">课程名称</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 210px; font-weight: bold; text-align: left;">数据库系统原理</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">学号</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 210px; font-weight: bold; text-align: left;">21281280</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">姓名</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 210px; font-weight: bold; text-align: left;">柯劲帆</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">班级</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 210px; font-weight: bold; text-align: left;">物联网2101班</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">指导老师</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 210px; font-weight: bold; text-align: left;">郝爽</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">修改日期</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 210px; font-weight: bold; text-align: left;">2024年6月19日</span></div>
</div>
---
[TOC]
# 1. 系统规划与可行性分析报告
## 1.1. 系统名称
KJF航班订票系统 (KJF's FlightBooking System)
## 1.2. 组织架构图及相关业务部门
**组织架构图:**
```
航空公司
├── 运营部门
│ ├── 航班管理
│ ├── 机场管理
│ └── 票务管理
├── IT 部门
│ ├── 系统开发
│ ├── 数据库管理
│ ├── 应用支持
│ └── 安全与合规
└── 客户服务部门
├── 客服中心
└── 技术支持
```
**涉及的相关业务部门:**
- **运营部门**:负责航班和机场数据的管理、维护和更新。
- **IT 部门**:负责系统的开发、维护和安全管理,确保系统稳定运行。
- **客户服务部门**:提供客户支持,解决用户在使用系统过程中遇到的问题。
1. 用户使用系统开展业务的场景
**用户(旅客):**
1. **注册**:用户在飞行订票系统的注册页面填写个人信息,完成账号注册。**
2. **查询航班**:登录后,用户在系统中输入出发地、目的地和日期,查询可用航班和座位级别信息。
3. **预订机票**:选定航班和座位级别后,用户通过系统完成支付,生成电子机票,并在行程日期前往机场使用电子机票登机。
**运营部门员工:**
1. **登录**:员工使用分配的账号登录系统。
2. **管理航班和机场信息**:员工进入后台管理界面,添加或修改航班信息(如航班编号、起飞时间、到达时间、座位级别等)和机场信息(如机场名称、所在国家和城市等)。
2. 系统性能指标
- **并发用户数**:支持同时在线用户数量 50,000 人。
- **总用户数**:系统应支持注册用户数量 10,000,000 人。
- **核心业务响应时间**:查询航班和预订机票的响应时间应不超过 1 秒。
- **数据更新频率**航班和机场数据应能在5分钟内更新。
3. 系统的战略地位
飞行订票系统作为航空公司的核心业务系统,其战略地位体现在以下几个方面:
- **客户服务**:提供便捷的在线订票服务,提高客户满意度,增强客户忠诚度。
- **运营效率**:通过电子化管理航班和机场数据,提高航空运营的效率和准确性。
- **市场地位**:占据航空票务市场的主要份额,增强在交通出行领域的市场竞争力。
- **收益**:通过在线售票获得直接收益,同时通过提升运营效率间接节约成本。
4. 投资和运营成本及收益分析
**投资成本:**
- **硬件投入**:服务器、存储设备、网络设备等。
- **软件投入**:数据库软件、应用服务器软件、安全防护软件等。
- **开发投入**:系统开发费用,包括需求分析、设计、编码、测试等。
- **培训费用**:对员工的培训费用。
**运营成本:**
- **维护成本**:系统的日常维护,包括硬件维护、软件升级、数据备份等。
- **人力成本**:技术支持人员、客户服务人员、运营管理人员等的工资。
- **安全成本**:系统安全防护,包括防火墙、入侵检测、防病毒等。
**收益分析:**
- **直接收益**:机票销售收入。
- **间接收益**:提高运营效率,降低人力成本和错误率,提升客户满意度和忠诚度。
5. 技术选型规划
- **数据库**:选用高性能的关系型数据库,如 MySQL、PostgreSQL用于存储用户、机场、航班和机票数据。
- **应用服务器**:采用分布式架构,使用 Java EE、Spring Boot 等技术实现系统的业务逻辑。
- **前端技术**:使用 React、Vue.js 等框架开发用户界面,提供良好的用户体验。
- **安全技术**:部署 SSL 证书,采用 OAuth 2.0 进行用户认证,使用防火墙、入侵检测系统等保护系统安全。
# 2. 系统需求规格说明书
## 2.1. 用例图
![用例图.drawio](images\用例图.drawio.svg)
## 2.2. 泳道图
![泳道图.drawio](images\泳道图.drawio.svg)
## 2.3. 数据结构
![数据结构类图.drawio](images\数据结构类图.drawio.svg)
**数据字典**
- **Passengers 表**
- ID: 身份证号主键18位正则验证。
- Name: 姓名必填长度255。
- Phone_number: 手机号必填长度11正则验证。
- **Users 表**
- Phone_number: 手机号主键长度11正则验证。
- Username: 用户名必填长度255。
- Password: 密码必填长度255。
- **Airports 表**
- ID: 机场三字码主键长度3。
- Name: 机场名称必填唯一长度255。
- City: 城市必填长度255。
- **Flights 表**
- ID: 航班编号主键长度255。
- Airline: 航空公司必填长度255。
- Departure_airport: 出发机场必填长度3外键。
- Arrival_airport: 到达机场必填长度3外键。
- Departure_time: 出发时间,必填,日期时间格式。
- Arrival_time: 到达时间,必填,日期时间格式。
- First_class_seats_remaining: 头等舱剩余座位数,必填,整数。
- Business_class_seats_remaining: 商务舱剩余座位数,必填,整数。
- Economy_class_seats_remaining: 经济舱剩余座位数,必填,整数。
- First_class_price: 头等舱票价,必填,数值格式。
- Business_class_price: 商务舱票价,必填,数值格式。
- Economy_class_price: 经济舱票价,必填,数值格式。
- Status: 航班状态必填长度255。
- **Orders 表**
- ID: 订单编号,自增,主键。
- Order_time: 订单时间,必填,日期时间格式。
- Paid: 是否支付,必填,布尔值。
- User_phone_number: 用户手机号必填长度11外键。
- **Tickets 表**
- ID: 机票编号,自增,主键。
- Price: 票价,必填,数值格式。
- FlightID: 航班编号必填长度255外键。
- Seat_class: 座位等级必填长度255。
- PassengerID: 乘客身份证号必填长度18外键。
- OrderID: 订单编号,必填,整数,外键。
## 2.4. 数据流图
![数据流图.drawio](images\数据流图.drawio.svg)
## 2.5. 非功能性需求
**业务处理性能**
- **响应时间**: 系统必须在用户请求操作后的2秒内做出响应。
- **并发处理能力**: 系统需支持至少1000个并发用户。
**安全性**
- **数据加密**: 所有传输的隐私数据必须使用密文传输。
- **身份验证**: 系统必须实现多因素身份验证MFA
- **权限控制**: 不同用户角色拥有不同的操作权限,确保数据的访问安全。
**完整性**
- **数据备份**: 系统需实现每日数据备份,防止数据丢失。
- **数据校验**: 系统在数据录入时需进行校验,确保数据的准确性和一致性。
# 3. 系统详细设计说明书
## 3.1. 系统功能概述
系统主要分为两个部分:管理员和用户。
管理员主要维护航班信息。而用户可以订票,在数据库中新增乘客、订单和机票。
## 3.2. 系统功能模块结构
### 3.2.1. 前端功能
对于管理员,前端提供:登录、查询航班信息、修改航班信息(包括删除航班、修改余票额、修改票价、修改航班状态)、批量导入新航班功能。
对于用户,前端提供:注册、登录、修改用户信息(包括删除账号、修改手机号、修改密码、修改用户名)、查询航班、下订单、查看订单列表、支付订单、删除订单。
### 3.2.2. WEB服务端
WEB服务端提供前端功能对应的接口同时与数据库进行交互。
### 3.2.3. 数据库端
#### 3.2.3.1. 关系
![E-R图.drawio](images\E-R图.drawio.svg)
#### 3.2.3.2. 触发器
设计该触发器,当用户删除订单时,在正式将机票记录删除前,触发将机票对应余座数更新操作。
```mysql
CREATE TRIGGER restore_seats
BEFORE DELETE ON Tickets
FOR EACH ROW
BEGIN
IF OLD.Seat_class = 'First Class' THEN
UPDATE Flights
SET First_class_seats_remaining = First_class_seats_remaining + 1
WHERE ID = OLD.FlightID;
ELSEIF OLD.Seat_class = 'Business Class' THEN
UPDATE Flights
SET Business_class_seats_remaining = Business_class_seats_remaining + 1
WHERE ID = OLD.FlightID;
ELSEIF OLD.Seat_class = 'Economy Class' THEN
UPDATE Flights
SET Economy_class_seats_remaining = Economy_class_seats_remaining + 1
WHERE ID = OLD.FlightID;
END IF;
END //
```
#### 3.2.3.3. 存储过程
创建该存储过程,将用户下订单后的一系列操作(更新乘客信息、更新余座数、插入机票信息)封装为一个存储过程。
```mysql
CREATE PROCEDURE AddPassengerAndTicket(
IN p_passenger_id VARCHAR(18),
IN p_name VARCHAR(255),
IN p_phone_number BIGINT,
IN p_seat_class VARCHAR(255),
IN p_flight_id VARCHAR(255),
IN p_price DECIMAL(7, 2),
IN p_order_id INT
)
BEGIN
-- 插入或更新乘客信息
INSERT INTO Passengers (ID, Name, Phone_number)
VALUES (p_passenger_id, p_name, p_phone_number)
ON DUPLICATE KEY UPDATE Name=VALUES(Name), Phone_number=VALUES(Phone_number);
-- 更新航班座位数
IF p_seat_class = 'First Class' THEN
UPDATE Flights
SET First_class_seats_remaining = First_class_seats_remaining - 1
WHERE ID = p_flight_id;
ELSEIF p_seat_class = 'Business Class' THEN
UPDATE Flights
SET Business_class_seats_remaining = Business_class_seats_remaining - 1
WHERE ID = p_flight_id;
ELSEIF p_seat_class = 'Economy Class' THEN
UPDATE Flights
SET Economy_class_seats_remaining = Economy_class_seats_remaining - 1
WHERE ID = p_flight_id;
END IF;
-- 插入机票信息
INSERT INTO Tickets (Price, FlightID, Seat_class, PassengerID, OrderID)
VALUES (p_price, p_flight_id, p_seat_class, p_passenger_id, p_order_id);
END //
```
## 3.3. 系统界面设计
### 3.3.1. 登陆界面设计
![登录界面](images\登录界面.png)
该页面设计了一个登录框,并将一个轮播图组建作为背景。
### 3.3.2. 主页页面设计
![主页界面](images\主页界面.png)
主页设计包括一个导航栏,导航栏包含跳转至主页和订单列表页的超链接。
其下面是一个轮播图组建作为背景。
再下面是搜索页面的入口可以输入航班查询条件跳转到查阅页面。出发日期默认是当前日期的下一天出发地和目的地默认为北京和上海乘客人数默认为1。
### 3.3.3. 查询页面设计
![查询界面](images\查询界面.png)
显示查询结果。鼠标悬停在列表行上,列表行会高亮显示。点击列表行,可以跳转至订票页面。
### 3.3.4. 订票页面设计
![订票界面](images\订票界面.png)
### 3.3.5. 订单页面设计
![订单界面](images\订单界面.png)
### 3.3.6. 订单列表页面设计
![订单列表界面](images\订单列表界面.png)
## 3.4. 系统物理模型
表如下:
- Passengers(<u>ID</u>, Name, Phone_number)
- Users(<u>Phone_number</u>, Username, Password)
- Airports(<u>ID</u>, Name, City)
- Flights(<u>ID</u>, Airline, Departure_airport, Arrival_airport, Departure_time, Arrival_time, First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining, First_class_price, Business_class_price, Economy_class_price, Status)
- Orders(<u>ID</u>, Order_time, Paid, User_phone_number)
- Tickets(<u>ID</u>, Price, FlightID, Seat_class, PassengerID, OrderID)
其索引为:
- Flights(Departure_airport) REFERENCES Airports(ID)
- Flights(Arrival_airport) REFERENCES Airports(ID)
- Orders(User_phone_number) REFERENCES Users(Phone_number)
- Tickets(FlightID) REFERENCES Flights(ID)
- Tickets(PassengerID) REFERENCES Passengers(ID)
- Tickets(OrderID) REFERENCES Orders(ID)
无视图设计。
## 3.5. 系统安全体系设计
对于用户管理与控制,采用管理员控制航班信息,用户控制订票信息的设计方式。
对于存储与恢复,采用定时自动将数据库导出备份的方式。
## 3.6. 系统运行环境设计与部署结构
本系统使用Python Flask的运行环境。
部署结构如下:
```
.
├── Manager
│ ├── func
│ │ ├── config.py # 配置文件
│ │ ├── index.py # 主页后端
│ │ └── login.py # 登录后端
│ ├── main.py
│ ├── static
│ │ ├── css # 各页面CSS文件
│ │ │ ├── index.css
│ │ │ └── login.css
│ │ └── js # 各页面JS文件
│ │ ├── index.js
│ │ └── login.js
│ └── templates # 各页面HTML文件
│ ├── index.html
│ └── login.html
├── Service
│ ├── func
│ │ ├── __init__.py
│ │ ├── book.py # 订票后端
│ │ ├── cancel_order.py # 取消订单后端
│ │ ├── config.py # 配置文件
│ │ ├── index.py # 主页后端
│ │ ├── login.py # 登录后端
│ │ ├── modify.py # 修改用户信息后端
│ │ ├── order.py # 订单详情后端
│ │ ├── order_list.py # 订单列表后端
│ │ ├── pay_confirm.py # 支付后端
│ │ ├── search.py # 查询后端
│ │ ├── signup.py # 注册后端
│ │ └── utils.py # 工具函数
│ ├── main.py
│ ├── static
│ │ ├── css # 各页面CSS文件
│ │ │ ├── book.css
│ │ │ ├── index.css
│ │ │ ├── login.css
│ │ │ ├── modify.css
│ │ │ ├── order.css
│ │ │ ├── order_list.css
│ │ │ ├── search.css
│ │ │ └── signup.css
│ │ └── js # 各页面JS文件
│ │ ├── checkInfo.js
│ │ ├── index.js
│ │ ├── login.js
│ │ ├── modify.js
│ │ ├── search.js
│ │ ├── signup.js
│ │ └── slideshow.js
│ └── templates # 各页面HTML文件
│ ├── book.html
│ ├── index.html
│ ├── login.html
│ ├── modify.html
│ ├── order.html
│ ├── order_list.html
│ ├── search.html
│ └── signup.html
├── data_source # 数据
├── airports
│ ├── airports.csv # 机场信息
│ ├── airports.sql # 机场信息插入sql
│ ├── make_data.py # 将raw数据转换为csv和sql
│ └── raw.txt # 机场信息原始文本
├── db_user.sql # 创建用户sql
├── flights
│ ├── add.csv # 批量新建航班样例
│ └── flights.sql # 航班列表初始化sql
├── init_manager_db.sql # 新建管理员数据库sql
└── init_service_db.sql # 新建用户数据库sql
```
# 4. 用户安装与使用手册
进入项目文件夹后,安装环境依赖:
```sh
pip install -r requirements.txt
```
然后初始化数据库:
```mysql
mysql> source src/data_source/init_service_db.sql -- 新建用户数据库
mysql> source src/data_source/init_manager_db.sql -- 新建管理员数据库
mysql> source src/data_source/db_user.sql -- 创建用户
mysql> source src/data_source/airports/airports.sql -- 创建机场表
mysql> source src/data_source/flights/flights.sql -- 创建初始航班表
```
随后进入Manger并启动管理员服务
```sh
cd src/Manager && python main.py
```
在另一命令行窗口进入Service并启动用户服务
```sh
cd src/Service && python main.py
```
最终,分别在浏览器访问主机 `IP``8889``8888` 端口操作管理员和服务端。
# 5. 所有源代码与脚本
见本项目的 `src` 文件夹。
# 6. 系统设计总结
通过本次课程设计,我完成了从需求分析、系统设计、数据库设计、功能实现到测试和部署的全过程。这不仅加深了我对数据库系统原理的理解,也提升了我在实际项目中应用这些原理的能力。虽然过程中遇到了一些挑战,但通过不断学习,我最终成功地完成了项目。
本系统的成功设计和实现为我今后在数据库系统和软件开发领域的进一步学习和实践打下了坚实的基础。我也认识到,在实际开发中,系统的可扩展性和维护性是至关重要的,这需要在设计初期就进行充分的考虑和规划。
# 7. 课程总结与建议
本学期的《数据库系统原理》课程,通过理论学习与实践操作相结合的方式,使我对数据库系统的设计、管理与应用有了深刻的理解和掌握。在课程中,我不仅学习了数据库的基本原理和操作,还通过课程设计项目,实际应用这些知识,构建了一个完整的航班订票系统。以下是我在本课程中的几点总结:
1. **理论与实践并重**
- 通过课堂教学我系统学习了数据库的基本概念、数据库设计理论、SQL语言以及事务管理等核心知识。
- 课程设计项目则提供了实践平台,让我将理论知识应用于实际开发,从需求分析、系统设计、数据库设计到编码实现与测试,整个过程对知识的理解更加深入。
2. **系统设计能力提升**
- 课程设计要求我从零开始设计并实现一个数据库系统,这大大提升了我的系统设计能力。我学会了如何进行需求分析、如何设计数据库表结构、如何进行数据建模等关键技能。
- 特别是在处理复杂业务逻辑、确保数据一致性与完整性、优化数据库性能等方面,我掌握了许多实用的方法和技巧。
3. **问题解决能力的提升**
- 在项目开发过程中,我遇到了许多技术难题,如数据库设计中的各种约束实现、复杂查询的优化、系统的安全性设计等。通过查阅资料,我逐一解决了这些问题,大大提升了我的独立解决问题的能力。
建议:本门课的课设负担较重,希望可以多人合作完成。

View File

@ -1,10 +0,0 @@
DROP TABLE IF EXISTS passengers;
CREATE TABLE passengers (
ID BIGINT PRIMARY KEY,
`Name` VARCHAR (255) NOT NULL,
Phone_number BIGINT UNIQUE NOT NULL,
`Password` VARCHAR (255) NOT NULL,
CHECK (ID REGEXP '^\\d{18}$'),
CHECK (Phone_number REGEXP '^\\d{11}$')
);

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 75 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 77 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -1,17 +0,0 @@
import pymysql
db = pymysql.connect(
host='localhost', user='kejingfan',
password='KJF2811879', database='TESTDB'
)
cursor = db.cursor()
with open('db.sql', 'r') as f:
sql_commands = f.read().split(';')
for command in sql_commands:
if command.strip(): # 确保不执行空命令
cursor.execute(command)
db.close()

View File

@ -1,179 +0,0 @@
from flask import Flask, render_template, request, flash, redirect, url_for
import pymysql
from pymysql.cursors import Cursor
import os
from typing import Dict
app = Flask(__name__)
app.secret_key = os.environ.get('SECRET_KEY', 'OPTIONALSECRETKEY')
def get_db():
return pymysql.connect(
host='localhost', user='kejingfan',
password='KJF2811879', database='TESTDB'
)
@app.route("/")
def index():
return render_template("index.html")
@app.route("/signup.html", methods=('GET', 'POST'))
def signup():
if request.method == 'GET':
return render_template('signup.html')
if request.method == 'POST':
id = request.form['cardCode']
name = request.form['name']
phone_number = request.form['mobileNo']
password = request.form['encryptedPassword']
db = get_db()
cursor = db.cursor()
# 检查已有用户
sql = """
SELECT COUNT(*) FROM passengers \
WHERE ID = %s;
"""
try:
cursor.execute(sql, (id,))
id_exist = cursor.fetchall()[0][0]
except Exception as e:
flash("数据库异常,查询失败")
print(e)
return redirect(url_for('signup'))
if (id_exist != 0):
flash("您已注册过,请勿重复注册")
db.close()
return redirect(url_for('index'))
# 插入
sql = '''
INSERT INTO passengers (ID, `Name`, Phone_number, `Password`) \
VALUES (%s, %s, %s, %s); \
'''
try:
cursor.execute(sql, (id, name, phone_number, password))
db.commit()
flash("注册成功")
except Exception as e:
db.rollback()
print(e)
flash("数据库异常,注册失败")
db.close()
return redirect(url_for('index'))
def verify_user(cursor:Cursor, id:str, password:str) -> str:
# 检查已有用户
sql = """
SELECT COUNT(*) FROM passengers \
WHERE ID = %s;
"""
try:
cursor.execute(sql, (id,))
id_exist = cursor.fetchall()[0][0]
except Exception as e:
flash("数据库异常,查询失败")
print(e)
return redirect(url_for('signup'))
if (id_exist == 0):
return "NO_USER"
# 检查密码
sql = """
SELECT `Password` FROM passengers \
WHERE ID = %s;
"""
try:
cursor.execute(sql, (id,))
record_password = cursor.fetchall()[0][0]
except Exception as e:
flash("数据库异常,查询失败")
print(e)
return redirect(url_for('modify'))
if (record_password != password):
return "WRONG_PASSWORD"
return "USER_VERIFIED"
class ModifyInfo:
def __init__(self, form:Dict[str, str]):
self.id = form['cardCode']
modifyType = form['modifyType']
self.new_password = form['encryptedNewPassword']
self.phone_number = form['mobileNo']
modifyType2command = {
'1':'delete account',
'2':'modify Password',
'3':'modify Phone_Number'
}
self.sql_dict = {
'delete account': 'DELETE FROM passengers WHERE ID = %s;',
'modify Password': 'UPDATE passengers SET `Password` = %s WHERE ID = %s;',
'modify Phone_Number': 'UPDATE passengers SET Phone_number = %s WHERE ID = %s;'
}
self.sql_args_dict = {
'delete account': (self.id,),
'modify Password': (self.new_password, self.id),
'modify Phone_Number': (self.phone_number, self.id)
}
self.ok_message_dict = {
'delete account': "删除账户成功",
'modify Password': "修改密码成功",
'modify Phone_Number': "修改手机号成功"
}
self.fail_message_dict = {
'delete account': "数据库异常,删除账户失败",
'modify Password': "数据库异常,修改密码失败",
'modify Phone_Number': "数据库异常,修改手机号失败"
}
self.command = modifyType2command[modifyType]
def get_sql(self):
return self.sql_dict[self.command]
def get_args(self):
return self.sql_args_dict[self.command]
def get_ok_message(self):
return self.ok_message_dict[self.command]
def get_fail_message(self):
return self.fail_message_dict[self.command]
@app.route("/modify.html", methods=('GET', 'POST'))
def modify():
if request.method == 'GET':
return render_template('modify.html')
if request.method == 'POST':
id = request.form['cardCode']
password = request.form['encryptedPassword']
db = get_db()
cursor = db.cursor()
verify_info = verify_user(cursor, id, password)
if (verify_info == "NO_USER"):
flash("您未注册过,无法修改账号")
db.close()
return redirect(url_for('signup'))
elif (verify_info == "WRONG_PASSWORD"):
flash("密码错误")
db.close()
return redirect(url_for('modify'))
modifyInfo = ModifyInfo(request.form)
try:
cursor.execute(modifyInfo.get_sql(), modifyInfo.get_args())
db.commit()
flash(modifyInfo.get_ok_message())
except Exception as e:
db.rollback()
print(e)
flash(modifyInfo.get_fail_message())
db.close()
return redirect(url_for('index'))

View File

@ -1 +0,0 @@
SECRET_KEY='ILOVEDATABASETECH' FLASK_APP=main FLASK_ENV=development flask run

View File

@ -0,0 +1,16 @@
db_service = {
'host':'localhost',
'user':'managerAgent',
'password':'password123',
'database':'ServiceDatabase'
}
db_manager = {
'host':'localhost',
'user':'managerAgent',
'password':'password123',
'database':'ManagerDatabase'
}
SECRET_KEY = 'ILOVEDATABASETECH'

View File

@ -0,0 +1,143 @@
from flask import render_template, request, g, redirect, url_for, session, jsonify
from .config import db_service
import pymysql
import csv
import io
def index():
if request.method == 'GET':
if not g.user:
return redirect(url_for("login"))
flightID = request.args.get('flightID')
if flightID:
conn = pymysql.connect(**db_service)
cursor = conn.cursor(pymysql.cursors.DictCursor)
search_sql = """SELECT * FROM Flights WHERE ID = %s"""
cursor.execute(search_sql, (flightID, ))
flight = cursor.fetchone()
cursor.close()
conn.close()
return render_template(
'index.html',
flight=flight,
username=g.user
)
else:
return render_template('index.html', username=g.user)
def modify():
if request.method == 'POST':
flight_id = request.form.get('flightID')
first_class_change = int(request.form.get('first_class_change', 0))
business_class_change = int(request.form.get('business_class_change', 0))
economy_class_change = int(request.form.get('economy_class_change', 0))
first_class_price = float(request.form.get('first_class_price', 0))
business_class_price = float(request.form.get('business_class_price', 0))
economy_class_price = float(request.form.get('economy_class_price', 0))
status = request.form.get('status', '未知')
conn = pymysql.connect(**db_service)
cursor = conn.cursor(pymysql.cursors.DictCursor)
try:
# 查询当前座位数
cursor.execute("SELECT First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining FROM Flights WHERE ID = %s", (flight_id,))
current_seats = cursor.fetchone()
new_first_class_seats = current_seats['First_class_seats_remaining'] + first_class_change
new_business_class_seats = current_seats['Business_class_seats_remaining'] + business_class_change
new_economy_class_seats = current_seats['Economy_class_seats_remaining'] + economy_class_change
# 检查余座数是否为负值
if new_first_class_seats < 0 or new_business_class_seats < 0 or new_economy_class_seats < 0:
flash('座位变化后余座数不能为负值', 'error')
return redirect(url_for('index'))
# 更新座位数和价格
update_sql = """
UPDATE Flights
SET First_class_seats_remaining = %s, Business_class_seats_remaining = %s, Economy_class_seats_remaining = %s,
First_class_price = %s, Business_class_price = %s, Economy_class_price = %s, Status = %s
WHERE ID = %s
"""
cursor.execute(update_sql, (new_first_class_seats, new_business_class_seats, new_economy_class_seats,
first_class_price, business_class_price, economy_class_price, status, flight_id))
conn.commit()
flash('座位数、价格和状态更新成功', 'success')
except Exception as e:
print(e)
conn.rollback()
flash(f'数据库错误:{e}', 'error')
finally:
cursor.close()
conn.close()
return redirect(url_for('index'))
def delete_flight():
if request.method == 'DELETE':
flight_id = request.args.get('flightID')
conn = pymysql.connect(**db_service)
cursor = conn.cursor()
try:
delete_sql = "DELETE FROM Flights WHERE ID = %s"
cursor.execute(delete_sql, (flight_id,))
conn.commit()
except Exception as e:
print(e)
conn.rollback()
return jsonify({'message': '数据库错误,请稍后再试', 'success': False}), 500
finally:
cursor.close()
conn.close()
return jsonify({'message': '航班删除成功', 'success': True}), 200
from flask import flash, redirect, url_for, jsonify, request
import pymysql
import csv
import io
from .config import db_service
def upload_csv():
if request.method == 'POST':
file = request.files['file']
if not file:
flash('没有文件上传', 'error')
return redirect(url_for('index'))
conn = pymysql.connect(**db_service)
cursor = conn.cursor()
try:
stream = io.StringIO(file.stream.read().decode("UTF8"), newline=None)
csv_input = csv.reader(stream)
next(csv_input) # 跳过表头
for row in csv_input:
cursor.execute("""
INSERT INTO Flights (ID, Airline, Departure_airport, Arrival_airport, Departure_time, Arrival_time,
First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining,
First_class_price, Business_class_price, Economy_class_price, Status)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
""", row)
conn.commit()
flash('航班批量添加成功', 'success')
except Exception as e:
print(e)
conn.rollback()
flash(f'文件处理错误:{e}', 'error')
finally:
cursor.close()
conn.close()
return redirect(url_for('index'))

View File

@ -0,0 +1,39 @@
from flask import request, jsonify, session, url_for, render_template, redirect
from .config import db_manager
import pymysql
def connect(managerID, encrypted_password):
conn = pymysql.connect(**db_manager)
cursor = conn.cursor(pymysql.cursors.DictCursor)
args = (managerID, encrypted_password)
verify_sql = "SELECT COUNT(*) FROM Managers WHERE ID = %s AND `Password` = %s;"
cursor.execute(verify_sql, args)
verified = cursor.fetchone()
cursor.close()
conn.close()
return verified['COUNT(*)'] > 0
def login():
if request.method == 'GET':
return render_template('login.html')
if request.method == 'POST':
session.pop('user_id', None)
managerID = request.json.get('username')
encrypted_password = request.json.get('password')
try:
user = connect(managerID, encrypted_password)
if not user:
return jsonify({'message': '账号或密码错误'}), 401
session['user_id'] = managerID
session.modified = True
return jsonify({'redirect': url_for('index')})
except Exception as e:
print(e)
return jsonify({'message': '数据库错误,请稍后再试'}), 500
def logout():
session.clear()
session.pop('user_id', None)
return redirect(url_for('login'))

View File

@ -0,0 +1,57 @@
from flask import Flask, redirect, url_for, session, g
from flask_httpauth import HTTPTokenAuth
from flask_cors import CORS
from func.config import SECRET_KEY
import func.login
import func.index
app = Flask(__name__)
app.config["SECRET_KEY"] = SECRET_KEY
app.config["JSON_AS_ASCII"] = False
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SECURE'] = False
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
CORS(app, supports_credentials=True)
auth = HTTPTokenAuth(scheme='Bearer')
@app.before_request
def before_request():
g.user = None
if 'user_id' in session:
g.user = session.get('user_id')
@app.route("/")
def home():
return redirect(url_for('index'))
@app.route("/index", methods=['GET'])
def index():
return func.index.index()
@app.route("/modify", methods=['POST'])
def modify():
return func.index.modify()
@app.route("/login", methods=['GET', 'POST'])
def login():
return func.login.login()
@app.route('/logout')
def logout():
return func.login.logout()
@app.route("/delete_flight", methods=['DELETE'])
def delete_flight():
return func.index.delete_flight()
@app.route("/upload_csv", methods=['POST'])
def upload_csv():
return func.index.upload_csv()
if __name__ == "__main__":
app.run(
host="0.0.0.0",
port=8889,
debug=True
)

View File

@ -0,0 +1,206 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px;
width: 100%;
position: fixed;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.logo {
font-size: 24px;
font-weight: bold;
margin-left: 20px;
}
.nav-buttons {
display: flex;
gap: 20px;
}
.nav-buttons a {
color: white;
text-decoration: none;
font-size: 16px;
padding: 10px;
border-radius: 5px;
}
.nav-buttons a:hover {
background-color: #155a8c;
}
.user-menu {
position: relative;
display: flex;
align-items: center;
margin-right: 20px;
}
.user-menu span {
margin-right: 10px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropbtn {
background-color: rgba(28, 108, 178, 0.9);
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
right: 0;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #f1f1f1;
}
.dropdown:hover .dropdown-content {
display: block;
}
main {
flex: 1;
width: 80%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
h2 {
text-align: center;
color: #1c6cb2;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table, th, td {
border: 1px solid #ccc;
}
th, td {
padding: 10px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
.flight-row {
transition: transform 0.3s ease, box-shadow 0.3s ease, border-radius 0.3s ease;
}
.flight-row:hover {
transform: scale(1.02);
box-shadow: 0 0 10px rgba(28, 108, 178, 0.5);
border-radius: 10px;
}
.flight-info th, .flight-info td {
padding: 10px;
border: 1px solid #ccc;
}
.no-results {
text-align: center;
color: red;
font-size: 18px;
margin-top: 20px;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
position: relative;
margin-top: auto;
}
.content {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
border-radius: 10px;
text-align: center;
width: 80%;
margin: 20px auto;
position: relative;
}
.form-group {
margin-bottom: 15px;
text-align: left;
}
.form-group label {
display: block;
margin-bottom: 5px;
}
.form-group input {
width: 100%;
padding: 8px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 5px;
}
.btn {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
cursor: pointer;
}
.btn:hover {
background-color: #155a8c;
}

View File

@ -0,0 +1,93 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #ffffff;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
}
header {
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px 0;
text-align: center;
width: 100%;
}
main {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
position: relative;
}
.content {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
border-radius: 10px;
text-align: center;
position: absolute;
}
h2 {
color: #1c6cb2;
}
.login-form {
margin-bottom: 20px;
}
.login-form input {
display: block;
margin: 10px auto;
padding: 10px;
font-size: 16px;
width: 80%;
max-width: 300px;
margin-bottom: 20px; /* 增加外边距 */
}
.buttons {
display: flex;
justify-content: center;
gap: 10px;
}
.login-form button,
.btn {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
line-height: 20px;
cursor: pointer;
}
.login-form button:hover,
.btn:hover {
background-color: #155a8c;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
}
.error-message {
color: red;
font-size: 12px;
text-align: left;
margin-top: -10px;
margin-bottom: 10px;
}

View File

@ -0,0 +1,15 @@
function increment() {
var passengers = document.getElementById("passengers");
var value = parseInt(passengers.value, 10);
if (value < 50) {
passengers.value = value + 1;
}
}
function decrement() {
var passengers = document.getElementById("passengers");
var value = parseInt(passengers.value, 10);
if (value > 1) {
passengers.value = value - 1;
}
}

View File

@ -0,0 +1,80 @@
window.onload = function() {
autoLogin();
};
var checkInfo = {};
checkInfo.checkUsername = function() {
let username = document.getElementById('username').value;
if (username.length < 1) {
document.getElementById('usernameError').textContent = '用户名不能为空';
return false;
}
document.getElementById('usernameError').textContent = '';
return true;
}
checkInfo.checkPassword = function() {
let password = document.getElementById('password').value;
let regexPassword = /^[A-Za-z0-9\W_]{6,20}$/;
if (!regexPassword.test(password)) {
document.getElementById('loginError').textContent = "密码须为长度为6-20位字母、数字或符号";
return false;
}
document.getElementById('loginError').textContent = '';
return true;
}
function submitForm() {
if (checkInfo.checkUsername() && checkInfo.checkPassword()) {
document.getElementById('encryptedPassword').value = md5(
document.getElementById('password').value
);
login();
return true;
}
return false;
}
// 登录函数
async function login() {
const username = document.getElementById('username').value;
const encryptedPassword = document.getElementById('encryptedPassword').value;
try {
const response = await fetch('/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ username: username, password: encryptedPassword }),
credentials: 'include' // 确保请求包含凭据cookies
});
const data = await response.json();
if (response.ok) {
alert('登录成功');
// 自动跳转到主页
window.location.href = data.redirect;
} else {
document.getElementById('loginError').textContent = data.message;
}
} catch (error) {
alert('数据库错误,请稍后再试');
}
}
// 自动登录函数
async function autoLogin() {
const token = localStorage.getItem('token');
if (token) {
const response = await fetch('/index', {
headers: {
'Authorization': 'Bearer ' + token
}
});
if (response.ok) {
document.getElementById('content').innerText = '已自动登录';
} else {
document.getElementById('content').innerText = '自动登录失败';
}
}
}

View File

@ -0,0 +1,219 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KJF航班订票</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/index.css') }}">
<script>
window.onload = function() {
{% with messages = get_flashed_messages() %}
{% if messages %}
var message = "";
{% for msg in messages %}
message += "{{ msg }}\n";
{% endfor %}
alert(message);
{% endif %}
{% endwith %}
};
</script>
</head>
<body>
<header>
<div class="header-content">
<div class="logo">KJF航班订票</div>
<div class="nav-buttons">
<a href="{{ url_for('index') }}">首页</a>
</div>
<div class="user-menu">
<span>{{ username }}</span>
<div class="dropdown">
<button class="dropbtn"></button>
<div class="dropdown-content">
<a href="{{ url_for('logout') }}">退出登录</a>
</div>
</div>
</div>
</div>
</header>
<main>
<div class="content">
<form method="get" action="{{ url_for('index') }}">
<div class="form-group">
<label for="flightID">航班号:</label>
<input type="text" id="flightID" name="flightID" placeholder="请输入航班号">
</div>
<button type="submit" class="btn">查询</button>
</form>
{% if flight %}
<div class="flight-info">
<table>
<thead>
<tr>
<th>航班号</th>
<th>航空公司</th>
<th>出发机场</th>
<th>到达机场</th>
<th>出发时间</th>
<th>到达时间</th>
<th>头等舱剩余座位</th>
<th>商务舱剩余座位</th>
<th>经济舱剩余座位</th>
<th>头等舱价格</th>
<th>商务舱价格</th>
<th>经济舱价格</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<tr class="flight-row">
<td>{{ flight.ID }}</td>
<td>{{ flight.Airline }}</td>
<td>{{ flight.Departure_airport }}</td>
<td>{{ flight.Arrival_airport }}</td>
<td>{{ flight.Departure_time }}</td>
<td>{{ flight.Arrival_time }}</td>
<td id="first-class-seats">{{ flight.First_class_seats_remaining }}</td>
<td id="business-class-seats">{{ flight.Business_class_seats_remaining }}</td>
<td id="economy-class-seats">{{ flight.Economy_class_seats_remaining }}</td>
<td id="first-class-price">{{ flight.First_class_price }}</td>
<td id="business-class-price">{{ flight.Business_class_price }}</td>
<td id="economy-class-price">{{ flight.Economy_class_price }}</td>
<td>{{ flight.Status }}</td>
</tr>
</tbody>
</table>
</div>
<div class="modify-seats">
<h3>修改座位数、价格及状态</h3>
<form id="modify-form" method="post" action="{{ url_for('modify') }}" onsubmit="return validateSeatChange()">
<input type="hidden" name="flightID" value="{{ flight.ID }}">
<div class="form-group">
<label for="first_class_change">头等舱座位变化:</label>
<div class="passenger-input">
<button type="button" onclick="decrement('first_class_change', {{ flight.First_class_seats_remaining }})">-</button>
<input type="number" id="first_class_change" name="first_class_change" placeholder="输入变化数量" value="0">
<button type="button" onclick="increment('first_class_change')">+</button>
</div>
</div>
<div class="form-group">
<label for="business_class_change">商务舱座位变化:</label>
<div class="passenger-input">
<button type="button" onclick="decrement('business_class_change', {{ flight.Business_class_seats_remaining }})">-</button>
<input type="number" id="business_class_change" name="business_class_change" placeholder="输入变化数量" value="0">
<button type="button" onclick="increment('business_class_change')">+</button>
</div>
</div>
<div class="form-group">
<label for="economy_class_change">经济舱座位变化:</label>
<div class="passenger-input">
<button type="button" onclick="decrement('economy_class_change', {{ flight.Economy_class_seats_remaining }})">-</button>
<input type="number" id="economy_class_change" name="economy_class_change" placeholder="输入变化数量" value="0">
<button type="button" onclick="increment('economy_class_change')">+</button>
</div>
</div>
<div class="form-group">
<label for="first_class_price">头等舱价格:</label>
<input type="number" step="0.01" id="first_class_price" name="first_class_price" placeholder="输入价格" value="{{ flight.First_class_price }}" oninput="validatePrice(this)">
</div>
<div class="form-group">
<label for="business_class_price">商务舱价格:</label>
<input type="number" step="0.01" id="business_class_price" name="business_class_price" placeholder="输入价格" value="{{ flight.Business_class_price }}" oninput="validatePrice(this)">
</div>
<div class="form-group">
<label for="economy_class_price">经济舱价格:</label>
<input type="number" step="0.01" id="economy_class_price" name="economy_class_price" placeholder="输入价格" value="{{ flight.Economy_class_price }}" oninput="validatePrice(this)">
</div>
<div class="form-group">
<label for="status">航班状态:</label>
<select id="status" name="status">
<option value="候机中" {% if flight.Status == '候机中' %}selected{% endif %}>候机中</option>
<option value="延误" {% if flight.Status == '延误' %}selected{% endif %}>延误</option>
<option value="已起飞" {% if flight.Status == '已起飞' %}selected{% endif %}>已起飞</option>
<option value="已降落" {% if flight.Status == '已降落' %}selected{% endif %}>已降落</option>
<option value="开始检票" {% if flight.Status == '开始检票' %}selected{% endif %}>开始检票</option>
<option value="未知" {% if flight.Status == '未知' %}selected{% endif %}>未知</option>
</select>
</div>
<button type="submit" class="btn">提交</button>
</form>
</div>
<div class="flight-actions">
<h3>其他操作</h3>
<button class="btn" onclick="deleteFlight('{{ flight.ID }}')">删除航班</button>
<form id="upload-csv-form" method="post" action="{{ url_for('upload_csv') }}" enctype="multipart/form-data">
<input type="file" name="file" accept=".csv" required>
<button type="submit" class="btn">批量添加航班</button>
</form>
</div>
{% endif %}
</div>
</main>
<footer>
<p>&copy; 2024 KJF航班订票. 保留所有权利。</p>
</footer>
<script>
function validateSeatChange() {
const firstClassSeats = parseInt(document.getElementById('first-class-seats').textContent);
const businessClassSeats = parseInt(document.getElementById('business-class-seats').textContent);
const economyClassSeats = parseInt(document.getElementById('economy-class-seats').textContent);
const firstClassChange = parseInt(document.getElementById('first_class_change').value || 0);
const businessClassChange = parseInt(document.getElementById('business_class_change').value || 0);
const economyClassChange = parseInt(document.getElementById('economy_class_change').value || 0);
const newFirstClassSeats = firstClassSeats + firstClassChange;
const newBusinessClassSeats = businessClassSeats + businessClassChange;
const newEconomyClassSeats = economyClassSeats + economyClassChange;
if (newFirstClassSeats < 0 || newBusinessClassSeats < 0 || newEconomyClassSeats < 0) {
alert('座位变化后余座数不能为负值');
return false;
}
return true;
}
function validatePrice(input) {
const value = parseFloat(input.value);
if (isNaN(value) || value < 0) {
input.setCustomValidity('价格不能为负值且仅支持小数点后2位');
} else {
input.setCustomValidity('');
}
}
function increment(inputId) {
var inputElement = document.getElementById(inputId);
var value = parseInt(inputElement.value, 10);
inputElement.value = value + 1;
}
function decrement(inputId, remainingSeats) {
var inputElement = document.getElementById(inputId);
var value = parseInt(inputElement.value, 10);
if (remainingSeats + value > 0) {
inputElement.value = value - 1;
}
}
function deleteFlight(flightID) {
if (confirm('确定要删除此航班吗?')) {
fetch(`{{ url_for('delete_flight') }}?flightID=${flightID}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(data => {
alert(data.message);
if (data.success) {
window.location.href = "{{ url_for('index') }}";
}
})
.catch(error => console.error('Error:', error));
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>管理员登录 - KJF航班订票</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/login.css') }}">
<script src="{{ url_for('static', filename='js/login.js') }}" defer></script>
<script src="https://cdn.bootcss.com/blueimp-md5/2.12.0/js/md5.min.js"></script>
</head>
<body>
<header>
<h1>KJF航班订票</h1>
</header>
<main>
<div class="content">
<h2>管理员登录</h2>
<div class="login-form">
<input type="text" id="username" placeholder="用户名">
<div id="usernameError" class="error-message"></div>
<input type="password" id="password" placeholder="密码">
<div id="loginError" class="error-message"></div>
<input type="hidden" id="encryptedPassword">
<div class="buttons">
<button onclick="submitForm()">登录</button>
</div>
</div>
</div>
</main>
<footer>
<p>&copy; 2024 KJF航班订票. 保留所有权利。</p>
</footer>
</body>
</html>

Binary file not shown.

Binary file not shown.

View File

View File

@ -0,0 +1,79 @@
from flask import render_template, request, redirect, url_for, g, flash, session
from .config import db
import pymysql
from datetime import datetime
def book():
flight_id = request.args.get('flight_id')
if request.method == 'GET':
if not g.user:
return redirect(url_for("login"))
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
flight_sql = """
SELECT f.*, d.Name as Departure_airport_name, a.Name as Arrival_airport_name
FROM Flights f
JOIN Airports d ON f.Departure_airport = d.ID
JOIN Airports a ON f.Arrival_airport = a.ID
WHERE f.ID = %s;
"""
cursor.execute(flight_sql, (flight_id,))
flight = cursor.fetchone()
cursor.close()
conn.close()
return render_template('book.html', flight=flight, username=g.name)
if request.method == 'POST':
passengers = []
passenger_keys = ['card_code', 'name', 'phone_number', 'seat_class']
for i in range(len(request.form) // len(passenger_keys)):
passenger = {}
for key in passenger_keys:
passenger[key] = request.form.get(f'passengers[{i}][{key}]')
passengers.append(passenger)
if not passengers:
flash("请至少添加一位乘客", "error")
return redirect(url_for('search'))
conn = pymysql.connect(**db)
cursor = conn.cursor()
try:
# 插入订单记录
insert_order_sql = """
INSERT INTO Orders (Order_time, Paid, User_phone_number)
VALUES (%s, 0, %s)
"""
cursor.execute(insert_order_sql, (datetime.now(), g.user))
order_id = cursor.lastrowid
for passenger in passengers:
passenger_id = passenger['card_code']
name = passenger['name']
phone_number = passenger['phone_number']
seat_class = passenger['seat_class']
price_field = f"{seat_class.replace(' ', '_').lower()}_price"
price_sql = f"SELECT {price_field} FROM Flights WHERE ID = %s"
cursor.execute(price_sql, (flight_id,))
price = cursor.fetchone()[0]
# 调用存储过程
cursor.callproc('AddPassengerAndTicket', (passenger_id, name, phone_number, seat_class, flight_id, price, order_id))
conn.commit()
return redirect(url_for('order', order_id=order_id))
except Exception as e:
conn.rollback()
print(e)
flash("订票失败", "error")
return redirect(url_for('search'))
finally:
cursor.close()
conn.close()

View File

@ -0,0 +1,41 @@
from flask import request, redirect, url_for, g, flash
from .config import db
import pymysql
def cancel_order():
order_id = request.args.get('order_id')
if not g.user:
return redirect(url_for("login"))
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 检查订单是否存在
check_order_sql = "SELECT ID FROM Orders WHERE ID = %s"
cursor.execute(check_order_sql, (order_id,))
order_exists = cursor.fetchone()
if not order_exists:
cursor.close()
conn.close()
return redirect(url_for("order_list"))
try:
# 删除对应的机票
delete_tickets_sql = "DELETE FROM Tickets WHERE OrderID = %s"
cursor.execute(delete_tickets_sql, (order_id,))
# 删除订单
delete_order_sql = "DELETE FROM Orders WHERE ID = %s"
cursor.execute(delete_order_sql, (order_id,))
conn.commit()
flash("订单取消成功", "success")
except Exception as e:
conn.rollback()
print(e)
flash(f"订单取消失败:{e}", "error")
finally:
cursor.close()
conn.close()
return redirect(url_for('order_list'))

View File

@ -0,0 +1,18 @@
db = {
'host':'localhost',
'user':'serviceAgent',
'password':'password123',
'database':'ServiceDatabase'
}
SECRET_KEY = 'ILOVEDATABASETECH'
slideshow_images = [
{"link": "https://www.csair.com/mcms/mcms/SG/zh/2024/20240208_6/index-zh.html?lang=zh&country=sg&utm_campaign=2402gwstu&utm_source=gw&utm_channel=sg-lb", "src": "https://www.csair.com/mcms/20240321/3ee85acd463f481bb33f0d535a5814c6.jpg"},
{"link": "https://www.csair.com/mcms/mcms/SG/zh/2024/20240605_10/index_sg_cn.html?lang=zh&country=sg&utm_source=sg&utm_campaign=ZB001lydc&utm_channel=gw", "src": "https://www.csair.com/mcms/20240605/a553252769834188b0c76a9698292f27.jpg"},
{"link": "https://www.csair.com/mcms/mcms/SG/zh/2024/20240426_17/index_cn.html?lang=zh&country=sg&utm_source=sg&utm_campaign=ZB001znjp&utm_channel=gw", "src": "https://www.csair.com/mcms/20240321/820cd99c111849408b84c2b579086ef6.jpg"},
{"link": "https://www.csair.com/mcms/mcms/SG/zh/2024/20240524_2/index_cn.html?lang=zh&country=sg&country=my&utm_source=us&utm_campaign=ZB001nhzgx&utm_channel=gw", "src": "https://www.csair.com/mcms/20240321/61889331ca174670babd144bb064d398.jpg"},
{"link": "https://www.csair.com/mcms/mcms/SG/zh/2024/20240514_7/coupon.html?lang=zh&country=sg", "src": "https://www.csair.com/mcms/20240321/97e67c05291b4c64a8905e8a0c915d89.jpg"},
{"link": "#", "src": "https://www.csair.com/mcms/1026/43124f5d5124487f8d6678745ae42f57.jpg"},
{"link": "https://www.csair.com/mcms/mcms/SG/zh/2023/20231120_2/index_sg_cn.html?lang=zh&country=sg&utm_source=sg&utm_campaign=ZB001mq&utm_channel=gw", "src": "https://www.csair.com/mcms/1026/ea00e9cb9d9b43bea6497a6895c6d9e1.jpg"}
]

View File

@ -0,0 +1,18 @@
from flask import render_template, request, g, redirect, url_for, session
from .config import slideshow_images
from .utils import get_cities
def index():
if request.method == 'GET':
if not g.user:
return redirect(url_for("login"))
images = slideshow_images
return render_template(
'index.html', cities=get_cities(),
images=images, username=g.name
)
def logout():
session.clear()
session.pop('user_id', None)
return redirect(url_for('login'))

View File

@ -0,0 +1,35 @@
from flask import request, jsonify, session, url_for, render_template
from .config import db, slideshow_images
import pymysql
def connect(mobileNo, encrypted_password):
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
args = (mobileNo, encrypted_password)
verify_sql = "SELECT Phone_number FROM Users WHERE Phone_number = %s AND `Password` = %s;"
cursor.execute(verify_sql, args)
user = cursor.fetchone()
cursor.close()
conn.close()
return user
def login():
if request.method == 'GET':
images = slideshow_images
return render_template('login.html', images=images)
if request.method == 'POST':
session.pop('user_id', None)
mobileNo = request.json.get('username')
encrypted_password = request.json.get('password')
try:
user = connect(mobileNo, encrypted_password)
if not user:
return jsonify({'message': '用户不存在,请点击注册按钮注册'}), 401
session['user_id'] = mobileNo
session.modified = True
return jsonify({'redirect': url_for('index')})
except Exception as e:
print(e)
return jsonify({'message': '数据库错误,请稍后再试'}), 500

View File

@ -0,0 +1,119 @@
from flask import render_template, request, flash, redirect, url_for, session, g
from typing import Dict
from pymysql.cursors import Cursor
import pymysql
from .config import db
def verify_user(cursor: Cursor, phone_number: str, password: str) -> str:
sql = """
SELECT Password FROM Users WHERE Phone_number = %s;
"""
cursor.execute(sql, (phone_number,))
record = cursor.fetchone()
if not record:
return "NO_USER"
if record['Password'] != password:
return "WRONG_PASSWORD"
return "USER_VERIFIED"
class ModifyInfo:
def __init__(self, form: Dict[str, str], user_phone: str):
self.phone_number = user_phone
modifyType = form['modifyType']
self.new_password = form.get('encryptedNewPassword', None)
self.new_phone_number = form.get('mobileNo', None)
self.new_username = form.get('username', None)
modifyType2command = {
'删除账户': 'delete account',
'修改密码': 'modify Password',
'修改手机号': 'modify Phone_Number',
'修改用户名': 'modify Username'
}
self.sql_dict = {
'delete account': 'DELETE FROM Users WHERE Phone_number = %s;',
'modify Password': 'UPDATE Users SET Password = %s WHERE Phone_number = %s;',
'modify Phone_Number': 'UPDATE Users SET Phone_number = %s WHERE Phone_number = %s;',
'modify Username': 'UPDATE Users SET Username = %s WHERE Phone_number = %s;'
}
self.sql_args_dict = {
'delete account': (self.phone_number,),
'modify Password': (self.new_password, self.phone_number),
'modify Phone_Number': (self.new_phone_number, self.phone_number),
'modify Username': (self.new_username, self.phone_number)
}
self.ok_message_dict = {
'delete account': "删除账户成功",
'modify Password': "修改密码成功",
'modify Phone_Number': "修改手机号成功",
'modify Username': "修改用户名成功"
}
self.fail_message_dict = {
'delete account': "数据库异常,删除账户失败",
'modify Password': "数据库异常,修改密码失败",
'modify Phone_Number': "数据库异常,修改手机号失败",
'modify Username': "数据库异常,修改用户名失败"
}
self.command = modifyType2command[modifyType]
def get_sql(self):
return self.sql_dict[self.command]
def get_args(self):
return self.sql_args_dict[self.command]
def get_ok_message(self):
return self.ok_message_dict[self.command]
def get_fail_message(self):
return self.fail_message_dict[self.command]
def modify():
if request.method == 'GET':
if not g.user:
return redirect(url_for("login"))
user_phone = session.get('user_id')
return render_template('modify.html', current_user_phone=user_phone, current_username=g.name)
if request.method == 'POST':
user_phone = session.get('user_id')
password = request.form['encryptedPassword']
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
verify_info = verify_user(cursor, user_phone, password)
if verify_info == "NO_USER":
session.clear()
return redirect(url_for('login'))
elif verify_info == "WRONG_PASSWORD":
flash("密码错误")
conn.close()
return redirect(url_for('modify'))
modifyInfo = ModifyInfo(request.form, user_phone)
if modifyInfo.command == 'modify Phone_Number':
check_sql = "SELECT COUNT(*) FROM Users WHERE Phone_number = %s;"
cursor.execute(check_sql, (modifyInfo.new_phone_number,))
if cursor.fetchone()[0] > 0:
flash("手机号已存在,请使用其他手机号")
conn.close()
return redirect(url_for('modify'))
try:
cursor.execute(modifyInfo.get_sql(), modifyInfo.get_args())
conn.commit()
flash(modifyInfo.get_ok_message())
conn.close()
if modifyInfo.command in ['modify Phone_Number', 'modify Password', 'delete account']:
session.clear()
session.pop("user_id", None)
return redirect(url_for('login'))
elif modifyInfo.command == 'modify Username':
return redirect(url_for('modify'))
except Exception as e:
conn.rollback()
print(e)
flash(modifyInfo.get_fail_message())
conn.close()
return redirect(url_for('modify'))

View File

@ -0,0 +1,55 @@
from flask import render_template, request, redirect, url_for, g
from .config import db
import pymysql
def order():
order_id = request.args.get('order_id')
if not g.user:
return redirect(url_for("login"))
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 查询订单信息和航班信息
order_sql = """
SELECT o.*, f.*, d.Name as Departure_airport_name, a.Name as Arrival_airport_name
FROM Orders o
JOIN Tickets t ON o.ID = t.OrderID
JOIN Flights f ON t.FlightID = f.ID
JOIN Airports d ON f.Departure_airport = d.ID
JOIN Airports a ON f.Arrival_airport = a.ID
WHERE o.ID = %s
"""
cursor.execute(order_sql, (order_id,))
order_info = cursor.fetchone()
# 如果订单信息不存在,返回订单列表页面
if not order_info:
cursor.close()
conn.close()
return redirect(url_for("order_list"))
# 查询乘客信息和票据信息
tickets_sql = """
SELECT t.*, p.Name, p.Phone_number
FROM Tickets t
JOIN Passengers p ON t.PassengerID = p.ID
WHERE t.OrderID = %s
"""
cursor.execute(tickets_sql, (order_id,))
tickets = cursor.fetchall()
seatClass2Chinses = {
'First Class': '头等舱',
'Business Class': '商务舱',
'Economy Class': '经济舱'
}
for ticket in tickets:
ticket['Seat_class'] = seatClass2Chinses[ticket['Seat_class']]
cursor.close()
conn.close()
total_price = sum(ticket['Price'] for ticket in tickets)
return render_template('order.html', order=order_info, tickets=tickets, total_price=total_price, username=g.name)

View File

@ -0,0 +1,54 @@
from flask import render_template, request, redirect, url_for, g
from .config import db
import pymysql
def order_list():
if not g.user:
return redirect(url_for("login"))
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 查询用户关联的所有订单信息
orders_sql = """
SELECT o.ID as OrderID, o.Order_time, o.Paid, f.ID as FlightID, f.Airline,
d.Name as Departure_airport_name, a.Name as Arrival_airport_name,
f.Departure_time, f.Status, p.Name as PassengerName, t.Price
FROM Orders o
JOIN Tickets t ON o.ID = t.OrderID
JOIN Flights f ON t.FlightID = f.ID
JOIN Airports d ON f.Departure_airport = d.ID
JOIN Airports a ON f.Arrival_airport = a.ID
JOIN Passengers p ON t.PassengerID = p.ID
WHERE o.User_phone_number = %s
"""
cursor.execute(orders_sql, (g.user,))
orders = cursor.fetchall()
cursor.close()
conn.close()
# 整理订单信息
order_dict = {}
for order in orders:
order_id = order['OrderID']
if order_id not in order_dict:
order_dict[order_id] = {
'OrderID': order_id,
'Order_time': order['Order_time'],
'Paid': order['Paid'],
'FlightID': order['FlightID'],
'Airline': order['Airline'],
'Departure_airport_name': order['Departure_airport_name'],
'Arrival_airport_name': order['Arrival_airport_name'],
'Departure_time': order['Departure_time'],
'Status': order['Status'],
'Passengers': [],
'TotalPrice': 0
}
order_dict[order_id]['Passengers'].append(order['PassengerName'])
order_dict[order_id]['TotalPrice'] += order['Price']
order_list = list(order_dict.values())
return render_template('order_list.html', orders=order_list, username=g.name)

View File

@ -0,0 +1,30 @@
from flask import redirect, url_for, g, request
from .config import db
import pymysql
def pay_confirm():
order_id = request.args.get('order_id')
if not g.user:
return redirect(url_for("login"))
conn = pymysql.connect(**db)
cursor = conn.cursor()
# 检查订单是否存在
check_order_sql = "SELECT ID FROM Orders WHERE ID = %s"
cursor.execute(check_order_sql, (order_id,))
order_exists = cursor.fetchone()
if not order_exists:
cursor.close()
conn.close()
return redirect(url_for("order_list"))
update_order_sql = "UPDATE Orders SET Paid = 1 WHERE ID = %s"
cursor.execute(update_order_sql, (order_id,))
conn.commit()
cursor.close()
conn.close()
return redirect(url_for('order_list', order_id=order_id))

View File

@ -0,0 +1,53 @@
from flask import render_template, request, g, abort, redirect, url_for, flash
from .config import db
from .utils import get_cities
import pymysql
import datetime
def search():
if not g.user:
return redirect(url_for("login"))
departure_city = request.args.get('departure')
destination_city = request.args.get('destination')
departure_date = request.args.get('departure-date')
passengers = int(request.args.get('passengers', 1))
if not departure_city or not destination_city or not departure_date or not passengers:
flash("请填写所有查询条件", "error")
return render_template('search.html', cities=get_cities(), flights=[], username=g.name)
# Date validation
try:
departure_date_obj = datetime.datetime.strptime(departure_date, '%Y-%m-%d').date()
if departure_date_obj < datetime.date.today():
abort(400, description="Departure date cannot be in the past.")
except ValueError:
abort(400, description="Invalid date format.")
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
search_sql = """
SELECT f.*, d.Name as Departure_airport_name, a.Name as Arrival_airport_name
FROM Flights f
JOIN Airports d ON f.Departure_airport = d.ID
JOIN Airports a ON f.Arrival_airport = a.ID
WHERE d.City = %s AND a.City = %s
AND DATE(f.Departure_time) = %s
AND (f.First_class_seats_remaining + f.Business_class_seats_remaining + f.Economy_class_seats_remaining) >= %s
AND f.Status NOT IN ('已起飞', '已降落');
"""
cursor.execute(search_sql, (departure_city, destination_city, departure_date, passengers))
flights = cursor.fetchall()
cursor.close()
conn.close()
return render_template(
'search.html',
cities=get_cities(),
flights=flights,
username=g.name
)

View File

@ -0,0 +1,74 @@
from flask import render_template, request, redirect, url_for
from .config import db
import re
import pymysql
def signup():
error_messages = {
'username': '',
'mobileNo': '',
'password': '',
'confirmPassword': ''
}
if request.method == 'GET':
return render_template('signup.html', errors=error_messages)
if request.method == 'POST':
username = request.form['username']
phone_number = request.form['mobileNo']
password = request.form['encryptedPassword']
confirm_password = request.form['encryptedConfirmPassword']
# Basic validation for phone number
if not re.match(r'^\d{11}$', phone_number):
error_messages['mobileNo'] = '手机号格式有误'
# Check password length after MD5 hash
if len(password) != 32: # MD5 hash length is 32 characters
error_messages['password'] = '密码格式有误'
# Confirm password validation
if password != confirm_password:
error_messages['confirmPassword'] = '两次输入的密码不一致'
if any(error_messages.values()):
return render_template('signup.html', errors=error_messages)
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 检查已有用户
sql = """
SELECT COUNT(*) FROM Users \
WHERE Phone_number = %s;
"""
try:
cursor.execute(sql, (phone_number,))
phone_exist = cursor.fetchall()[0]['COUNT(*)']
except Exception as e:
error_messages['mobileNo'] = "数据库异常,查询失败"
print(e)
return render_template('signup.html', errors=error_messages)
if phone_exist != 0:
error_messages['mobileNo'] = "该手机号已注册,请勿重复注册"
conn.close()
return render_template('signup.html', errors=error_messages)
# 插入
sql = '''
INSERT INTO Users (Phone_number, Username, `Password`) \
VALUES (%s, %s, %s); \
'''
try:
cursor.execute(sql, (phone_number, username, password))
conn.commit()
return redirect(url_for('index'))
except Exception as e:
conn.rollback()
print(e)
error_messages['mobileNo'] = "数据库异常,注册失败"
return render_template('signup.html', errors=error_messages)
finally:
conn.close()

View File

@ -0,0 +1,20 @@
from .config import db
import pymysql
from xpinyin import Pinyin
from pymysql.cursors import Cursor
def get_cities():
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute("SELECT DISTINCT City FROM Airports")
cities = [row['City'] for row in cursor.fetchall()]
cursor.close()
conn.close()
p = Pinyin()
cities = [
(row, p.get_pinyin(row).replace("-", ""))
for row in cities
]
cities = sorted(cities, key=lambda x: x[1])
cities = [row[0] for row in cities]
return cities

View File

@ -0,0 +1,98 @@
from flask import Flask, redirect, url_for, session, g
from flask_httpauth import HTTPTokenAuth
from flask_cors import CORS
from func.config import db, SECRET_KEY
import pymysql
import func.login
import func.signup
import func.modify
import func.index
import func.search
import func.book
import func.pay_confirm
import func.cancel_order
import func.order
import func.order_list
app = Flask(__name__)
app.config["SECRET_KEY"] = SECRET_KEY
app.config["JSON_AS_ASCII"] = False
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SECURE'] = False
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
CORS(app, supports_credentials=True)
auth = HTTPTokenAuth(scheme='Bearer')
@app.before_request
def before_request():
g.user = None
g.name = None
if 'user_id' in session:
conn = pymysql.connect(**db)
cursor = conn.cursor(pymysql.cursors.DictCursor)
args = (session.get('user_id'),)
verify_sql = "SELECT Username FROM Users WHERE Phone_number = %s;"
cursor.execute(verify_sql, args)
res = cursor.fetchone()
if not res:
g.user = None
g.name = None
else:
g.user = session.get('user_id')
g.name = res['Username']
@app.route("/")
def home():
return redirect(url_for('index'))
@app.route("/index", methods=['GET', 'POST'])
def index():
return func.index.index()
@app.route("/login", methods=['GET', 'POST'])
def login():
return func.login.login()
@app.route('/logout')
def logout():
return func.index.logout()
@app.route("/signup", methods=['GET', 'POST'])
def signup():
return func.signup.signup()
@app.route("/modify", methods=['GET', 'POST'])
def modify():
return func.modify.modify()
@app.route("/search", methods=['GET'])
def search():
return func.search.search()
@app.route("/book", methods=['GET', 'POST'])
def book():
return func.book.book()
@app.route("/order", methods=['GET'])
def order():
return func.order.order()
@app.route('/cancel_order', methods=['POST'])
def cancel_order():
return func.cancel_order.cancel_order()
@app.route('/pay_confirm', methods=['POST'])
def pay_confirm():
return func.pay_confirm.pay_confirm()
@app.route("/order_list", methods=['GET', 'POST'])
def order_list():
return func.order_list.order_list()
if __name__ == "__main__":
app.run(
host="0.0.0.0",
port=8888,
debug=True
)

View File

@ -0,0 +1,238 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px;
width: 100%;
position: fixed;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.logo {
font-size: 24px;
font-weight: bold;
margin-left: 20px;
}
.nav-buttons {
display: flex;
gap: 20px;
}
.nav-buttons a {
color: white;
text-decoration: none;
font-size: 16px;
padding: 10px;
border-radius: 5px;
}
.nav-buttons a:hover {
background-color: #155a8c;
}
.user-menu {
position: relative;
display: flex;
align-items: center;
margin-right: 20px;
}
.user-menu span {
margin-right: 10px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropbtn {
background-color: rgba(28, 108, 178, 0.9);
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
right: 0; /* 确保下拉菜单靠右对齐 */
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #f1f1f1;
}
.dropdown:hover .dropdown-content {
display: block;
}
main {
flex: 1;
width: 80%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
h2 {
text-align: center;
color: #1c6cb2;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table, th, td {
border: 1px solid #ccc;
}
th, td {
padding: 10px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
.flight-row {
transition: transform 0.3s ease, box-shadow 0.3s ease, border-radius 0.3s ease;
}
.flight-row:hover {
transform: scale(1.02);
box-shadow: 0 0 10px rgba(28, 108, 178, 0.5);
border-radius: 10px;
}
.flight-info th, .flight-info td {
padding: 10px;
border: 1px solid #ccc;
}
form {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
}
.passenger {
margin-bottom: 20px;
transition: transform 0.3s ease, box-shadow 0.3s ease, border-radius 0.3s ease;
}
.passenger:hover {
transform: scale(1.02);
box-shadow: 0 0 10px rgba(28, 108, 178, 0.5);
border-radius: 10px;
}
.passenger h3 {
margin-top: 0;
}
.delete-btn {
background-color: #ff4d4d;
color: white;
border: none;
cursor: pointer;
padding: 5px 10px;
border-radius: 5px;
float: left;
}
.form-row {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
}
label {
flex: 1;
margin-right: 10px;
text-align: right;
line-height: 32px;
}
input, select {
flex: 2;
padding: 8px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 5px;
}
.error-message {
color: red;
font-size: 12px;
margin-top: 5px;
}
.total-price {
font-size: 18px;
font-weight: bold;
margin-top: 20px;
margin-bottom: 20px;
}
.btn {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
cursor: pointer;
margin-top: 10px;
}
.btn:hover {
background-color: #155a8c;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
position: relative;
margin-top: auto; /* 将footer推到页面底部 */
}

View File

@ -0,0 +1,237 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px;
width: 100%;
position: fixed;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.logo {
font-size: 24px;
font-weight: bold;
margin-left: 20px;
}
.nav-buttons {
display: flex;
gap: 20px;
}
.nav-buttons a {
color: white;
text-decoration: none;
font-size: 16px;
padding: 10px;
border-radius: 5px;
}
.nav-buttons a:hover {
background-color: #155a8c;
}
.user-menu {
position: relative;
display: flex;
align-items: center;
margin-right: 20px;
}
.user-menu span {
margin-right: 10px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropbtn {
background-color: rgba(28, 108, 178, 0.9);
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
right: 0; /* 确保下拉菜单靠右对齐 */
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #f1f1f1;
}
.dropdown:hover .dropdown-content {
display: block;
}
main {
flex: 1;
width: 100%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
.slides {
position: relative;
width: 100%;
height: 620px;
overflow: hidden;
}
.slides ul {
display: flex;
padding: 0;
width: 100%;
height: 100%;
list-style: none;
margin: 0;
transition: transform 0.6s ease-in-out;
}
.slides li {
min-width: 100%;
box-sizing: border-box;
}
.slides img {
width: 100%;
height: 100%;
object-fit: cover;
}
.content {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
border-radius: 10px;
text-align: center;
width: 80%;
max-width: 800px;
margin: -170px auto 20px;
position: relative;
}
.tabcontent {
display: block;
padding: 20px;
}
.form-row {
display: flex;
justify-content: flex-start; /* Left-align the form items */
margin-bottom: 15px;
}
.form-row label {
flex: 0 0 120px; /* Fixed width for labels */
margin-right: 10px;
text-align: right;
line-height: 32px;
}
.form-row input,
.form-row select {
flex: 1;
padding: 8px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 5px;
}
.form-row.form-row-center {
justify-content: center; /* Center-align the button */
}
.passenger-input {
display: flex;
align-items: center;
gap: 5px;
}
.passenger-input button {
padding: 5px 10px;
font-size: 18px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.passenger-input button:hover {
background-color: #155a8c;
}
.passenger-input input {
width: 50px;
text-align: center;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 5px;
}
.btn {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
cursor: pointer;
}
.btn:hover {
background-color: #155a8c;
}
.error-message {
color: red;
font-size: 12px;
margin-top: 5px;
text-align: left;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
position: relative;
margin-top: auto; /* 将footer推到页面底部 */
}

View File

@ -0,0 +1,121 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #ffffff;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
}
header {
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px 0;
text-align: center;
width: 100%;
}
main {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
position: relative;
}
.slides {
position: relative;
width: 100%;
height: 600px;
overflow: hidden;
}
.slides ul {
display: flex;
padding: 0;
width: 100%;
height: 100%;
list-style: none;
margin: 0;
transition: transform 0.6s ease-in-out;
}
.slides li {
min-width: 100%;
box-sizing: border-box;
}
.slides img {
width: 100%;
height: 100%;
object-fit: cover;
}
.content {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
border-radius: 10px;
text-align: center;
position: absolute;
}
h2 {
color: #1c6cb2;
}
.login-form {
margin-bottom: 20px;
}
.login-form input {
display: block;
margin: 10px auto;
padding: 10px;
font-size: 16px;
width: 80%;
max-width: 300px;
margin-bottom: 20px; /* 增加外边距 */
}
.buttons {
display: flex;
justify-content: center;
gap: 10px;
}
.login-form button,
.btn {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
line-height: 20px;
cursor: pointer;
}
.login-form button:hover,
.btn:hover {
background-color: #155a8c;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
}
.error-message {
color: red;
font-size: 12px;
text-align: left;
margin-top: -10px;
margin-bottom: 10px;
}

View File

@ -0,0 +1,149 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px;
width: 100%;
position: fixed;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
align-items: center;
justify-content: space-between;
width: 90%;
margin: 0 auto;
position: relative;
}
.header-content .btn-back {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
}
.header-content .btn-back:hover {
background-color: #155a8c;
}
.header-content h1 {
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.header-content .header-spacer {
width: 100px; /* 占位符,确保标题居中 */
}
main {
flex: 1;
width: 80%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
.content {
background-color: rgba(255, 255, 255, 0.9);
padding: 30px;
border-radius: 10px;
text-align: center;
width: 400px;
position: relative;
margin: auto;
}
h2 {
color: #1c6cb2;
}
form {
margin-top: 20px;
}
.tab {
display: flex;
justify-content: space-around;
margin-bottom: 20px;
}
.tab button {
background-color: #f1f1f1;
border: none;
outline: none;
cursor: pointer;
padding: 10px 20px;
transition: 0.3s;
font-size: 17px;
border-radius: 5px;
}
.tab button:hover {
background-color: #ddd;
}
.tab button.active {
background-color: #1c6cb2;
color: white;
}
.tabcontent {
display: none;
}
.form-group {
margin-bottom: 15px;
text-align: left;
}
.form-group div {
margin-bottom: 5px;
font-weight: bold;
}
.form-group input {
width: 100%;
padding: 10px;
box-sizing: border-box;
}
button[type="submit"] {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
width: 100%;
font-size: 16px;
}
button[type="submit"]:hover {
background-color: #155a8c;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
position: relative;
margin-top: auto; /* 将footer推到页面底部 */
}

View File

@ -0,0 +1,191 @@
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(28, 108, 178, 0.9);
color: white;
padding: 20px;
width: 100%;
position: fixed;
top: 0;
z-index: 1000;
}
.header-content {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.logo {
font-size: 24px;
font-weight: bold;
margin-left: 20px;
}
.nav-buttons {
display: flex;
gap: 20px;
}
.nav-buttons a {
color: white;
text-decoration: none;
font-size: 16px;
padding: 10px;
border-radius: 5px;
}
.nav-buttons a:hover {
background-color: #155a8c;
}
.user-menu {
position: relative;
display: flex;
align-items: center;
margin-right: 20px;
}
.user-menu span {
margin-right: 10px;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropbtn {
background-color: rgba(28, 108, 178, 0.9);
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
right: 0;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #f1f1f1;
}
.dropdown:hover .dropdown-content {
display: block;
}
main {
flex: 1;
width: 80%;
margin: 20px auto;
padding-top: 80px; /* 给主内容增加顶部填充,以避免被固定导航栏遮挡 */
}
h2 {
text-align: center;
color: #1c6cb2;
}
.order-info, .passenger-info, .order-summary {
background-color: rgba(255, 255, 255, 0.8);
padding: 20px;
border-radius: 10px;
margin-bottom: 20px;
}
.order-info p, .order-summary p {
margin: 5px 0;
}
table {
width: 100%;
border-collapse: collapse;
}
table, th, td {
border: 1px solid #ccc;
}
th, td {
padding: 10px;
text-align: center;
}
th {
background-color: #f2f2f2;
}
.btn {
padding: 10px 20px;
background-color: #1c6cb2;
color: white;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
cursor: pointer;
margin-top: 10px;
}
.btn:hover {
background-color: #155a8c;
}
.cancel-btn {
background-color: #ff4d4d;
}
.cancel-btn:hover {
background-color: #cc0000;
}
.back-btn {
background-color: #f2f2f2;
color: black;
border: none;
border-radius: 5px;
padding: 10px 20px;
cursor: pointer;
text-decoration: none;
display: inline-block;
margin: 10px 0;
}
.back-btn:hover {
background-color: #d9d9d9;
}
footer {
background-color: rgba(28, 108, 178, 0.9);
color: white;
text-align: center;
padding: 10px 0;
width: 100%;
position: relative;
margin-top: auto; /* 将footer推到页面底部 */
}

Some files were not shown because too many files have changed in this diff Show More