Skip to content

Commit 081e63c

Browse files
committed
新增红票样式
1 parent 626dc51 commit 081e63c

File tree

4 files changed

+302
-184
lines changed

4 files changed

+302
-184
lines changed

package/website/public/bluebg.png

168 KB
Loading

package/website/public/redbg.png

515 KB
Loading

package/website/src/components/TrainTicket.vue

Lines changed: 130 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,40 @@
99
transform: exporting ? 'none' : `scale(${scale})`,
1010
transformOrigin: 'top left',
1111
width: BASE_WIDTH + 'px',
12-
height: BASE_HEIGHT + 'px'
12+
height: BASE_HEIGHT + 'px',
13+
backgroundImage: backgroundImage
1314
}"
1415
>
1516
<div
16-
class="ticket relative text-[32px] text-gray-800 w-full h-full rounded-[14px] shadow-[0_6px_24px_rgba(0,0,0,.12),0_2px_6px_rgba(0,0,0,.08)] border border-[#b8cfe0] overflow-hidden p-[5px_65px_0_50px]"
17+
class="ticket relative text-[35px] w-full h-full rounded-[14px] shadow-[0_6px_24px_rgba(0,0,0,.12),0_2px_6px_rgba(0,0,0,.08)] border border-[#b8cfe0] overflow-hidden p-[5px_60px_0_50px]"
18+
:style="{
19+
padding: style=='red' ? '50px 60px 0 60px' : '5px 60px 0 50px'
20+
}
21+
"
1722
role="img"
1823
aria-label="火车票">
1924

20-
<!-- 顶部:票号/检票口 -->
21-
<div class="topbar flex items-center justify-between tracking-[0.3px]">
25+
<!-- 顶部:票号/检票口,当style等于red时隐藏 -->
26+
<div class="topbar flex items-center justify-between tracking-[0.3px]" v-if="showHeader()">
2227
<div class="serial text-[#e35757] font-semibold">{{ serial }}</div>
2328
<div class="gate">检票:{{ gate }}</div>
2429
</div>
2530

2631
<div class="bgmain">
27-
<div
28-
class="absolute inset-0 z-[-2] opacity-5 bg-bottom bg-no-repeat bg-contain"
29-
:style="{ backgroundImage: 'url(/CRH-Dr3OhT7q.jpg)' }"
30-
></div>
31-
<div class="h-[250px]">
32+
<div>
3233
<!-- 主信息:出发站 / 车次 / 到达站 -->
33-
<div class="main grid grid-cols-[1fr_auto_1fr] gap-[10px] px-[0px_40px_0_20px] items-center">
34+
<div class="grid grid-cols-[1fr_auto_1fr] gap-[10px] px-[0px_20px_0_20px] items-center">
3435
<div class="station flex flex-col from items-center">
3536
<div class="flex items-center flex-grow-0">
3637
<div
37-
class="name text-[45px] tracking-[0.5px] max-w-[240px]"
38+
class="station-name"
3839
:class="{'two-char': fromStation.length === 2}"
3940
>
4041
{{ fromStation }}
4142
</div>
42-
<div class="big-fix px-[4px] py-[0px] text-[35px]">站</div>
43+
<div class="big-fix px-[4px] py-[0px]">站</div>
4344
</div>
44-
<div class="pinyin ml-[10px] text-[24px]">{{ fromPinyin }}</div>
45+
<div class="pinyin ml-[10px] mt-[-10px] text-[26px]">{{ fromPinyin }}</div>
4546
</div>
4647
<!-- 中间列:车次 + 箭头 -->
4748
<div class="train-center flex flex-col items-center justify-center">
@@ -51,42 +52,38 @@
5152
<!-- 箭头 -->
5253
<!-- CSS 箭头 -->
5354
<div class="arrow mt-[6px] relative h-3 w-full">
54-
<div class="line h-[4px] bg-gray-600 w-full"></div>
55-
<div class="arrow-head absolute right-0 top-[-7px] h-4 w-4 border-t-[4px] border-gray-600 rotate-45"></div>
55+
<div class="line h-[4px] bg-black w-full"></div>
56+
<div class="arrow-head absolute right-0 top-[-7px] h-4 w-4 border-t-[4px] border-black rotate-45"></div>
5657
</div>
5758
</div>
5859
<div class="station to flex flex-col items-center">
5960
<div class="flex items-center flex-grow-0">
6061
<div
61-
class="name text-[45px] tracking-[0.5px] max-w-[240px]"
62+
class="station-name"
6263
:class="{'two-char': toStation.length === 2}"
6364
>
6465
{{ toStation }}
6566
</div>
66-
<div class="big-fix px-[4px] py-[0px] text-[35px]">站</div>
67+
<div class="big-fix px-[4px] py-[0px]">站</div>
6768
</div>
68-
<div class="pinyin ml-[10px] text-[24px]">{{ toPinyin }}</div>
69+
<div class="pinyin ml-[10px] mt-[-10px] text-[26px]">{{ toPinyin }}</div>
6970
</div>
7071
</div>
7172

7273
<!-- 第二行:时间 / 车厢座位 / 价格 / 座位类型 -->
73-
<div class="second-row flex justify-between pr-[100px]">
74+
<div class="flex justify-between pr-[100px] mt-[-10px]">
7475
<div class="datetime">
75-
{{ dateTime.year }}
76-
<span class="small-fix text-[24px]">年</span>
77-
{{ dateTime.month }}
78-
<span class="small-fix text-[24px]">月</span>
79-
{{ dateTime.day }}
80-
<span class="small-fix text-[24px]">日</span>
81-
{{ dateTime.time }}
82-
<span class="small-fix text-[24px]">开</span>
76+
{{ dateTime.year }}<span class="small-fix text-[24px]">年
77+
</span>{{ dateTime.month }}<span class="small-fix text-[24px]">月
78+
</span>{{ dateTime.day }}<span class="small-fix text-[24px]">日
79+
</span>{{ dateTime.time }}<span class="small-fix text-[24px]">开</span>
8380
</div>
8481
<div class="seat">{{ carriage }}<span class="small-fix text-[24px]">车</span>{{ seatNumber }}<span class="small-fix text-[24px]">号</span><span v-if="berthType">{{ berthType }}</span><span v-if="berthType" class="small-fix text-[24px]">铺</span></div>
8582
</div>
8683
<!-- 价格和座位类型行:添加优惠标识 -->
87-
<div class="second-row flex justify-between pr-[100px] items-center">
88-
<div class="datetime flex items-center gap-[12px]">
89-
¥{{ price }}<span class="small-fix text-[24px]">元</span>
84+
<div class="flex justify-between pr-[100px] items-center mt-[-10px]">
85+
<div>
86+
¥{{ price }}<span class="text-[24px]">元</span>
9087
</div>
9188
<div>
9289
<!-- 优惠标识 -->
@@ -97,17 +94,21 @@
9794
</div>
9895
</div>
9996
</div>
100-
97+
<p class="muted text-[30px]">仅供当日乘车<br></p>
98+
<p class="muted text-[30px]">仅供报销使用</p>
10199
<!-- 详情与二维码 -->
102100
<div class="detail-area relative grid grid-cols-[1fr_170px] gap-[16px]">
103101
<div>
104-
<p class="muted mt-[6px]">仅供报销使用</p>
102+
105103
<div class="code">{{ idNumber }} {{ passengerName }}</div>
106-
<!-- 虚线框 -->
107-
<div class="details text-[20px] text-center leading-[1.5] border-dashed border-[3px] border-[#999] mx-[28px]">
104+
<!-- 虚线框,单个虚线变长 -->
105+
<div class="details text-[24px] text-center mt-[-6px] ">
108106
<p>报销凭证 遗失不补</p>
109107
<p>退票改签时须交回车站</p>
110108
</div>
109+
<div class="footer-red" v-if="!showHeader()">
110+
<div class="text-[30px]">{{ footerInfo }}</div>
111+
</div>
111112
</div>
112113

113114
<!-- 二维码 -->
@@ -119,8 +120,8 @@
119120
</div>
120121

121122
<!-- 底部出票信息 -->
122-
<div class="footer absolute w-[856px] left-[-50px] bottom-[-8px] h-[65px] flex justify-between items-center bg-[#94CAE0] text-[25px] text-[#2a2a2a]">
123-
<div class="from px-[50px]">{{ footerInfo }}</div>
123+
<div class="footer" v-if="showHeader()">
124+
<div class="px-[50px] text-[30px]">{{ footerInfo }}</div>
124125
</div>
125126
</div>
126127
</div>
@@ -188,7 +189,8 @@ const props = defineProps({
188189
}
189190
return validTypes.includes(value)
190191
}
191-
}
192+
},
193+
style: {type: String, default: 'red' }
192194
})
193195
194196
// 拆分时间
@@ -245,6 +247,15 @@ const discountTexts = computed(() => {
245247
return texts
246248
})
247249
250+
// 如果style为red则设置背景为redTicket.png
251+
const backgroundImage = computed(() => {
252+
return props.style === 'red' ? "url('/redbg.png')" : "url('/bluebg.png')"
253+
})
254+
255+
const showHeader = () => {
256+
return props.style !== 'red'
257+
}
258+
248259
defineExpose({ wrapper, exporting }) // ✅ 暴露内部DOM给父组件访问
249260
</script>
250261

@@ -262,13 +273,26 @@ defineExpose({ wrapper, exporting }) // ✅ 暴露内部DOM给父组件访问
262273
.ticket-container {
263274
transform-origin: top left;
264275
transition: transform 0.2s ease;
276+
z-index: -1;
277+
background-repeat: no-repeat;
278+
background-position: bottom;
279+
background-size: contain;
280+
background-image: url('/redbg.png');
281+
font-family: 'SimSun', '宋体','PingFang SC', 'Microsoft YaHei', 'WenQuanYi Zen Hei', serif, sans-serif;
282+
font-weight: 600;
283+
color: #291e1e;
265284
}
266285
267286
/* 票样式 */
268287
.ticket > * {
269288
position: relative;
270289
z-index: 1;
290+
/* 背景图填充整个元素,不重复,包含padding和margin */
291+
292+
/* class="absolute inset-0 z-[-2] opacity-5 bg-bottom bg-no-repeat bg-contain" */
293+
271294
}
295+
272296
.ticket {
273297
font-smoothing: antialiased;
274298
-webkit-font-smoothing: antialiased;
@@ -281,7 +305,6 @@ defineExpose({ wrapper, exporting }) // ✅ 暴露内部DOM给父组件访问
281305
position: absolute;
282306
inset: 0;
283307
z-index: -1;
284-
background-color: #e8f3f7;
285308
background-image: linear-gradient(
286309
-45deg,
287310
rgba(180, 200, 220, 0.3) 1px,
@@ -291,6 +314,53 @@ defineExpose({ wrapper, exporting }) // ✅ 暴露内部DOM给父组件访问
291314
background-size: 4px 4px;
292315
}
293316
317+
.station-name {
318+
font-size: 50px;
319+
max-width: 280px;
320+
/* letter-spacing: 0.5px; */
321+
font-family: 'SimHei', '黑体', 'SimSun', '宋体','PingFang SC', 'Microsoft YaHei', 'WenQuanYi Zen Hei', serif, sans-serif;
322+
font-weight: 500;
323+
}
324+
325+
.details {
326+
/* 保留原样式:字体、对齐、内外边距 */
327+
font-size: 24px;
328+
text-align: center;
329+
/* line-height: 1.5; */
330+
margin: 0 28px; /* 原 mx-[28px] */
331+
padding: 2px; /* 内边距避免文字贴边框,可调整 */
332+
--dash-length: 15px; /* 虚线单段长度(可改) */
333+
--dash-gap: 8px; /* 虚线间距(可改) */
334+
--border-width: 2px; /* 边框粗细(可改) */
335+
--border-color: #291e1e;/* 边框颜色(可改) */
336+
337+
/* 模拟四向虚线边框:通过4个背景图层分别实现上、右、下、左 */
338+
background-image:
339+
/* 上边框:水平方向,实线段15px,透明段8px,重复 */
340+
repeating-linear-gradient(to right, var(--border-color), var(--border-color) var(--dash-length), transparent var(--dash-length), transparent calc(var(--dash-length) + var(--dash-gap))),
341+
/* 右边框:垂直方向,实线段15px,透明段8px,重复 */
342+
repeating-linear-gradient(to bottom, var(--border-color), var(--border-color) var(--dash-length), transparent var(--dash-length), transparent calc(var(--dash-length) + var(--dash-gap))),
343+
/* 下边框:水平方向 */
344+
repeating-linear-gradient(to right, var(--border-color), var(--border-color) var(--dash-length), transparent var(--dash-length), transparent calc(var(--dash-length) + var(--dash-gap))),
345+
/* 左边框:垂直方向 */
346+
repeating-linear-gradient(to bottom, var(--border-color), var(--border-color) var(--dash-length), transparent var(--dash-length), transparent calc(var(--dash-length) + var(--dash-gap)));
347+
348+
/* 控制每个背景图层的尺寸和位置 */
349+
background-size:
350+
100% var(--border-width), /* 上边框:宽度100%,高度=边框粗细 */
351+
var(--border-width) 100%, /* 右边框:宽度=边框粗细,高度100% */
352+
100% var(--border-width), /* 下边框 */
353+
var(--border-width) 100%; /* 左边框 */
354+
355+
background-position:
356+
top left, /* 上边框:居上左 */
357+
top right, /* 右边框:居上右 */
358+
bottom left, /* 下边框:居下左 */
359+
top left; /* 左边框:居上左 */
360+
361+
background-repeat: no-repeat; /* 背景不重复(重复由 repeating-linear-gradient 实现) */
362+
}
363+
294364
/* 背景图 */
295365
/* .bgmain::before {
296366
content: "";
@@ -315,7 +385,7 @@ defineExpose({ wrapper, exporting }) // ✅ 暴露内部DOM给父组件访问
315385
height: 0;
316386
border-left: 8px solid transparent; /* 左透明边框(数值越小箭头越细) */
317387
border-right: 8px solid transparent; /* 右透明边框(与左边数值一致) */
318-
border-top: 8px solid #3a5874; /* 箭头颜色(与拼音同色) */
388+
border-top: 8px solid #291e1e; /* 箭头颜色(与拼音同色) */
319389
margin-top: 6px; /* 箭头与文字的间距(可按需调整) */
320390
}
321391
/* 新增:优惠标识圆圈样式 */
@@ -325,12 +395,32 @@ defineExpose({ wrapper, exporting }) // ✅ 暴露内部DOM给父组件访问
325395
justify-content: center;
326396
width: 36px;
327397
height: 36px;
328-
border: 3px solid #1f1d1d;
398+
border: 3px solid #291e1e;
329399
border-radius: 50%;
330400
font-size: 24px;
331401
/* font-weight: 600; */
332402
line-height: 1;
333403
text-align: center;
334404
/* background-color: rgba(227, 87, 87, 0.08); */
335405
}
406+
407+
.footer {
408+
position: absolute;
409+
width: 856px;
410+
left: 0px;
411+
bottom: 0px;
412+
height: 52px;
413+
display: flex;
414+
justify-content: left;
415+
align-items: left;
416+
}
417+
418+
.footer-red {
419+
/* position: absolute; */
420+
/* width: 856px; */
421+
left: -40px;
422+
bottom: 0px;
423+
height: 52px;
424+
}
425+
336426
</style>

0 commit comments

Comments
 (0)