From 847957be61d8395f073c0581cb2b6429d3278151 Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Sun, 19 Jul 2026 00:16:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E7=BA=BF=E8=B7=AF=E5=9B=BE=E7=BD=B2=E5=90=8D=E5=B9=B6=E5=9B=BA?= =?UTF-8?q?=E5=AE=9A=20CC=20BY=204.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/routes/assets.js | 24 ++++++++++++++++++++++-- web/home.html | 24 ++++++++++++++++++++++-- web/index.html | 21 +++++++++++++++++++-- web/index.js | 26 +++++++++++++++++++++----- web/style.css | 3 +++ web/ticket-order.js | 20 +++++++++++++++++++- 6 files changed, 106 insertions(+), 12 deletions(-) diff --git a/server/routes/assets.js b/server/routes/assets.js index 60d7365..f8793bf 100644 --- a/server/routes/assets.js +++ b/server/routes/assets.js @@ -8,6 +8,7 @@ const router = express.Router(); const ASSETS_DIR = path.join(__dirname, '../../Assets'); const MANIFEST_PATH = path.join(ASSETS_DIR, 'manifest.json'); +const ROUTE_MAP_LICENSE = 'CC BY 4.0'; const getIp = (req) => (req.headers['x-forwarded-for'] || '').toString().split(',')[0].trim() || req.ip || req.connection?.remoteAddress || ''; @@ -48,6 +49,8 @@ const writeManifest = (m) => { fs.writeFileSync(MANIFEST_PATH, JSON.stringify(out, null, 2), 'utf8'); }; +const normalizeCredit = (value) => String(value || '').trim().slice(0, 200); + const removeByPrefix = (prefix) => { ensureDir(ASSETS_DIR); const list = fs.readdirSync(ASSETS_DIR); @@ -97,6 +100,8 @@ router.get('/manifest', (req, res) => { res.json({ ok: true, routeMap, + routeMapCredit: normalizeCredit(m.routeMapCredit || ''), + routeMapLicense: ROUTE_MAP_LICENSE, fareTable, updatedAt: m.updatedAt || null }); @@ -106,10 +111,24 @@ router.post('/route-map', uploadRouteMap.single('file'), (req, res) => { if (!req.file) return res.status(400).json({ ok: false, error: '缺少文件' }); const m = readManifest(); m.routeMap = path.basename(req.file.filename); + if (req.body && Object.prototype.hasOwnProperty.call(req.body, 'credit')) { + m.routeMapCredit = normalizeCredit(req.body.credit); + } else if (typeof m.routeMapCredit !== 'string') { + m.routeMapCredit = ''; + } m.updatedAt = Date.now(); writeManifest(m); - appendReqLog(req, { category: 'admin', type: 'asset_upload_route_map', detail: { file: m.routeMap } }); - res.json({ ok: true, routeMap: m.routeMap, updatedAt: m.updatedAt }); + appendReqLog(req, { category: 'admin', type: 'asset_upload_route_map', detail: { file: m.routeMap, credit: m.routeMapCredit || '' } }); + res.json({ ok: true, routeMap: m.routeMap, routeMapCredit: m.routeMapCredit || '', routeMapLicense: ROUTE_MAP_LICENSE, updatedAt: m.updatedAt }); +}); + +router.post('/route-map/credit', (req, res) => { + const m = readManifest(); + m.routeMapCredit = normalizeCredit(req.body?.credit); + m.updatedAt = Date.now(); + writeManifest(m); + appendReqLog(req, { category: 'admin', type: 'asset_update_route_map_credit', detail: { credit: m.routeMapCredit || '' } }); + res.json({ ok: true, routeMapCredit: m.routeMapCredit || '', routeMapLicense: ROUTE_MAP_LICENSE, updatedAt: m.updatedAt }); }); router.post('/fare-table', uploadFareTable.single('file'), (req, res) => { @@ -129,6 +148,7 @@ router.delete('/route-map', (req, res) => { } removeByPrefix('route-map'); m.routeMap = null; + m.routeMapCredit = ''; m.updatedAt = Date.now(); writeManifest(m); appendReqLog(req, { category: 'admin', type: 'asset_delete_route_map', detail: { ok: true } }); diff --git a/web/home.html b/web/home.html index 8b4bb90..6010292 100644 --- a/web/home.html +++ b/web/home.html @@ -184,6 +184,26 @@