Skip to content

Commit f5a7e54

Browse files
committed
update nuoche;
1 parent 7cba6bf commit f5a7e54

File tree

5 files changed

+253
-33
lines changed

5 files changed

+253
-33
lines changed

src/CodeWF/Pages/Tool/Converter/IconConverter.razor

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
@using Microsoft.JSInterop
2-
@inject IOptions<SiteOption> SiteOptions
3-
@inject IJSRuntime JS
1+
@inject IOptions<SiteOption> SiteOptions
42

53
<PageTitle>在线ICO转换器 - @SiteOptions.Value.AppTitle</PageTitle>
64

@@ -134,15 +132,6 @@
134132

135133
@code {
136134
public const string Slug = "ico";
137-
138-
protected override async Task OnAfterRenderAsync(bool firstRender)
139-
{
140-
if (firstRender)
141-
{
142-
await JS.InvokeVoidAsync("initIconConverter");
143-
}
144-
}
145-
146135
}
147136

148137
<script>

src/CodeWF/Pages/Tool/Converter/NuoChe.razor

Lines changed: 188 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
[SupplyParameterFromQuery]
88
public string? P { get; set; }
99

10+
public const string Slug = "nuoche";
11+
1012
private long? _decodePhone;
1113

1214
protected override void OnInitialized()
@@ -17,7 +19,6 @@
1719
_decodePhone = new Hashids("codewf").DecodeLong(P)[0];
1820
}
1921
}
20-
2122
}
2223

2324
<PageTitle>免费挪车码</PageTitle>
@@ -27,7 +28,30 @@
2728
{
2829
<div class="generator-container">
2930
<h1 class="generator-title">挪车码在线生成器</h1>
30-
<p class="generator-subtitle">开发中</p>
31+
<div class="input-group">
32+
<label for="phoneNumber">手机号码</label>
33+
<input type="tel" id="phoneNumber" placeholder="请输入手机号码" />
34+
</div>
35+
<div class="input-group">
36+
<label for="title">标题</label>
37+
<input type="text" id="title" placeholder="临时停靠,请多关照" value="临时停靠,请多关照" />
38+
</div>
39+
<div class="button-group">
40+
<button class="primary-button" onclick="generateQrCode()">
41+
<i class="fas fa-qrcode"></i> 生成二维码
42+
</button>
43+
</div>
44+
<div class="qr-code-container" style="display: none">
45+
<img alt="挪车码" />
46+
<div class="action-buttons">
47+
<a target="_blank" class="preview-link">
48+
<i class="fas fa-external-link-alt"></i> 预览
49+
</a>
50+
<a class="download-link">
51+
<i class="fas fa-download"></i> 下载
52+
</a>
53+
</div>
54+
</div>
3155
</div>
3256
}
3357
else
@@ -102,10 +126,10 @@
102126
text-align: center;
103127
}
104128
105-
.card-header i {
106-
font-size: 2rem;
107-
margin-bottom: 10px;
108-
}
129+
.card-header i {
130+
font-size: 2rem;
131+
margin-bottom: 10px;
132+
}
109133
110134
.title {
111135
font-size: 1.3rem;
@@ -146,16 +170,16 @@
146170
align-items: center;
147171
}
148172
149-
.phone-button:hover,
150-
.phone-button:focus {
151-
background-color: #f4511e;
152-
box-shadow: 0 6px 12px rgba(255, 87, 34, 0.4);
153-
transform: translateY(-2px);
154-
}
173+
.phone-button:hover,
174+
.phone-button:focus {
175+
background-color: #f4511e;
176+
box-shadow: 0 6px 12px rgba(255, 87, 34, 0.4);
177+
transform: translateY(-2px);
178+
}
155179
156-
.phone-button i {
157-
margin-right: 8px;
158-
}
180+
.phone-button i {
181+
margin-right: 8px;
182+
}
159183
160184
.generate-link {
161185
color: #3385ff;
@@ -165,11 +189,157 @@
165189
padding: 5px;
166190
}
167191
168-
.generate-link:hover {
169-
text-decoration: underline;
170-
}
192+
.generate-link:hover {
193+
text-decoration: underline;
194+
}
171195
196+
/* 添加新的样式 */
197+
.input-group {
198+
width: 100%;
199+
margin-bottom: 20px;
200+
}
201+
202+
.input-group label {
203+
display: block;
204+
margin-bottom: 8px;
205+
color: #333;
206+
font-weight: 500;
207+
text-align: left;
208+
}
209+
210+
.input-group input {
211+
width: 100%;
212+
padding: 12px;
213+
border: 1px solid #ddd;
214+
border-radius: 8px;
215+
font-size: 1rem;
216+
transition: border-color 0.3s;
217+
}
218+
219+
.input-group input:focus {
220+
border-color: #3385ff;
221+
outline: none;
222+
}
223+
224+
.button-group {
225+
margin: 20px 0;
226+
}
227+
228+
.primary-button {
229+
background-color: #3385ff;
230+
color: white;
231+
border: none;
232+
padding: 12px 24px;
233+
border-radius: 8px;
234+
font-size: 1rem;
235+
cursor: pointer;
236+
transition: all 0.3s;
237+
display: flex;
238+
align-items: center;
239+
justify-content: center;
240+
gap: 8px;
241+
}
242+
243+
.primary-button:hover {
244+
background-color: #2670e8;
245+
transform: translateY(-2px);
246+
}
247+
248+
.qr-code-container {
249+
margin-top: 20px;
250+
text-align: center;
251+
}
252+
253+
.qr-code-container img {
254+
max-width: 340px;
255+
margin-bottom: 10px;
256+
}
257+
258+
.preview-link {
259+
color: #3385ff;
260+
text-decoration: none;
261+
display: inline-flex;
262+
align-items: center;
263+
gap: 4px;
264+
}
265+
266+
.preview-link:hover {
267+
text-decoration: underline;
268+
}
269+
270+
.action-buttons {
271+
display: flex;
272+
justify-content: center;
273+
gap: 20px;
274+
margin-top: 10px;
275+
}
276+
277+
.download-link {
278+
color: #28a745;
279+
text-decoration: none;
280+
display: inline-flex;
281+
align-items: center;
282+
gap: 4px;
283+
cursor: pointer;
284+
}
285+
286+
.download-link:hover {
287+
text-decoration: underline;
288+
}
172289
</style>
173290

174291
<!-- 添加Font Awesome图标支持 -->
175292
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet">
293+
294+
<!-- 在页面底部添加script标签 -->
295+
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
296+
<script>
297+
async function generateQrCode() {
298+
const title = document.getElementById('title').value;
299+
const phoneNumber = document.getElementById('phoneNumber').value;
300+
301+
if (!title || !phoneNumber) {
302+
alert('请输入标题和手机号码');
303+
return;
304+
}
305+
306+
try {
307+
const response = await fetch('/api/Image/nuoche', {
308+
method: 'POST',
309+
headers: {
310+
'Content-Type': 'application/json',
311+
},
312+
body: JSON.stringify({
313+
title: title,
314+
phoneNumber: phoneNumber
315+
})
316+
});
317+
318+
const data = await response.json();
319+
if (data.success) {
320+
const qrCodeContainer = document.querySelector('.qr-code-container');
321+
const img = qrCodeContainer.querySelector('img');
322+
img.src = data.qrCodeUrl;
323+
qrCodeContainer.querySelector('.preview-link').href = data.generatedUrl;
324+
325+
// 添加下载功能
326+
const downloadLink = qrCodeContainer.querySelector('.download-link');
327+
downloadLink.onclick = () => {
328+
const a = document.createElement('a');
329+
a.href = data.qrCodeUrl;
330+
a.download = '挪车码.png';
331+
document.body.appendChild(a);
332+
a.click();
333+
document.body.removeChild(a);
334+
};
335+
336+
qrCodeContainer.style.display = 'block';
337+
} else {
338+
throw new Error(data.message);
339+
}
340+
} catch (error) {
341+
console.error('生成二维码失败:', error);
342+
alert('生成二维码失败,请稍后重试');
343+
}
344+
}
345+
</script>

src/CodeWF/Pages/Tool/Index.razor

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,15 @@
3939
{
4040
<IconConverter/>
4141
}
42+
4243
@if (string.Equals(Slug, Timestamp.Slug, StringComparison.OrdinalIgnoreCase))
4344
{
44-
<Timestamp />
45+
<Timestamp/>
46+
}
47+
48+
@if (string.Equals(Slug, NuoChe.Slug, StringComparison.OrdinalIgnoreCase))
49+
{
50+
<NuoChe/>
4551
}
4652
}
4753
</ChildContent>

src/WebSite/Controllers/ImageController.cs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
using CodeWF.Tools;
1+
using CodeWF.Options;
2+
using CodeWF.Tools;
23
using CodeWF.Tools.FileExtensions;
4+
using CodeWF.Tools.Image;
5+
using HashidsNet;
36
using Microsoft.AspNetCore.Authorization;
47
using Microsoft.AspNetCore.Mvc;
5-
using WebSite.ViewModels;
8+
using Microsoft.Extensions.Options;
69

710
namespace WebSite.Controllers;
811

@@ -82,6 +85,51 @@ public async Task<IActionResult> SeparateGenerateIconAsync([FromForm] IFormFile
8285
}
8386
}
8487

88+
[HttpPost("nuoche")]
89+
[AllowAnonymous]
90+
public async Task<IActionResult> NuoCheAsync([FromBody] NuoCheRequest request,
91+
[FromServices] IWebHostEnvironment env,
92+
[FromServices] IOptions<SiteOption> siteOption)
93+
{
94+
try
95+
{
96+
if (string.IsNullOrWhiteSpace(request.Title) || string.IsNullOrWhiteSpace(request.PhoneNumber))
97+
{
98+
return BadRequest(new { success = false, message = "标题和手机号码不能为空" });
99+
}
100+
101+
if (!long.TryParse(request.PhoneNumber, out long phoneNumberLong))
102+
{
103+
return BadRequest(new { success = false, message = "无效的手机号码" });
104+
}
105+
106+
var encodedPhone = new Hashids("codewf").EncodeLong(phoneNumberLong);
107+
var generatedUrl = $"{siteOption.Value.Domain}/nuoche?p={encodedPhone}";
108+
109+
var fileName = $"qrcode_{Guid.NewGuid():N}.png";
110+
var qrCodePath = Path.Combine(env.WebRootPath, IconFolder, fileName);
111+
112+
// 确保目录存在
113+
Directory.CreateDirectory(Path.Combine(env.WebRootPath, IconFolder));
114+
115+
// 生成二维码
116+
QrCodeGenerator.GenerateQrCode(request.Title, generatedUrl, qrCodePath);
117+
118+
// 返回可访问的URL
119+
var qrCodeUrl = $"/{IconFolder}/{fileName}";
120+
return Ok(new
121+
{
122+
success = true,
123+
qrCodeUrl = qrCodeUrl,
124+
generatedUrl = generatedUrl
125+
});
126+
}
127+
catch (Exception ex)
128+
{
129+
return BadRequest(new { success = false, message = ex.Message });
130+
}
131+
}
132+
85133
private async Task<string> SaveFileAsync(IFormFile file, IWebHostEnvironment env)
86134
{
87135
var saveFileName = Guid.NewGuid().ToString("N");
@@ -93,4 +141,10 @@ private async Task<string> SaveFileAsync(IFormFile file, IWebHostEnvironment env
93141
await file.CopyToAsync(fs);
94142
return saveFullPath;
95143
}
144+
145+
public class NuoCheRequest
146+
{
147+
public string Title { get; set; }
148+
public string PhoneNumber { get; set; }
149+
}
96150
}

src/WebSite/WebSite.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
</PropertyGroup>
1111

1212
<ItemGroup>
13+
<PackageReference Include="CodeWF.Tools.Image" Version="1.3.5.3" />
1314
<PackageReference Include="FluentValidation" Version="12.0.0-preview1" />
1415
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
1516
<PackageReference Include="Known.Core" Version="3.1.9" />

0 commit comments

Comments
 (0)