From af67ad6147800468ab2b101c5a4cc361cb1fd35b Mon Sep 17 00:00:00 2001
From: zyj <zyj@local>
Date: 星期日, 13 九月 2026 23:39:44 +0800
Subject: [PATCH] docs(工作日结): 补记 2026-09-13 《运距异常分析》分析报告(出版)重写与文件误覆盖恢复
---
package-deploy.py | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 283 insertions(+), 0 deletions(-)
diff --git a/package-deploy.py b/package-deploy.py
new file mode 100644
index 0000000..41d0c19
--- /dev/null
+++ b/package-deploy.py
@@ -0,0 +1,283 @@
+# -*- coding: utf-8 -*-
+"""TrafficAudit 涓�閿墦鍖呰剼鏈細鍓嶇鏋勫缓 -> 鍐呭祵杩涘悗绔� jar -> 缁勮閮ㄧ讲鍖� -> 鎵� zip
+鐢ㄦ硶锛歱ython package-deploy.py [--no-build]
+"""
+import io, os, sys, shutil, zipfile, subprocess, datetime
+
+ROOT = os.path.dirname(os.path.abspath(__file__))
+WEB = os.path.join(ROOT, "traffic-audit-web")
+SERVER = os.path.join(ROOT, "traffic-audit-server")
+STATIC = os.path.join(SERVER, "src", "main", "resources", "static")
+STAMP = datetime.datetime.now().strftime("%Y%m%d")
+STAGE = os.path.join(ROOT, "deploy", "traffic-audit-deploy-" + STAMP)
+ZIP = os.path.join(ROOT, "traffic-audit-deploy-" + STAMP + ".zip")
+JAR_NAME = "traffic-audit-server-1.0.0-SNAPSHOT.jar"
+SKIP_DOC_DIRS = {"ai_demo", "usage_screenshots", "鍔熻兘娴嬭瘯鎶ュ憡", "宸ヤ綔鏃ョ粨"}
+
+def rmtree_force(path):
+ """鍒犻櫎鐩綍锛氬厛娓呮帀鍙灞炴�э紙婧愮洰褰曢噷瀛樺湪鍙鏂囦欢锛宑opy2 浼氬甫杩囨潵锛屽鑷� Windows 涓� rmtree 鎶ユ嫆缁濊闂級"""
+ if not os.path.isdir(path):
+ return
+ for r, d, fs in os.walk(path):
+ for f in fs:
+ try:
+ os.chmod(os.path.join(r, f), 0o666)
+ except OSError:
+ pass
+ shutil.rmtree(path, ignore_errors=True)
+
+
+def run(cmd, cwd, log):
+ with io.open(log, "w", encoding="utf-8", newline="") as f:
+ p = subprocess.run(cmd, cwd=cwd, stdout=f, stderr=subprocess.STDOUT, shell=True)
+ return p.returncode
+
+def main():
+ do_build = "--no-build" not in sys.argv
+ print("[1/6] 鍓嶇鏋勫缓 ...")
+ if do_build:
+ rc = run('cmd /c "npm.cmd run build 1>build_prod.log 2>&1"', WEB, os.path.join(WEB, "build_prod.log"))
+ print(" npm run build rc=%d" % rc)
+ if rc != 0:
+ raise SystemExit("鍓嶇鏋勫缓澶辫触锛岃 traffic-audit-web/build_prod.log")
+ dist = os.path.join(WEB, "dist")
+ if not os.path.isfile(os.path.join(dist, "index.html")):
+ raise SystemExit("鏈壘鍒� dist/index.html锛岃鍏堟瀯寤哄墠绔�")
+
+ print("[2/6] 鎶� dist 鍐呭祵杩涘悗绔� static 骞舵墦 jar ...")
+ copied = []
+ try:
+ rmtree_force(STATIC)
+ shutil.copytree(dist, STATIC)
+ for r, d, fs in os.walk(STATIC):
+ for f in fs:
+ copied.append(os.path.join(r, f))
+ rc = run('cmd /c "mvn.cmd -o -q clean package -DskipTests -f traffic-audit-server\\pom.xml"',
+ ROOT, os.path.join(ROOT, "package_build.log"))
+ if rc != 0:
+ print(" 绂荤嚎鎵撳寘澶辫触锛屾敼涓鸿仈缃戞墦鍖� ...")
+ rc = run('cmd /c "mvn.cmd -q clean package -DskipTests -f traffic-audit-server\\pom.xml"',
+ ROOT, os.path.join(ROOT, "package_build.log"))
+ if rc != 0:
+ raise SystemExit("鍚庣鎵撳寘澶辫触锛岃 package_build.log")
+ finally:
+ rmtree_force(STATIC)
+ os.makedirs(STATIC, exist_ok=True)
+ jar = os.path.join(SERVER, "target", JAR_NAME)
+ if not os.path.isfile(jar):
+ raise SystemExit("鏈壘鍒� jar: " + jar)
+ print(" jar=%.1f MB" % (os.path.getsize(jar) / 1048576.0))
+
+ print("[3/6] 缁勮閮ㄧ讲鐩綍 %s ..." % STAGE)
+ rmtree_force(STAGE)
+ be = os.path.join(STAGE, "backend")
+ fe = os.path.join(STAGE, "frontend")
+ db = os.path.join(STAGE, "db")
+ for d in (be, fe, db):
+ os.makedirs(d)
+ shutil.copy2(jar, os.path.join(be, JAR_NAME))
+ rmtree_force(os.path.join(be, "docs"))
+ dst_docs = os.path.join(be, "docs")
+ os.makedirs(dst_docs)
+ for name in os.listdir(os.path.join(ROOT, "docs")):
+ if name in SKIP_DOC_DIRS:
+ continue
+ src = os.path.join(ROOT, "docs", name)
+ dst = os.path.join(dst_docs, name)
+ if os.path.isdir(src):
+ shutil.copytree(src, dst, ignore=shutil.ignore_patterns("杈撳嚭"))
+ else:
+ shutil.copy2(src, dst)
+ shutil.copytree(dist, os.path.join(fe, "dist"))
+ for s in ("init.sql", "sql_city_bus.sql", "sql_city_taxi.sql", "sql_wyc.sql"):
+ shutil.copy2(os.path.join(ROOT, "docs", s), os.path.join(db, s))
+
+ print("[4/6] 鍐欏叆閰嶇疆涓庡惎鍔ㄨ剼鏈� ...")
+ io.open(os.path.join(be, "application.yml"), "w", encoding="utf-8", newline="\r\n").write(APPLICATION_YML)
+ io.open(os.path.join(be, "start-backend.cmd"), "w", encoding="utf-8", newline="\r\n").write(START_CMD)
+ io.open(os.path.join(be, "start-backend.sh"), "w", encoding="utf-8", newline="\n").write(START_SH)
+ io.open(os.path.join(STAGE, "frontend", "nginx.conf.example"), "w", encoding="utf-8", newline="\n").write(NGINX)
+ io.open(os.path.join(STAGE, "README-閮ㄧ讲璇存槑.txt"), "w", encoding="utf-8", newline="\r\n").write(README)
+
+ print("[5/6] 鎵� zip ...")
+ if os.path.isfile(ZIP):
+ os.remove(ZIP)
+ n = 0
+ with zipfile.ZipFile(ZIP, "w", zipfile.ZIP_DEFLATED, compresslevel=6) as z:
+ for r, d, fs in os.walk(STAGE):
+ for f in fs:
+ full = os.path.join(r, f)
+ z.write(full, os.path.relpath(full, STAGE))
+ n += 1
+ print("[6/6] 瀹屾垚锛�%s (%.1f MB, %d 涓枃浠�)" % (ZIP, os.path.getsize(ZIP) / 1048576.0, n))
+
+APPLICATION_YML = u"""# ============================================================
+# TrafficAudit 鍚庣澶栭儴閰嶇疆锛堜笌 jar 鍚岀骇鍗冲彲鐢熸晥锛屼紭鍏堢骇楂樹簬 jar 鍐呯疆閰嶇疆锛�
+# 閮ㄧ讲鍒版柊鏈哄櫒鍚庯紝璇�**鑷冲皯**淇敼涓嬮潰鏍囨敞 TODO 鐨勪笁澶勬暟鎹簱閰嶇疆锛�
+# ============================================================
+server:
+ port: 8090
+app:
+ captcha:
+ required: false # 鐢熶骇鐜濡傞渶鍥惧舰楠岃瘉鐮侊紝鏀逛负 true
+spring:
+ datasource:
+ url: jdbc:mysql://127.0.0.1:3306/traffic_audit?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true
+ username: root # TODO 鏀规垚浣犵殑 MySQL 璐﹀彿
+ password: 璇锋敼鎴愪綘鐨勬暟鎹簱瀵嗙爜 # TODO 鏀规垚浣犵殑 MySQL 瀵嗙爜
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ servlet:
+ multipart:
+ max-file-size: 100MB
+ max-request-size: 100MB
+ jackson:
+ date-format: yyyy-MM-dd HH:mm:ss
+ time-zone: Asia/Shanghai
+mybatis-plus:
+ mapper-locations: classpath*:/mapper/**/*.xml
+ type-aliases-package: com.trafficaudit
+ configuration:
+ map-underscore-to-camel-case: true
+ global-config:
+ db-config:
+ id-type: auto
+ logic-delete-field: deleted
+ logic-delete-value: 1
+ logic-not-delete-value: 0
+jwt:
+ # 蹇呴』鏄�孊ase64 鍚堟硶瀛楃 + 闀垮害鏄� 4 鐨勫�嶆暟銆嶏紱涓嬮潰杩欎覆 32 浣嶅崄鍏繘鍒跺彲鐩存帴鐢紝
+ # 鐢熶骇鐜寤鸿鎹㈡垚鑷繁鐨勯殢鏈轰覆锛堝~涓枃鎴栦笉鍚堟硶瀛楃浼氬鑷寸櫥褰� 500锛�
+ secret: 8f2c1d64a7b34e09c5d81f6a2b0e7c93
+ expiration: 86400000
+docs:
+ template-root: docs
+city-passenger:
+ template-dir: docs/鍩庡競瀹㈣繍
+passenger:
+ template-dir: docs/鍏矾鏃呭
+freight:
+ template-dir: docs/璐ц繍
+energy:
+ template-dir: docs/鑳借��
+investment:
+ template-dir: docs/鎶曡祫/妯℃澘
+summary:
+ template-dir: docs/鐢熸垚姹囨�诲ぇ琛� # 姹囨�诲ぇ琛ㄦ瘝鐗堜笌鐗堝紡鍙傜収浠舵墍鍦ㄧ洰褰曪紙蹇呴渶锛�
+deepseek:
+ api-key: "" # AI 鍒嗘瀽鐢紱鐣欑┖鍒� AI 鍒嗘瀽涓嶅彲鐢�
+ api-url: https://api.deepseek.com/v1/chat/completions
+ model: deepseek-chat
+"""
+
+START_CMD = u"""@echo off
+chcp 65001 >nul
+cd /d %~dp0
+where java >nul 2>nul
+if errorlevel 1 (
+ echo [ERROR] 鏈壘鍒� java锛岃鍏堝畨瑁� JDK 8 骞跺姞鍏� PATH
+ pause
+ exit /b 1
+)
+echo ============================================
+echo TrafficAudit 鍚姩涓細http://localhost:8090
+echo 鍓嶇宸插唴宓岋紝鐩存帴璁块棶 8090 鍗冲彲锛堜笉闇�瑕� nginx锛�
+echo 鏃ュ織鏄剧ず鍦ㄦ湰绐楀彛锛屽叧闂獥鍙e嵆鍋滄鏈嶅姟
+echo ============================================
+java -jar traffic-audit-server-1.0.0-SNAPSHOT.jar
+pause
+"""
+
+START_SH = u"""#!/bin/sh
+cd "$(dirname "$0")" || exit 1
+echo "TrafficAudit 鍚姩涓細http://localhost:8090 锛圕trl+C 鍋滄锛�"
+java -jar traffic-audit-server-1.0.0-SNAPSHOT.jar 2>&1 | tee app.log
+"""
+
+NGINX = u"""# 鍓嶇 nginx 閰嶇疆绀轰緥锛堝彧鏈夊湪涓嶆兂鐢ㄣ�宩ar 鍐呭祵鍓嶇銆嶆椂鎵嶉渶瑕侊級
+server {
+ listen 8080;
+ server_name localhost;
+ root /opt/traffic-audit/frontend/dist; # 鏀规垚瀹為檯璺緞
+ index index.html;
+ location /api/ {
+ proxy_pass http://127.0.0.1:8090;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_read_timeout 300s;
+ }
+ location / { try_files $uri $uri/ /index.html; }
+}
+"""
+
+README = u"""TrafficAudit 浜ら�氳揣杩愮粺璁″鏍哥郴缁� 鈥斺�� 閮ㄧ讲鍖咃紙{stamp}锛�
+========================================================
+
+銆愮洰褰曠粨鏋勩��
+ backend/
+ traffic-audit-server-1.0.0-SNAPSHOT.jar 鍚庣绋嬪簭锛堝惈鍏ㄩ儴渚濊禆锛�**宸插唴宓屽墠绔�**锛�
+ docs/ 鎶ヨ〃妯℃澘涓庤繍琛屾暟鎹洰褰曪紙蹇呴渶锛屽嬁鍒狅級
+ application.yml 澶栭儴閰嶇疆锛堟敼杩欓噷鍗冲彲锛屾棤闇�閲嶆柊鎵撳寘锛�
+ start-backend.cmd / start-backend.sh 鍚姩鑴氭湰
+ frontend/
+ dist/ 鍓嶇鏋勫缓浜х墿锛堝鐢細鎯崇敤 nginx 鎵樼鏃剁敤锛�
+ nginx.conf.example nginx 閰嶇疆绀轰緥
+ db/
+ init.sql 寤哄簱寤鸿〃 + 棰勭疆璐﹀彿锛堝繀椤绘墽琛岋級
+ sql_city_bus.sql 鍩庡競瀹㈣繍-鍏氦鏈堝害琛紙蹇呴』鎵ц锛�
+ sql_city_taxi.sql 鍩庡競瀹㈣繍-鍑虹鏈堝害琛�/鍑虹鎺堟潈琛紙蹇呴』鎵ц锛�
+ sql_wyc.sql 缃戠害杞﹀叏鐪佹�婚噺琛�/璁㈠崟鍒嗗競宸炶〃锛堝繀椤绘墽琛岋級
+ README-閮ㄧ讲璇存槑.txt
+
+銆愰儴缃叉満鐜瑕佹眰銆�
+ JDK 8锛堝繀闇�锛�
+ MySQL 5.7 / 8.0锛堝繀闇�锛�
+ **涓嶉渶瑕� Redis**锛堜唬鐮佹湭浣跨敤锛涙棫鐗堣鏄庨噷鐨� Redis 鏄仐鐣欓厤缃紝鍙拷鐣ワ級
+ **涓嶉渶瑕� nginx**锛堝墠绔凡鍐呭祵杩� jar锛岃闂� 8090 鍗冲彲锛沶ginx 浠呬负澶囬�夋柟妗堬級
+
+銆愰儴缃叉楠ゃ��
+ 1. 鍒濆鍖栨暟鎹簱锛�4 涓剼鏈兘瑕佹墽琛岋紝椤哄簭濡備笅锛�
+ mysql --default-character-set=utf8mb4 -u root -p < db/init.sql
+ mysql --default-character-set=utf8mb4 -u root -p traffic_audit < db/sql_city_bus.sql
+ mysql --default-character-set=utf8mb4 -u root -p traffic_audit < db/sql_city_taxi.sql
+ mysql --default-character-set=utf8mb4 -u root -p traffic_audit < db/sql_wyc.sql
+ 棰勭疆璐﹀彿锛歛dmin / admin123锛堥娆$櫥褰曞悗璇锋敼瀵嗙爜锛�
+
+ 2. 鏀归厤缃� backend/application.yml
+ - spring.datasource.url / username / password 锛氭敼鎴愰儴缃叉満鐨� MySQL锛堥粯璁ょ鍙� 3306锛�
+ - jwt.secret 锛氭敼鎴愪竴涓查殢鏈哄瓧绗︿覆锛�**蹇呴』鏄� Base64 鍚堟硶瀛楃涓旈暱搴︽槸 4 鐨勫�嶆暟**锛屽 32 浣嶅崄鍏繘鍒讹紱濉腑鏂囦細鐧诲綍澶辫触锛�
+ - deepseek.api-key 锛氶渶瑕� AI 鍒嗘瀽鏃跺~锛屼笉闇�瑕佸彲鐣欑┖
+ 娉細application.yml 涓� jar 鍚岀骇鍗崇敓鏁堬紝涓嶇敤閲嶆柊鎵撳寘銆�
+
+ 3. 鍚姩鍚庣锛堝湪 backend 鐩綍涓嬶級
+ Windows锛氬弻鍑� start-backend.cmd
+ Linux锛� sh start-backend.sh
+ 鎴愬姛鏍囧織锛氬嚭鐜� "Started TrafficAuditApplication" 涓� "Tomcat started on port(s): 8090"
+
+ 4. 璁块棶绯荤粺
+ 娴忚鍣ㄦ墦寮� http://<閮ㄧ讲鏈篒P>:8090 锛堝墠绔凡鍐呭祵锛岄〉闈笌鎺ュ彛鍚屾簮锛�
+ 璐﹀彿锛歛dmin / admin123
+
+銆愭暟鎹縼绉伙紙鍙�夛級銆�
+ 鎯虫妸鏈満鏁版嵁涓�骞舵惉鍒版柊鏈哄櫒锛岀敤 mysqldump锛堟湰鏈� MySQL 鑻ヤ笉鍦� 3306锛屾寜瀹為檯绔彛鏀癸級锛�
+ mysqldump -h 127.0.0.1 -P 3306 -u root -p --databases traffic_audit > traffic_audit_full.sql
+ 鍐嶅湪鏂版満鍣ㄦ墽琛岋細
+ mysql -u root -p < traffic_audit_full.sql
+ 娉ㄦ剰锛氬叏閲� dump 浼氬甫涓婃湰鏈虹殑璐﹀彿瀵嗙爜锛岃鐩� init.sql 棰勭疆鐨� admin 璐﹀彿銆�
+
+銆愬父瑙侀棶棰樸��
+ 1. 鍚姩鎶ャ�屾湭鎵惧埌鏁版嵁鐩綍 docs銆�/ 瀵煎嚭鎶ャ�屾湭鎵惧埌妯℃澘鏂囦欢銆嶏細
+ 蹇呴』鍦� backend 鐩綍涓嬪惎鍔紙jar 涓� docs 鍚岀骇锛夛紝涓嶈鍙嫹 jar銆�
+ 2. 鎶ヨ〃瀵煎嚭鎶ャ�屾湭鎵惧埌姹囨�昏〃姣嶇増銆奩YYY骞碝鏈堥亾璺繍杈撻噺姹囨�昏〃.xlsx銆嬨�嶏細
+ docs/鐢熸垚姹囨�诲ぇ琛� 涓嬬己灏戣鏈堜唤姣嶇増锛涙妸婧愭満鍣ㄧ殑璇ユ枃浠舵嫹杩囧幓銆�
+ 3. 8090 绔彛琚崰鐢細鏀� application.yml 鐨� server.port 鍚庨噸鍚��
+ 4. 椤甸潰鎵撳紑鏄┖鐧斤細纭璁块棶鐨勬槸 http://<IP>:8090 鏍硅矾寰勶紝涓旀祻瑙堝櫒寮哄埗鍒锋柊锛圕trl+F5锛夈��
+ 5. 涓婁紶澶ф枃浠跺け璐ワ細鍚庣闄愬埗 100MB锛屽凡閰嶇疆锛涘鍓嶉潰杩樻寕浜� nginx锛岄渶鍚屾鏀惧ぇ client_max_body_size銆�
+
+銆愬仠姝㈡湇鍔°��
+ Windows锛氬叧闂� start-backend.cmd 绐楀彛
+ Linux锛� Ctrl+C锛屾垨 kill 瀵瑰簲 java 杩涚▼锛坧s -ef | grep java锛�
+"""
+
+if __name__ == "__main__":
+ main()
--
Gitblit v1.9.1