This commit is contained in:
2026-06-12 11:48:17 +08:00
parent ee26bc6d7a
commit 8c93377659
45 changed files with 12786 additions and 1716 deletions
+2 -2
View File
@@ -15,5 +15,5 @@ WORKDIR /app
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:1024 || exit 1
RUN bash -c 'touch /app/ruopiao.jar'
ENTRYPOINT ["java","-jar","/app/ruopiao.jar","--spring.profiles.active=prod"]
RUN bash -c 'touch /app/piaowu.jar'
ENTRYPOINT ["java","-jar","/app/piaowu.jar","--spring.profiles.active=prod"]
+299
View File
@@ -0,0 +1,299 @@
gitea: ZhihuiGitea gms3buqu info@rszhihui.com
携程账号:
1350830938 cjq&xc2026
干部培训虚拟机:
https://blj.henu.edu.cn/index.php/Public/index/stra_name/local
hebixue
Gms&Peixun2026
航班管家:
fxrongshuo 密码: 13520830938 Gms&hangguan2026
hg_shuangfang 244817043@qq.com
hg_zhangyang
厦门航空B2B
168.92+50000
东方航空:
登录名:13520830938 密码:Zhihui@ce2026
b2t: zhangyang1 Zhihui@2026
shuangfang1 Zhihui@2026
https://www.tianqiip.com
13520830938
Zhihui2026
共翔天翼下载:https://eterm.travelsky.cn/tosp/#/promoteTraining/SGUI?activeName=fourth 只能安装在win10/11
6位工作号:
239032 密码 Gms&3buqu -> Gmsgwl&3buqu -> Gms&3buqu2026 ->Gms&KueNmb@2026
中国航信配置平台:https://tcc.travelsky.cn
主激活码:X6A6-Z4C5-Y9W5-N6M8 通道号:CG22107
双认证平台:新建工作号后,要登录这里激活。
https://eterm.travelsky.cn/tosp
239032
登录密码:Gms&3buquhelp
配置缴费:
U翼eterm平台:http://uwing.travelsky.com.cn/
uwing网站: http://uwing.travelsky.com.cn/uwing/common/login.jsp
uwing账号 用户名 密码
RONGSHUOZHIHUI PEK309 1a2b3c4d
eterm账号:eterm.travelsky.cn , 这个网站仅可修改eterm的password
黑屏登录账号:用户名:o3daf471 ,原始密码 zD6fZ9pZ4u 密码已改为-> Gms&3buqu
服务器地址选CRS03.eterm.com.cn ,并勾选CRS
腾云平台:
web.travelsky.com.cn 腾云账号 changjunqiang Gms&3buqu
=================================================================
智汇票务服务器1aliyun.com:beijing
北京融硕 Gms3buqu
123.57.71.170 administrator KueNmb/1yux.3buqu
智汇票务服务器2tencentyun:shanghai
118.25.129.153 root KueNmb/1yux,3buqu -> KueNmb/118yux -> KueNmb/1yux,3buqu
智汇票务服务器3:天翼云北京:
登录:北京融硕 Gms*3buqu
49.7.179.42 administrator KueNmb/1yux,3buqu -> KueNmb/1yux,tianyi -> KueNmb/2yux,tianyi2604
茂华服务器:49.7.183.243 administrator Gms&maohua2026
工作号:211411 密码: MaoHua@2026
通道号:CG25227
主激活码:Z6S9-H7F2-H8P6-U9M9
辅激活码:Q3T9-S5R3-N4U6-E9Q5
手机号:17516767676
共翔助手密码:beiJING@159!
智汇票务服务器4:volcengine 火山服务器 beijing 登录帐号: info@rszhihui.com Gms3buqu
101.126.159.1 root KueNmb/2yux,3buqu
1panel面板管理: http://101.126.159.1:1111/safe admin gms3buqu
=======================
iata.org info@rszhihui.com
通道服务器:腾讯云344656718@qq.com 13837313963
101.42.162.65 administrator KueNmb/1yux,3buqu
扶摇平台:
https://www.71fy.com/Login/Login
民航清算中心申请行程单 http://xcd.caacsc.com/login
pek309c Gmsgwl&xcd
====================================================================
航协代理人系统:iasa-asd.com 0800945 Gmsgwl3buqu-> gmsgwl&3buqu -> Rszhihui2025-> Rszhihui2026
航协申请:https://www.iata-asd.com/asdcore/login.seam
https://www.iata-asd.com/2131e4a4-50fc-42f4-823a-215e588cdee8/ALL/ALL.pdf
portal.iata.org
账号: info@rszhihui.com Gms&123buqu Gms&3buquiata -> Gmsgwl&3buqu -> Gmsgwl&3buqu2511
-> Gmsgwl&iata2601 -> Gmsgwl&iata2602-> Gmsgwl&iata2606
上岗证,BSP 培训电话:01056088112
【易宝支付】商户账号创建成功!管理员登录名:10090533084,支付密码:abcde&888->abcd@0912 登录密码:Gms&3buqu1pay->Gms&3buqu2026
13520830938 Gms&3buqu
商户标识:YP10090533084
出票秘钥:C0EB384C65B843389DC5083FCA64512B
交易密码:Gms&1pay
郭豪身份证号:410721199607205019
双芳账号: shuangfang 244817043@qq.com
我的账号:13520830938 登录密码: Gms&1buqu 交易密码:cjq@0912
www.dovepay.com
【德付通】 info@rszhihui.com Gms3buqu->Gms3buqudove-> Gms3buqu2026 179623->179632->179633
提现申请过以后,还需要在我的账户->提现审核 一下。
https://www.zhxgdb.com
=======================================================================================================================================
华中航空:ctrip携程:
携程账号:深圳华中
密码:shenzhen258.
appkey:c7bf422720ef3530
appsecret:b090ce975c51fe503ea6e57645e440bb793c31e1ee16e9cec60225d66f41df6b
秘钥:E2AA965505A762774AA486E160EEBCAC
授权OfficeNO: szx340
手机号码:18568527711
邮箱:18568527711@139.com
https://trade.ctrip.com/flight/newWeb/index.html#/workorder?redirect=%2Fpolicy%2FrawPolicy
政策携程账号:董志刚 密码:HJK123456-
uif 指令用于显示 当前登录账号。
违约金问题 订单审核国内机票 ddshgnjp@ctrip.com
订单问题 订单协调组国内机票 ddxtzgnjp@ctrip.com
投诉反馈 业务规范组 ywgfz@ctrip.com
配置接口使用问题 产品技术支持组 cpjszc@ctrip.com
政策投放 TBooking系统出票问题咨询 业务培训支持组
ywpxzcz@ctrip.com PATA权限申请 机票业务支持组 jpywzcz@Ctrip.com
https://tbooking.ctrip.com/ntbooking/ntpage/login
同程:===============================================================================
账号:szshzhk 密码: szshzhk@tcjp appid: 76345524
手机: 17734777168
同程政策API:
https://jpebook.ly.com/openapidoc/html/web/controller/console/console.html
领达
API开发需要注意的几个问题:
1.sign时用 hmacSha256,且转成String时要注意。
2.Header 中 token 和一般接口的 token值有区别,token 的是 10位时间戳。
===========================================================================
去哪儿:
账号: 3ed8iknm 密码: szhzHK_2011
退票审核appkey7c46e6ad793a06cb4416af695ae6a9eb
退票审核token 0b205e53b90d7873f9e13d7dd9a13fd9
航变推送tokenI#XTUWQ~0RgIhHB
新版appkey7c46e6ad793a06cb4416af695ae6a9eb
新版token0b205e53b90d7873f9e13d7dd9a13fd9
去哪儿接口地址:http://ssw.trade.qunar.com/
手机号码: 18924622310
http://open.qunar.com/developer/doc
途牛:
apiKey625zuA8MdvHC8DiOiH
sign: 33518
供应商ID33518
操作人名称:李瑞
手机号码:13823555251
酷讯:
酷讯账号:huazhongdingdan
酷讯密码:huazhongdingdan
航变账号:huazhonghangbian
航变站点号:382
航变密码:huazhonghangbian
酷讯接口地址: https://mproxy-flight.meituan.com/order/interface/export
手机号码:13823555251
普通验证码:http://www.fateadm.com 130074 Q9xeOMDcfLYT+BTV/G/Dtk3cXKYwfnH5
滑动验证码:http://www.rrocr.com 442438605@qq.com c9675660800147c1920674df3a84ce55
出票:
航班管家:18568527711 李先生 https://ticketsaas.huoli.com/docs/#/
用户id: szxhz 用户密码:13802290795
分销平台:https://ticketsaas.huoli.com/merchant/#/login
有IP限制。
易旅行:
EtravelB2Bpid : 0B330D1B3E7A44618B54EBE50AD694E4 安全码:0982aa9e78611ade 联系人:18568527711 冯一洋
Eterm 账号:office code: SZX340 47.107.127.4 端口:350
77703 密码:77703@1
FY1 密码:feiye888@#@
FY2 密码:feiye888@#@
FY3 密码:feiye888@
FY4 密码:feiye888@
http://www.pudn.com
华中易宝各航司对应账号: 易宝会员登陆账号:szhuazhong 18568527711 易宝信用卡:5201521661483959
航司 B2B账号 B2B密码 B2B支付账号 B2B支付密码 易宝商编 易宝网银密钥
GS SZXHZ340 SZXHZ@340 hz-zdcp 700816AbCd 10011418478 DE81A21BE7E148BEB5D4680F5FB351BF
QW szx340 Ci@123456 hz-zdcp 700816AbCd 10011418478 DE81A21BE7E148BEB5D4680F5FB351BF
CZ CGQ0160 Zm1234567@ hz-zdcp 700816AbCd 异常
MU 805186187@qq.com 700816LLa% 0002420230008970 700816
BK SZX340 huazhong667@ hz-zdcp 700816AbCd 10011418478 DE81A21BE7E148BEB5D4680F5FB351BF
A6 SZX340 huazhong667+-+ hz-zdcp 700816AbCd 5201521661483959 410711198901050022 13724305416 付英俊 340 1026
TV SZX340 AA@12345678 huazhong888@qq.com 124578aa
MF SZX_SZX340 700816L** hz-zdcp 700816AbCd 10011418478 DE81A21BE7E148BEB5D4680F5FB351BF
DZ szxszx340 huazhong667-AA hz-zdcp 700816AbCd 10011418478 DE81A21BE7E148BEB5D4680F5FB351BF 9517701000203885955
CA SZXHZHK01 CA123456a- hz-zdcp 700816AbCd
LT SZX340 gj123456a+ hz-zdcp 700816AbCd 10011418478 DE81A21BE7E148BEB5D4680F5FB351BF
HU huazhonghangkong huazhong677++A hz-zdcp 700816AbCd
KN agSZX340 700816llA@ hz-zdcp 700816AbCd
航班管家出票平台:
V2接口:
测试账号已开通
网关账号:huazhong
密钥:13835351728
测试网关:http://27.17.10.210:24880
后台地址:http://27.17.10.210:24880/distribution/merchant/#/login
账号:huazhong
密码:Gms&3buqu
dify deepseek 帐号: https://platform.deepseek.com/api_keys
deepseek difykey sk-06b21eace1374886a8b221d76d075c81
dify app local key: app-GLMHSZ8AYel1xOYpYi3LoDd7
https://api.deepseek.com
IDEAsk-10d5f095ab8047b4a6042708289f9d7e
118.25.129.153 344656718@qq.com gms3buqu 曾用:abcd1234
招商银行企业银行:
招商银行北京宣武门支行 110920617110401
zhaoxiaoting: 20121027
changjunqiang:30751789
BSP银行帐号:
中国银行新乡荣校东路支行
户名:北京融硕智汇科技有限公司
账号:257297883315
cjq13520830938 gms3buqu
zt15137323323 gms3buqu
aliyun ak:
LTAI5tJvTU7vg1KSQtJS95nw
CiCQcmjCI81XwLbQW4RkE4lvfuAeoU
票号范围:
781-2813903836 - 2813904135
东航B2T平台子帐号:
登录名:sjpek1
密码:sijie*PEK12345
德付通操作员:
操作员名称: info@rszhihui.com-mh01
绑定手机号: 16650329062
密码:shuang2025
M13843-mh
shuang2025
行啊
BJRS rongshuo gms3buquxinga-> gms3buqu,xinga
rsuser gms3buquxinga
代理人:常军强 gms3buquxinga
1panel.cn
安装:bash -c "$(curl -sSL https://resource.fit2cloud.com/1panel/package/v2/quick_start.sh)"
http://118.25.129.153:1111/safe admin gms3buqu
+3
View File
@@ -0,0 +1,3 @@
1.把ruoyi-piao ruoyi-uia 拿过来
2.把数据库按结构、数据建好
3.因新版本,在IConfigService里加了 public SysConfig selectConfigByConfigKey(String configKey);
+79
View File
@@ -0,0 +1,79 @@
$$OPEN TIPC3
DA
SI:55323/Y6U7I8O9/41
SO
AO
AI:55323:Y6U7I8O9
AN:oldpass/newpass
===================================
AV:
SK:
FD:
FF:
=====PNR订座==============================
nm 1赵婷 F12
rt #查看输入
ig #取消pnr 可用 i
==========================================
TSL:1 当日销售报告 tsl:t/1 小结金额
===票机======================================
DI:1 查看状态
DDI: 授权信息
TOL: 查看票池
ec:1 xc:1 建立控制 退出控制
ti:1 打开输入状态为active
tn:1X/1234567890-67891
tn:1X/2813903836-03845
===出票=======================================
TKTV:1 出票前确认:
ETDZ:1 Electronic Ticket Document Z 通常用来表示“结束”
一般用以下组合命令:
xe5|2rr|dz1 先删除出票时限,再将航段状态变为RR定妥状态,最后dz出票
DETR:TN/票号 或 :NM/名字 或 :NI/身份信息 查看票面 Display Electronic Ticket Record NINumber Identity
RTKT:票号 票的核心状态和航段信息 Retrieve Keep Ticket
想快速看一眼票是不是有效,用 RTKT;需要详细的票面信息做处理或核查,用 DETR
===退票==============================
TRFD:Z/票号/打票机号 航段和客票为 OPEN FOR USE 才可以退,Ticket Refund
!!!!!!
i 这是清缓存,常用。取消你在上一个封口后的所有操作
pat a 这个是查运价。 Passenger Air Tariff [ˈtærɪf]关税; 价格表
RT 中HK状态是正常的。
入价 要在生成 PNR 后操作,在 >SFC:01 后双击。
2rr 让第2行变成 rr 状态
快捷方式:在黑屏上光标处双击,即可将三角到光标的命令执行一次。
CTRL+A 或 cp 是清屏操作。
NM:1常军强
SS MU6641/Z/15NOV/PKXCTU/LL1
TK TL/0000/./PEK309
OSI MU CTCT13303802881
OSI MU CTCM13520830938/P1
SSR FOID/MU/HK/NI410782198008044995/P1
\
NM:1王治懿
SS MU5780/V/17OCT/TFUDIG/LL1/2030 2205
SS MU5779/L/19OCT/DIGTFU/LL1/2245 0010
TK TL/0000/./PEK309
OSI MU CTCT18836272215
OSI MU CTCT13027662456
OSI MU CTCM13027662456/P1
SSR FOID/MU/HK/NI500112199506200035/P1
\
+5
View File
@@ -0,0 +1,5 @@
iata-asd.com 登录账号:
info@rszhihui.com
登录密码:Gms&123buqu
Gmsgwl&123buqu
最新的
+12
View File
@@ -0,0 +1,12 @@
# 进入MySQL容器
docker exec -it mysql bash
# 登录MySQL
mysql -u root -p
# 在MySQL命令行中修改密码
#ALTER USER 'root'@'localhost' IDENTIFIED BY 'Gms2024&123buqu*#@';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'Gms2024&123buqu*#@' WITH GRANT OPTION;
FLUSH PRIVILEGES;
# 退出MySQL
EXIT;
# 退出容器
exit
+256
View File
@@ -0,0 +1,256 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 新增 WebSocket 专用日志格式
log_format websocket '$remote_addr [$time_local] "$request" '
'$status $upstream_status $body_bytes_sent';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name www.airzhihui.com 123.57.71.170;
return 301 https://www.airzhihui.com$request_uri;
}
# HTTPS 服务器
server {
listen 443 ssl http2;
server_name www.airzhihui.com;
# SSL 配置
ssl_certificate /mydata/cert/www.airzhihui.com.pem;
ssl_certificate_key /mydata/cert/www.airzhihui.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# 安全头部
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# 静态资源
root /mydata/www/piao/;
index index.html;
# 前端路由(Vue/React SPA 支持)
location / {
try_files $uri $uri/ /index.html;
}
# 静态头像文件(优先级最高)
location ^~ /api/profile/avatar/ {
alias /mydata/upload/piao/avatar/; # 关键修正:使用宿主机路径
try_files $uri =404;
expires 7d;
access_log off;
add_header Cache-Control "public";
}
# 通用静态资源(排除已单独处理的头像路径)
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
# 排除 /api/profile/avatar/ 路径
if ($request_uri ~* "^/api/profile/avatar/") {
break;
}
expires 30d;
access_log off;
add_header Cache-Control "public";
}
# WebSocket 代理配置
location /api/websocket/eterm {
proxy_pass http://123.57.71.170:1024/websocket/eterm;
# WebSocket 必须配置
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
# 连接超时设置
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 5s;
# 安全控制
# allow 192.168.1.0/24;
# allow 123.57.71.170;
# deny all;
# 日志记录
access_log /var/log/nginx/websocket.log websocket;
}
# 代理HTTP接口
location /api/ {
proxy_pass http://123.57.71.170:1024/;
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_set_header X-Forwarded-Proto $scheme;
}
location /airfly/ {
proxy_pass http://118.25.129.153:1025/airfly/; # 关键:末尾必须加斜杠
# 请求头透传
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_set_header X-Forwarded-Proto $scheme;
# Cookie 路径重写(与后端 context-path 匹配)
proxy_cookie_path /airfly /airfly; # 保持路径一致
# 安全头控制(允许 iframe 嵌入)
proxy_hide_header X-Frame-Options;
add_header Content-Security-Policy "frame-ancestors 'self' www.airzhihui.com";
# 其他优化
proxy_redirect off;
proxy_http_version 1.1;
}
}
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name www.rszhihui.com;
return 301 https://$host$request_uri;
}
# HTTPS 反向代理
server {
listen 443 ssl http2;
server_name www.rszhihui.com;
ssl_certificate /mydata/cert/www.rszhihui.com.pem;
ssl_certificate_key /mydata/cert/www.rszhihui.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
location / {
proxy_pass http://123.57.71.170:8088;
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_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
proxy_connect_timeout 60s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
}
}
# ==============================================
# 新增:AI 子域名配置 ai.rszhihui.com
# ==============================================
# HTTP 重定向到 HTTPSai.rszhihui.com
server {
listen 80;
server_name ai.rszhihui.com;
return 301 https://$host$request_uri;
}
# HTTPS 反向代理 AI 服务:ai.rszhihui.com
server {
listen 443 ssl http2;
server_name ai.rszhihui.com;
# 使用通配符或单独为 ai.rszhihui.com 签发的证书
ssl_certificate /mydata/cert/ai.rszhihui.com.pem; # 建议使用 *.rszhihui.com 或包含 ai.rszhihui.com 的证书
ssl_certificate_key /mydata/cert/ai.rszhihui.com.key;
# SSL 安全配置(同上)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# 安全头:允许被自己的主站嵌入(关键!)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# ✅ 允许被 https://www.rszhihui.com 嵌入
add_header Content-Security-Policy "frame-ancestors 'self' https://www.rszhihui.com;";
# 或者更开放:允许所有来源嵌入(不推荐生产环境)
# add_header Content-Security-Policy "frame-ancestors *;";
# 可选:如果不希望 X-Frame-Options 干扰,可以隐藏或不设置
# proxy_hide_header X-Frame-Options; # 如果后端返回了,可隐藏
# 代理到 AI 服务
location / {
proxy_pass http://118.25.129.153/;
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_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 超时设置
proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 日志(便于调试)
access_log /var/log/nginx/ai_rszhihui_access.log main;
error_log /var/log/nginx/ai_rszhihui_error.log;
}
}
}
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
# 加权限
#chmod +x /mydata/docker/piaoruo.sh
# 停止并移除当前运行的容器
docker stop piaoruo
docker rm piaoruo
# 移除旧的镜像
docker rmi ruopiao
#创建目录权限
mkdir -p /mydata/upload/piao
chmod 777 /mydata/upload/piao
# 进入项目目录
cd /mydata/docker/piaoruo
# 构建新的镜像
docker build -t ruopiao .
# 启动新的容器
docker run -d -p 1024:1024 -e TZ=Asia/Shanghai --network piaonetwork --name piaoruo \
--restart always -v /mydata/upload/piao:/app/upload/piao ruopiao
#建立容器间网络
#docker network disconnect bridge redis mysql
#docker network connect piaonetwork redis
#docker network connect piaonetwork mysql
#docker restart redis mysql piaoruo
#echo "服务已重启,网络配置完成!"
#docker network create piaonetwork
# 将Redis容器连接到这个网络
#docker network disconnect bridge redis
#docker network disconnect piaonetwork redis # 先断开再重连
#docker network connect piaonetwork redis
#docker network disconnect bridge mysql
#docker network connect piaonetwork mysql
# 将Web容器也连接到这个网络
#docker network disconnect bridge piaoruo
#docker network connect piaonetwork piaoruo
#查看网络内容器
#docker network inspect piaonetwork --format '{{range .Containers}}{{.Name}} {{end}}'
# 查看容器的日志
docker logs piaoruo -f
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
#ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'P0i8a1o9@#';
#ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'P0i8a1o9@#';
#FLUSH PRIVILEGES;
#chmod +x /mydata/docker/piaowu/mysql/piaowudbbak.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/mydata/docker/piaowu/mysql/bak"
MYSQL_USER="root"
MYSQL_PASSWORD="P2i0a2o6w@u"
DATABASE_NAME="piaowu"
CONTAINER_NAME="piaowumysql" # 替换为你的MySQL容器名或ID
# 创建备份目录(如果不存在)
mkdir -p $BACKUP_DIR
# 在MySQL容器内部执行 mysqldump 命令
docker exec $CONTAINER_NAME \
sh -c "exec mysqldump -u$MYSQL_USER -p'$MYSQL_PASSWORD' $DATABASE_NAME" > "$BACKUP_DIR/piaoruo_bak_$DATE.sql"
# 检查是否成功导出
if [ $? -eq 0 ]; then
echo "✅ 数据库备份成功: $BACKUP_DIR/piaowu_bak_$DATE.sql"
else
echo "❌ 数据库备份失败"
exit 1
fi
# 删除超过30天的旧备份
find $BACKUP_DIR -type f -name "*.sql" -mtime +30 -exec rm {} \;
#定时执行备份任务 cron
#0 1 * * * /mydata/docker/piaowu/mysql/piaowudbbak.sh >> /mydata/docker/piaowu/mysql/bak.log 2>&1
+58
View File
@@ -0,0 +1,58 @@
重构过程:
新建空项目,然后添加模块,base 先copy src ,再copy pom.xml中依赖部分。
1.在base/admin中重构 net.1024lab.sa 为 com.zhihui 将net.1024lab.sa中的base剪切到com.zhihui下面,再整体替换net.1024lab.sa.base 为 com.zhihui.base ; net.1024lab.sa.admin 为 com.zhihui.admin
2.pom中 <groupId>com.zhihui</groupId>
<artifactId>api</artifactId>
<version>1.0.0</version>
3.在文件中统一替换 net.1024lab.sa 为 com.zhihui
4.在文件net/lab1024/sa/base/module/support/operatelog/core/OperateLogAspect.java做以上的替换
5.修改com.zhihui.base.config.YamlProcessor.java,其中的
//Resource[] resources = resolver.getResources("classpath*:sa-*.yaml");
Resource[] resources = resolver.getResources("classpath*:*.yaml");
6.注意一下base/resources/META-INF/spring.factories。
7.复制 \api\admin\src\main\java\com\zhihui\admin\module\business\piao 到相应business位置。
8.复制 \api\admin\src\main\java\com\zhihui\admin\constant\AdminSwaggerTagConst.java中piao相关部分。
9.复制:com.zhihui.base.common.util.ArgUtil
\api\admin\src\main\java\com\zhihui\admin\config\CtripConfig.java、mybatisplusconfig.java
10.前端:\web\src\api\business\piao 复制。\web\src\views\business\piao 复制。
\web\src\assets\js\cities.js
11.端口更改在 vite.config.js
login.less :
.box-item {
width: 430px;
height: 450px;
12. 菜单的badge:在\web\src\layout\components\side-menu\sub-menu 中修改: </template>
{{ item.menuName }}<a-badge count="5" v-if="item.parentId === 312" />
</a-menu-item>
1. 添加web模块,删除Vite文件,copy,第一次运行: npm install,之后 npm run dev 或 npm run build:prod。
2. 在业务下添加ticket/air数据表,及自动生成的代码。
3.添加一个普通显示页面:
1. 在sa-admin/module/business/下新建一个DataController及相应配套方法.
2. 在sa-ui/api/business/ticket/下建data-api.js,里面要和controller里的方法对应上。
3. 在sa-ui/views/business/ticket下建data-list.vue
4.运行系统,登录后,在菜单管理里加新项:路由填写:/ticket/air/air-list,组件地址写:/business/ticket/air/air-list.vue
服务器上web的位置在: /www/
发布生成jar: mvn clean package -Dmaven.test.skip=true -P prod
npm config set registry https://registry.npm.taobao.org
npm config get registry
npm install @vueuse/core
后台获取用户id:SecurityUtils.getUserId()
密码长度最小是5-20
p_order p_ordersplit p_orderdetail关系:
p_order 中 splitids 不为 null 则为拆分订单
p_ordersplit 中 splitids 均为1
p_orderdetail splitid 值为 p_ordersplit 的主键。
疑问:
1. api里如何模拟登录权限。 --取登录 token即可。
+35
View File
@@ -0,0 +1,35 @@
# 允许本地和 Docker 网络连接
bind 0.0.0.0
# 禁用保护模式(如果仅绑定到本地地址,则可以禁用保护模式)
protected-mode no
# 设置 Redis 密码
requirepass Rds123!@$
# 监听端口(默认是 6379
port 6379
# 后台运行(Docker 中通常不需要启用,保持注释即可)
# daemonize no
# 日志级别
loglevel notice
# 日志文件路径(Docker 中通常输出到标准输出,保持注释即可)
# logfile ""
# 数据持久化配置(可选)
# RDB 持久化
save 900 1
save 300 10
save 60 10000
# AOF 持久化(可选)
appendonly yes
# 最大内存限制(可选)
# maxmemory 1gb
# 内存淘汰策略(可选)
# maxmemory-policy allkeys-lru
+3 -1
View File
@@ -1,3 +1,5 @@
SET NAMES utf8mb4;
ALTER DATABASE `piaowu` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- ----------------------------
-- 1、部门表
-- ----------------------------
@@ -644,7 +646,7 @@ create table sys_notice (
-- ----------------------------
insert into sys_notice values('1', '温馨提醒:2018-07-01 若依新版本发布啦', '2', '新版本内容', '0', 'admin', sysdate(), '', null, '管理员');
insert into sys_notice values('2', '维护通知:2018-07-01 若依系统凌晨维护', '1', '维护内容', '0', 'admin', sysdate(), '', null, '管理员');
insert into sys_notice values('3', '若依开源框架介绍', '1', '<p><span style=\"color: rgb(230, 0, 0);\">项目介绍</span></p><p><font color=\"#333333\">RuoYi开源项目是为企业用户定制的后台脚手架框架,为企业打造的一站式解决方案,降低企业开发成本,提升开发效率。主要包括用户管理、角色管理、部门管理、菜单管理、参数管理、字典管理、</font><span style=\"color: rgb(51, 51, 51);\">岗位管理</span><span style=\"color: rgb(51, 51, 51);\">、定时任务</span><span style=\"color: rgb(51, 51, 51);\">、</span><span style=\"color: rgb(51, 51, 51);\">服务监控、登录日志、操作日志、代码生成等功能。其中,还支持多数据源、数据权限、国际化、Redis缓存、Docker部署、滑动验证码、第三方认证登录、分布式事务、</span><font color=\"#333333\">分布式文件存储</font><span style=\"color: rgb(51, 51, 51);\">、分库分表处理等技术特点。</span></p><p><img src=\"https://foruda.gitee.com/images/1773931848342439032/a4d22313_1815095.png\" style=\"width: 64px;\"><br></p><p><span style=\"color: rgb(230, 0, 0);\">官网及演示</span></p><p><span style=\"color: rgb(51, 51, 51);\">若依官网地址:&nbsp;</span><a href=\"http://ruoyi.vip\" target=\"_blank\">http://ruoyi.vip</a><a href=\"http://ruoyi.vip\" target=\"_blank\"></a></p><p><span style=\"color: rgb(51, 51, 51);\">若依文档地址:&nbsp;</span><a href=\"http://doc.ruoyi.vip\" target=\"_blank\">http://doc.ruoyi.vip</a><br></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【不分离版】:&nbsp;</span><a href=\"http://demo.ruoyi.vip\" target=\"_blank\">http://demo.ruoyi.vip</a></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【分离版本】:&nbsp;</span><a href=\"http://vue.ruoyi.vip\" target=\"_blank\">http://vue.ruoyi.vip</a></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【微服务版】:&nbsp;</span><a href=\"http://cloud.ruoyi.vip\" target=\"_blank\">http://cloud.ruoyi.vip</a></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【移动端版】:&nbsp;</span><a href=\"http://h5.ruoyi.vip\" target=\"_blank\">http://h5.ruoyi.vip</a></p><p><br style=\"color: rgb(48, 49, 51); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 12px;\"></p>', '0', 'admin', sysdate(), '', null, '管理员');
insert into sys_notice values('3', '若依开源框架介绍', '1', '<p>岗位管理、定时任务、服务监控、登录日志、操作日志、代码生成等功能。其中,还支持多数据源、数据权限、国际化、Redis缓存、Docker部署、滑动验证码、第三方认证登录、分布式事务、、分库分表处理等技术特点。</p>', '0', 'admin', sysdate(), '', null, '管理员');
-- ----------------------------
+9
View File
@@ -1,3 +1,12 @@
/*
Navicat Premium Data Transfer
Source Server Type : MySQL
Source Server Version : 80044
Target Server Type : MySQL
Target Server Version : 80044
File Encoding : 65001
*/
SET NAMES utf8mb4;
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
File diff suppressed because it is too large Load Diff
+10779 -258
View File
File diff suppressed because one or more lines are too long
+92 -5
View File
@@ -1,7 +1,34 @@
SET FOREIGN_KEY_CHECKS = 0;
DELETE FROM `sys_menu`;
LOCK TABLES `sys_menu` WRITE;
truncate table `sys_dept`;
INSERT INTO `sys_dept` VALUES (100, 0, '0', '北京融硕智汇科技', 0, 'CEO', '13520830938', 'info@rszhihui.com', '0', '0', 'admin', '2025-04-11 13:51:33', '', NULL);
INSERT INTO `sys_dept` VALUES (101, 100, '0,100', '北京总公司', 1, '总经理', '13520830938', 'info@rszhihui.com', '0', '0', 'admin', '2025-04-11 13:51:33', '', NULL);
INSERT INTO `sys_dept` VALUES (102, 100, '0,100', '新乡分公司', 2, '总经理', '13837313963', 'info@rszhihui.com', '0', '0', 'admin', '2025-04-11 13:51:33', '', NULL);
INSERT INTO `sys_dept` VALUES (103, 101, '0,100,101', '研发部门', 1, '经理', '13837313963', 'info@rszhihui.com', '0', '0', 'admin', '2025-04-11 13:51:33', '', NULL);
INSERT INTO `sys_dept` VALUES (104, 101, '0,100,101', '市场部门', 2, '经理', '13837313963', 'info@rszhihui.com', '0', '0', 'admin', '2025-04-11 13:51:33', '', NULL);
INSERT INTO `sys_dept` VALUES (105, 101, '0,100,101', '测试部门', 3, '经理', '13837313963', 'info@rszhihui.com', '0', '0', 'admin', '2025-04-11 13:51:33', '', NULL);
INSERT INTO `sys_dept` VALUES (106, 101, '0,100,101', '财务部门', 4, '经理', '13837313963', 'info@rszhihui.com', '0', '0', 'admin', '2025-04-11 13:51:33', '', NULL);
INSERT INTO `sys_dept` VALUES (107, 101, '0,100,101', '运维部门', 5, '经理', '13837313963', 'info@rszhihui.com', '0', '0', 'admin', '2025-04-11 13:51:33', '', NULL);
INSERT INTO `sys_dept` VALUES (108, 102, '0,100,102', '市场部门', 1, '经理', '13837313963', 'info@rszhihui.com', '0', '0', 'admin', '2025-04-11 13:51:33', '', NULL);
INSERT INTO `sys_dept` VALUES (109, 102, '0,100,102', '财务部门', 2, '若依', '13837313963', 'info@rszhihui.com', '0', '0', 'admin', '2025-04-11 13:51:33', '', NULL);
truncate table `sys_job`;
INSERT INTO `sys_job` VALUES (1, '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', '1', 'admin', '2025-04-11 13:51:41', '', NULL, '');
INSERT INTO `sys_job` VALUES (2, '系统默认(有参)', 'DEFAULT', 'ryTask.ryParams(\'ry\')', '0/15 * * * * ?', '3', '1', '1', 'admin', '2025-04-11 13:51:41', '', NULL, '');
INSERT INTO `sys_job` VALUES (3, '系统默认(多参)', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)', '0/20 * * * * ?', '3', '1', '1', 'admin', '2025-04-11 13:51:41', '', NULL, '');
INSERT INTO `sys_job` VALUES (100, '携程订单', 'DEFAULT', 'orderRobot.xiecheng', '0 */10 * * * ?', '1', '1', '1', 'admin', '2024-07-19 02:30:34', 'admin', '2026-03-08 11:10:49', '执行频率');
INSERT INTO `sys_job` VALUES (101, '同程订单', 'DEFAULT', 'orderRobot.tongcheng', '0 */20 * * * ?', '1', '1', '1', 'admin', '2024-07-19 02:31:46', 'admin', '2025-04-11 16:23:19', '执行频率20分钟');
INSERT INTO `sys_job` VALUES (103, '同城退单', 'DEFAULT', 'refundRobot.tongtui', '0 */10 * * * ?', '1', '0', '1', 'admin', '2024-10-03 22:56:17', 'admin', '2025-04-11 16:23:30', '同城退单10分钟同期');
INSERT INTO `sys_job` VALUES (104, '同城改期', 'DEFAULT', 'changeRobot.tonggai', '0 */10 * * * ?', '1', '0', '1', 'admin', '2024-10-06 00:04:25', 'admin', '2025-04-11 16:23:36', '同城改期10分钟周期');
truncate table `sys_role`;
INSERT INTO `sys_role` VALUES (1, '超级管理员', 'admin', 1, '1', 1, 1, '0', '0', 'admin', '2025-04-11 13:51:34', '', NULL, '超级管理员');
INSERT INTO `sys_role` VALUES (2, '普通角色', 'common', 2, '2', 1, 1, '0', '0', 'admin', '2025-04-11 13:51:34', '', NULL, '普通角色');
INSERT INTO `sys_role` VALUES (3, '技术角色', 'techrole', 3, '3', 0, 0, '0', '0', 'admin', '2026-03-05 09:13:39', 'admin', '2026-03-24 21:08:13', NULL);
INSERT INTO `sys_role` VALUES (4, '销售角色', 'sale', 4, '3', 0, 0, '0', '0', 'admin', '2026-03-05 09:14:12', 'admin', '2026-04-06 23:11:09', NULL);
truncate table `sys_menu`;
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query`, `route_name`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES
-- 一级菜单
(1, '系统管理', 0, 9, 'system', NULL, '', '', 1, 0, 'M', '0', '0', '', 'setting', 'admin', '2024-06-08 09:48:12', 'admin', '2026-05-06 21:13:56', '系统管理目录'),
@@ -23,7 +50,7 @@ INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`
(106, '参数设置', 1, 7, 'config', 'system/config/index', '', '', 1, 0, 'C', '0', '0', 'system:config:list', 'edit', 'admin', '2024-06-08 09:48:12', '', NULL, '参数设置菜单'),
(107, '通知公告', 1, 8, 'notice', 'system/notice/index', '', '', 1, 0, 'C', '0', '0', 'system:notice:list', 'message', 'admin', '2024-06-08 09:48:12', '', NULL, '通知公告菜单'),
(108, '日志管理', 1, 9, 'log', '', '', '', 1, 0, 'M', '0', '0', '', 'history', 'admin', '2024-06-08 09:48:12', 'admin', '2026-05-07 08:34:33', '日志管理菜单'),
(3, '系统工具', 1, 3, 'tool', NULL, '', '', 1, 0, 'M', '0', '0', '', 'tool', 'admin', '2024-06-08 09:48:12', 'admin', '2026-05-07 08:21:36', '系统工具目录'),
(3, '系统工具', 1, 8, 'tool', NULL, '', '', 1, 0, 'M', '0', '0', '', 'tool', 'admin', '2024-06-08 09:48:12', 'admin', '2026-05-07 08:21:36', '系统工具目录'),
-- 系统监控下的菜单
(109, '在线用户', 2, 1, 'online', 'monitor/online/index', '', '', 1, 0, 'C', '0', '0', 'monitor:online:list', 'online', 'admin', '2024-06-08 09:48:12', '', NULL, '在线用户菜单'),
@@ -92,5 +119,65 @@ INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`
-- 智汇数据下的菜单
(2043, '爬虫任务', 4, 1, 'crawl', 'piao/data/crawl', NULL, '', 1, 0, 'C', '0', '0', '', 'database', 'admin', '2026-05-28 11:22:34', 'admin', '2026-05-28 16:25:49', '');
/*!40000 ALTER TABLE `sys_menu` ENABLE KEYS */;
UNLOCK TABLES;
truncate table `sys_role_menu`;
-- 角色 2 的菜单权限
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES
(2, 1), (2, 2), (2, 3), (2, 4), (2, 100), (2, 101), (2, 102), (2, 103), (2, 104),
(2, 105), (2, 106), (2, 107), (2, 108), (2, 109), (2, 110), (2, 111), (2, 112),
(2, 113), (2, 114), (2, 115), (2, 116), (2, 117), (2, 500), (2, 501), (2, 1000),
(2, 1001), (2, 1002), (2, 1003), (2, 1004), (2, 1005), (2, 1006), (2, 1007),
(2, 1008), (2, 1009), (2, 1010), (2, 1011), (2, 1012), (2, 1013), (2, 1014),
(2, 1015), (2, 1016), (2, 1017), (2, 1018), (2, 1019), (2, 1020), (2, 1021),
(2, 1022), (2, 1023), (2, 1024), (2, 1025), (2, 1026), (2, 1027), (2, 1028),
(2, 1029), (2, 1030), (2, 1031), (2, 1032), (2, 1033), (2, 1034), (2, 1035),
(2, 1036), (2, 1037), (2, 1038), (2, 1039), (2, 1040), (2, 1041), (2, 1042),
(2, 1043), (2, 1044), (2, 1045), (2, 1046), (2, 1047), (2, 1048), (2, 1049),
(2, 1050), (2, 1051), (2, 1052), (2, 1053), (2, 1054), (2, 1055), (2, 1056),
(2, 1057), (2, 1058), (2, 1059), (2, 1060);
-- 角色 3 的菜单权限
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES
(3, 2), (3, 4), (3, 109), (3, 110), (3, 111), (3, 112), (3, 113), (3, 114),
(3, 1046), (3, 1047), (3, 1048), (3, 1049), (3, 1050), (3, 1051), (3, 1052),
(3, 1053), (3, 1054), (3, 2000), (3, 2001), (3, 2002), (3, 2003), (3, 2004),
(3, 2005), (3, 2006), (3, 2007), (3, 2008), (3, 2009), (3, 2010), (3, 2011),
(3, 2012), (3, 2013), (3, 2014), (3, 2015), (3, 2016), (3, 2017), (3, 2018),
(3, 2019), (3, 2020), (3, 2021), (3, 2022), (3, 2023), (3, 2024), (3, 2025),
(3, 2026), (3, 2027), (3, 2028), (3, 2029), (3, 2030);
-- 角色 4 的菜单权限
INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) VALUES
(4, 2003), (4, 2004), (4, 2005), (4, 2011), (4, 2012), (4, 2025), (4, 2030),
(4, 2031), (4, 2032), (4, 2033), (4, 2034), (4, 2035);
truncate table `sys_user`;
INSERT INTO `sys_user` VALUES (1, 103, 'admin', '常军强', '00', '344656718@qq.com', '13520830938', '0', '/profile/avatar/2025-04-12/1527155022844_20250412002436A001.jpg', '$2a$10$dNiVc4PA1gX7LHz5f1Y1gO./RHMNTNYaNf5D/1J6w5.cw7Zau8p3C', '0', '0', '223.88.107.31', sysdate(), sysdate(), 'admin', sysdate(), '', null, '管理员');
INSERT INTO `sys_user` VALUES (2, 105, 'zhihui', '智汇票务员', '00', 'zhihui@qq.com', '15666666666', '1', '/images/defaultavatar.png', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), sysdate(), 'admin', sysdate(), '', null, '管理员');
INSERT INTO `sys_user` VALUES (3, 102, 'lizikang', '李梓康', '00', '', '', '0', '', '$2a$10$EypsMFjMJTAO5cgUmVd2HeAqBx/5U/jltXw8H25dfHjDbq2eqE7NW', '0', '0', '42.229.70.66', sysdate(), sysdate(), 'admin', sysdate(), '', null, '管理员');
INSERT INTO `sys_user` VALUES (4, 102, 'guohao', '郭豪', '00', '515210848@qq.com', '15670590335', '0', '', '$2a$10$tYac19iPk/7XmWIMB.WPxuyAEH/UHcIrcuOivqhBqqYpQ3uCqrwVW', '0', '0', '42.226.8.138', sysdate(), sysdate(), 'admin', sysdate(), '', null, '管理员');
INSERT INTO `sys_user` VALUES (5, 102, 'shuangfang', '双方', '00', '', '', '0', '', '$2a$10$gGZur5c.HCt4dDWoSRf8K.WJQvXD.XMxlKKq94pDR7D66FOS/plGa', '0', '0', '223.88.108.80', sysdate(), sysdate(), 'admin', sysdate(), '', null, '管理员');
INSERT INTO `sys_user` VALUES (6, 108, 'zhangyang', '张洋', '00', '', '', '0', '', '$2a$10$Sm7loHUoHbFFKLBYKMYz/eVZKVBuwGwrKU7qE9qVY5d0HqJvbyjf6', '0', '0', '59.152.38.195', sysdate(), sysdate(), 'admin', sysdate(), '', null, '管理员');
INSERT INTO `sys_user` VALUES (7, 109, 'zhaoting', '赵婷', '00', '', '15137323323', '1', '', '$2a$10$rlruoOZEDU5joZ4StIAfK.GXrzqaooN2bDljpqNWzNxBA7YieY2pq', '0', '0', '223.88.107.89', sysdate(), sysdate(), 'admin', sysdate(), '', null, '管理员');
truncate table `sys_user_post`;
INSERT INTO `sys_user_post` VALUES (1, 1);
INSERT INTO `sys_user_post` VALUES (2, 2);
INSERT INTO `sys_user_post` VALUES (3, 2);
INSERT INTO `sys_user_post` VALUES (4, 2);
INSERT INTO `sys_user_post` VALUES (5, 2);
INSERT INTO `sys_user_post` VALUES (6, 2);
INSERT INTO `sys_user_post` VALUES (7, 1);
INSERT INTO `sys_user_post` VALUES (7, 2);
truncate table `sys_user_role`;
INSERT INTO `sys_user_role` VALUES (1, 1);
INSERT INTO `sys_user_role` VALUES (2, 2);
INSERT INTO `sys_user_role` VALUES (3, 3);
INSERT INTO `sys_user_role` VALUES (4, 4);
INSERT INTO `sys_user_role` VALUES (5, 4);
INSERT INTO `sys_user_role` VALUES (6, 4);
INSERT INTO `sys_user_role` VALUES (7, 4);
SET FOREIGN_KEY_CHECKS = 0;
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

+84
View File
@@ -0,0 +1,84 @@
1. 联系中国航信开始培训,取得三人份证书。
2. 向iata-asd平台提交材料申请。
3. 办理中航鑫港担保函(50+10押金)。
4. 与国际航协签订代理销售协议,缴纳IATA年费,取得国际航协GoStandard代理人资质。
5. 与BSP清算银行(中国银行)签订直接借记业务授权。
6. 与GDS(中国航信)申请OfficeCode及开通工作号、通道号。
7. 与各航空公司联系取得出票授权。
8. 与OTA合作,获取订单,开始运营。
ASD平台->票证->申请电子客票,填写申请数量(试算700元一张)。
完成天翼云上运行北京地区 ETERM 和共翔天翼系统
9.2025年11月24日 国际航协完成第一次扣款。1232 元
---------------------------
10.实现airzhihui系统从docker分散模式向dockercompose模式升级。
更新前端html只需要将文件上传到www目录,更新jar只需要 docker compose up -d --build ,如要重新安装数据库down 时 加 -v 取消挂载
11.实现白屏通过BOP德付通进行扣款。
12.白屏统计报表自动化方案:WinForm中使用 FlatUI操作共翔天翼,用VNC在服务器上登录解决RDP关闭无Session显示问题。
资金使用情况:
易出行: 10万元 -理财 1000每月,20万一个月使用权。1.31利率
中航鑫港 10万元押金 -公司账
东航B2T 5万元-押金
去哪儿OTA主站 5万元-押金2025.12.25北京趣拿软件科技有限公司 2026.1.27分销账号充值20000元(原5000押金,后变为40000)
易宝支付
7:==============================
-1:东方航空:MU 781http://travel.ceair.com/ 申请成功,注册码:2025060443507, 已交押金5万元,2025.6.10
账号:info@rszhihui.com Gmsgwl&3buqu 已改为: Gmsgwl&3buqumu -> Gms&3buqumu->Gms&3buqu2026
-2:联合航空:https://b2b.flycua.com 申请: changjunqiang Gms&3buqu 已申请未收到回复。
https://b2t.flycua.com
m.flycua.com/bsp/login PEK309 CUA123!-> Gms&cua2026
已加KN代理人钉钉群: 101130003531 已通过
成都航空: 18686687480 北部大区 ,已联系上。已发送书面申请和电子文档。对方说等3大签后再签
华夏航空: 微信,已联系上。星罗平台:https://new.g5sky.com/
厦门航空:https://b2b.xiamenair.cn/ 已注册 PEK_XM309 Gms&3buqu 但登录不上去。95557 河北航空江西航空一起申请 BSP负责人,王珊 0311-89193171
qq: 2667291814 周亚辉 010-58297111 已联系上,充值10万 + 2万押金。
南方航空:maruia@csair.com 联系到邮件。
中国国航:已联系上,材料准备中。 010-87415273 heye2023@airchina.com
山东航空:https://scnewb2b.travelsky.com.cn 申请: changjunqiang Gms&3buqu 已联系上财务QQ
吉祥航空:010-85306249 北京区不开国内。
深圳航空:18684841078 G00733@SHENZHENAIR.COM,让先申请国航,开通后就可以跟随开通BSP
乌鲁木齐航空:https://b2b.urumqi-air.com/ 开始申请 changjunqiang Gms&3buqu
重庆航空:023-88197016 董真 无人接听
无人接听 信息来自asd网站,
四川航空
https://3u.travelsky.com.cn/3uagent/index.html#/unauth/login
B2B用户名:changjunqiang 密码:Gms&3buqu
开户申请已提交,请等待航空公司审核,审核的结果会通过短信,邮件的方式通知你。
8:==============================
>同程:已获取相关联系人手机,
>携程:已发送邮件到xcfx@trip.com
>去哪儿:2025年12月25日 去哪儿平台开始上线
www.qunar.com 13837313963 Gms3buqu
1.主站商户管理后台,登录地址:https://mppm.qunar.com/qunarMerchantManager/login.do
登录名:FLIGHTTTS105082076 登录密码:ubZ8rl9O
2.统一服务平台,https://fuwu.qunar.com 13837313963 sgbakqs2629 Gms&3buququnar
3.open.qunar.com
4.分销账务后台:https://mppm.qunar.com/qunarMerchantManager/login.do
登录名:newqudzfm 登录密码:SKAMhFk6
Appid : 10103
key:baef662549367303e69046a01f8949c1
token:a6f48e4e8abe1349f49a20bb30e1b4b0
>航班管家:测试账号已开通
网关账号:rongshuo 在GuanjiaTokenService 中定义使用
密钥:18222557743 网站密码:Gms&3buqu
测试网关:http://27.17.10.210:24880
后台地址:http://27.17.10.210:24880/distribution/merchant/#/login
北京税务局网站-》 社保业务 -》 日常申报 -》
+52
View File
@@ -0,0 +1,52 @@
1. <a-radio-button value="1">本地</a-radio-button>
在JS中的这种值比较 要用 vvv.value === '1'
2.当api中拿不到json数据时,可以将调用方法设置为async异步,即可获取。
3.未解决: 从携程拿到的PNR小编如何换成大编PNR去易宝支付GetPrice。
4.未解决:新增特殊政策报错:政策集合为空或政策字段格式错误,如何解决。
5.解决了prod环境页面刷新的问题,VITE_BASE_URL = '/',原先是'./'
6.解决了npm run dev启动慢的问题,在于浏览器禁用了缓存。
7.vue项目中图片放到 /public ,可以在代码里通过 / 定位。而不是 /src/assets/下,
8.解决了拆分订单在订单列表默认不打开的问题,原因在于:const listData = ref([{}]); 和 const listData = ref([]); 有区别,
应该使用前者。
9.a-table 的hover问题,是需要定义到cell,就可以不闪了:
.ddTable .ant-table-tbody .ant-table-cell:hover{ background-color: #0aff00; }
10.完成mybatisplus日志的显示与隐藏:在application.yaml 中设置:
log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl
#org.apache.ibatis.logging.stdout.StdOutImpl
11.实现前端代码对于角色的判断:
<a-button :disabled="!$store.state.roles.includes('admin')">
12.完成利用vue-cropper@1.0.5实现图片的裁剪功能,彻底完成。
13.向sys_user 表中加入 rate 字段。
已完成:
模拟降舱功能。
特政时间设置问题。
按钮权限功能设置。
日志功能添加。
同程推送接口。
解决之前注释掉modules/settings.js 的问题,又加上了。src/settings.js 改为: export default {
实现了线上https 的改造,api 用 ip 反向代理。
}
1.若依使用redis作消息队列。已完成。
1List方式:TongSpecialController 中: callbackAdd(@RequestBody JSONObject jsonObj)方法
messageProducerService.sendListMessage 发送List消息。然后在 getCallbackInfo方法中取消息:
String ttBack = stringRedisTemplate.opsForList().rightPop(pokey);
2:发布订阅方式:
1.在订单列表里看政策详情页面。
2.退票列表里开始退票流程。
3.从差务系统里发布机票订单(接口方式)。 完成
4.已完成项目的ICON所有显示功能。
几个关键问题:
1.eterm 查询 接口
2.IBE接口
3.订单推送接口。
目前遇到问题:
1:航司授权。
2OTA平台申请。
3:业务模型。
+41 -41
View File
@@ -1,27 +1,27 @@
services:
piaoruo:
web:
build:
context: /mydata/docker/piaoruo
dockerfile: /mydata/docker/piaoruo/Dockerfile
image: ruopiao:1.0
container_name: piaoruo
context: /mydata/docker/piaowu
dockerfile: /mydata/docker/piaowu/Dockerfile
image: piaowu:1.0
container_name: piaowu
ports:
- "1024:1024"
environment:
- TZ=Asia/Shanghai
- SPRING_DATASOURCE_URL=jdbc:mysql://piaomysql:3306/piaoruo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/piaowu?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=P0i8a1o9@#()
- SPRING_REDIS_HOST=piaoredis
- SPRING_REDIS_PASSWORD=Rds123!@$
- SPRING_DATASOURCE_PASSWORD=P2i0a2o6w@u
- SPRING_REDIS_HOST=piaowuredis
- SPRING_REDIS_PASSWORD=Rds234!@$
volumes:
- /mydata/docker/piaoruo/ruopiao.jar:/app/ruopiao.jar # jar 包挂载
- /mydata/docker/piaoruo/www:/app/upload/www # 前端文件挂载
- /mydata/docker/piaoruo/upload:/app/upload/piao
- /mydata/docker/piaoruo/upload/json:/app/upload/json
- /mydata/docker/piaoruo/upload/logs:/app/upload/logs
- /mydata/docker/piaowu/piaowu.jar:/app/piaowu.jar # jar 包挂载
- /mydata/docker/piaowu/www:/app/upload/www # 前端文件挂载
- /mydata/docker/piaowu/upload:/app/upload/piaowu
- /mydata/docker/piaowu/upload/json:/app/upload/json
- /mydata/docker/piaowu/upload/logs:/app/upload/logs
networks:
- piaonet
- piaowunet
restart: on-failure:3
depends_on:
mysql:
@@ -31,29 +31,29 @@ services:
redis:
image: redis
container_name: piaoredis
container_name: piaowuredis
volumes:
- redis-data:/data
command: redis-server --appendonly yes --requirepass Rds123!@$ --loglevel warning
- redis-data-piaowu:/data/redis
command: redis-server --appendonly yes --requirepass Rds234!@$ --loglevel warning
environment:
- TZ=Asia/Shanghai
networks:
- piaonet
- piaowunet
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "-a", "Rds123!@$", "ping"]
test: ["CMD", "redis-cli", "-a", "Rds234!@$", "ping"]
timeout: 3s
retries: 5
mysql:
image: mysql:8.0
container_name: piaomysql
container_name: piaowumysql
ports:
- "3306:3306" # ✅ 已支持远程访问(端口映射)
- "3309:3306" # ✅ 已支持远程访问(端口映射)
environment:
- MYSQL_ROOT_PASSWORD=P0i8a1o9@#()
- MYSQL_ROOT_PASSWORD=P2i0a2o6w@u
- TZ=Asia/Shanghai
- MYSQL_DATABASE=piaoruo
- MYSQL_DATABASE=piaowu
- MYSQL_CHARSET=utf8mb4
- MYSQL_COLLATION=utf8mb4_unicode_ci
command:
@@ -65,62 +65,62 @@ services:
- --bind-address=0.0.0.0 # ✅ 关键:允许远程连接
volumes:
- ./mysql/sql:/docker-entrypoint-initdb.d # 初始化脚本
- mysql-data:/var/lib/mysql # ✅ 关键:数据持久化卷
- mysql-data-piaowu:/var/lib/mysql # ✅ 关键:数据持久化卷
- ./mysql/conf:/etc/mysql/conf.d # 自定义配置目录
networks:
- piaonet
- piaowunet
restart: unless-stopped
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-pP0i8a1o9@#()"]
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-pP2i0a2o6w@u"]
timeout: 10s
retries: 10
start_period: 30s
nginx:
image: nginx:alpine
container_name: piaonginx
container_name: piaowunginx
ports:
- "8089:80"
volumes:
- ./www:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro
networks:
- piaonet
- piaowunet
restart: unless-stopped
depends_on:
- piaoruo
- web
gitea:
image: gitea/gitea:latest
container_name: piaogitea
image: gitea/gitea
container_name: piaowugitea
ports:
- "3001:3000" # Web 访问端口
- "2223:22" # SSH 端口(避免与服务器 SSH 22 端口冲突)
- "3000:3000" # Web 访问端口
- "222:22" # SSH 端口(避免与服务器 SSH 22 端口冲突)
environment:
- TZ=Asia/Shanghai
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=mysql
- GITEA__database__HOST=piaomysql:3306
- GITEA__database__HOST=mysql:3306
- GITEA__database__NAME=gitea
- GITEA__database__USER=root
- GITEA__database__PASSWD=P0i8a1o9@#()
volumes:
- gitea-data:/data
- gitea-data-piaowu:/data/gitea
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
networks:
- piaonet
- piaowunet
restart: unless-stopped
depends_on:
mysql:
condition: service_healthy
volumes:
redis-data: {} # 空对象表示使用默认配置
mysql-data: {} # 空对象表示使用默认配置
gitea-data: {} # Gitea 数据持久化
redis-data-piaowu: {} # 空对象表示使用默认配置
mysql-data-piaowu: {} # 空对象表示使用默认配置
gitea-data-piaowu: {} # Gitea 数据持久化
networks:
piaonet:
piaowunet:
driver: bridge
+1 -1
View File
@@ -69,7 +69,7 @@ http {
# 2. 头像静态资源
location /api/profile/avatar/ {
alias /mydata/docker/piaoruo/upload/avatar/;
alias /mydata/docker/piaowu/upload/avatar/;
try_files $uri =404;
expires 7d;
access_log off;
+1 -2
View File
@@ -10,7 +10,7 @@
<name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description>
<description>智汇票务管理系统</description>
<properties>
<ruoyi.version>3.9.2</ruoyi.version>
@@ -36,7 +36,6 @@
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!-- SpringBoot的依赖配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
+2 -13
View File
@@ -15,18 +15,6 @@
票务API入口
</description>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>2.0.0-RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- spring-boot-devtools -->
@@ -205,6 +193,7 @@
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>2.0.0-RC1</version>
</dependency>
</dependencies>
@@ -234,7 +223,7 @@
</configuration>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
<finalName>piaowu</finalName>
</build>
</project>
@@ -9,12 +9,12 @@ import org.springframework.scheduling.annotation.EnableAsync;
*/
@SpringBootApplication
@EnableAsync
public class RuoPiaoApplication
public class PiaoWuApplication
{
public static void main(String[] args)
{
// System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoPiaoApplication.class, args);
SpringApplication.run(PiaoWuApplication.class, args);
System.out.println(">>若票系统启动成功 :-) \n" +
" ____ ____ _\n" +
" | _ \\ _ _ ___ | _ \\ (_) __ _ ___\n" +
@@ -8,11 +8,11 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
*
* @author ruoyi
*/
public class RuoPiaoServletInitializer extends SpringBootServletInitializer
public class PiaoWuServletInitializer extends SpringBootServletInitializer
{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return application.sources(RuoPiaoApplication.class);
return application.sources(PiaoWuApplication.class);
}
}
@@ -0,0 +1,204 @@
package com.ruoyi.piao.controller;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.piao.domain.ResponseDTO;
import com.ruoyi.piao.domain.entity.Change;
import com.ruoyi.piao.domain.entity.Order;
import com.ruoyi.piao.domain.entity.Refund;
import com.ruoyi.piao.service.ChangeService;
import com.ruoyi.piao.service.OrderService;
import com.ruoyi.piao.service.RefundService;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.*;
@RestController
@RequestMapping("/ai")
public class AIController {
private static List<Map<String, Object>> hotlineCache = null;
private static LocalDateTime hotlineCacheTime = null;
private static final long CACHE_DURATION_HOURS = 1;
@Resource
private OrderService orderService;
@Autowired
private RefundService refundService;
@Autowired
private ChangeService changeService;
@Resource
private ChatClient chatClient;
@Anonymous
@GetMapping("/hotline")
public ResponseDTO<List<Map<String, Object>>> hotline() {
if (hotlineCache != null && hotlineCacheTime != null
&& LocalDateTime.now().minusHours(CACHE_DURATION_HOURS).isBefore(hotlineCacheTime)) {
return ResponseDTO.ok(hotlineCache);
}
String prompt = "你是一个机票票务AI助手。请根据当前中国民航市场情况,生成当前最热门的国内航线列表。" +
"请直接返回JSON数组,不要加markdown代码块标记,格式为:[{\"route\": \"北京-上海\", \"reason\": \"商务航线,客流量大\", \"rank\": 1}]。" +
"返回8条,按热门程度排序,每条reason用中文简要描述热门原因。";
String aiResponse = chatClient.prompt()
.system("你是一个民航数据分析助手,只返回纯JSON数组,不要任何其他文字和markdown标记。")
.user(prompt)
.call()
.content();
if (aiResponse != null) {
aiResponse = aiResponse.trim();
if (aiResponse.startsWith("```")) {
aiResponse = aiResponse.replaceAll("```json\\s*", "").replaceAll("```\\s*", "").trim();
}
}
try {
if (aiResponse != null) {
List<Map<String, Object>> list = JSON.parseObject(aiResponse, new com.alibaba.fastjson.TypeReference<List<Map<String, Object>>>(){});
if (list != null && !list.isEmpty()) {
hotlineCache = list;
hotlineCacheTime = LocalDateTime.now();
return ResponseDTO.ok(list);
}
}
} catch (Exception ignored) {}
if (hotlineCache != null) {
return ResponseDTO.ok(hotlineCache);
}
List<Map<String, Object>> fallback = new ArrayList<>();
Map<String, Object> item = new HashMap<>();
item.put("route", "北京-上海");
item.put("reason", "热门商务航线");
item.put("rank", 1);
fallback.add(item);
item = new HashMap<>();
item.put("route", "广州-深圳");
item.put("reason", "热门商务航线");
item.put("rank", 2);
fallback.add(item);
return ResponseDTO.ok(fallback);
}
@Anonymous
@GetMapping("/chat")
public String chat(@RequestParam String message,
@RequestParam(required = false) String context) {
StringBuilder systemPrompt = new StringBuilder("你是一个机票票务系统的AI助手,帮助用户解答关于票务系统的问题。" +
"用中文回答,简洁清晰,必要时可以给出数据统计。");
if (StrUtil.isNotBlank(context)) {
JSONObject ctx = JSON.parseObject(context);
String route = ctx.getString("route");
String pageTitle = ctx.getString("title");
if (StrUtil.isNotBlank(pageTitle)) {
systemPrompt.append("\n用户当前在「").append(pageTitle).append("」页面。");
}
if (route != null) {
systemPrompt.append(injectPageData(route));
}
Object pageDataObj = ctx.get("data");
if (pageDataObj != null) {
String pageData = pageDataObj instanceof String ? (String) pageDataObj : pageDataObj.toString();
systemPrompt.append("\n页面自定义数据:").append(pageData);
}
}
return chatClient.prompt()
.system(systemPrompt.toString())
.user(message)
.call()
.content();
}
private String injectPageData(String route) {
StringBuilder sb = new StringBuilder();
try {
if (route.contains("/order") || route.contains("/sale")) {
long pendingCount = orderService.lambdaQuery().eq(Order::getStatus, "1").count();
long issuingCount = orderService.lambdaQuery().eq(Order::getStatus, "21").count();
if (pendingCount > 0) {
List<Order> urgent = orderService.lambdaQuery()
.eq(Order::getStatus, "1")
.orderByAsc(Order::getLimittime)
.last("LIMIT 5")
.list();
sb.append("\n待处理订单共").append(pendingCount).append("单,出票中").append(issuingCount).append("单。");
if (!urgent.isEmpty()) {
sb.append("\n最紧急的5单:");
for (Order o : urgent) {
sb.append("\n- 订单").append(o.getId())
.append(" 航班").append(o.getFlightNumber())
.append(" ").append(o.getDepCode()).append("").append(o.getArrCode())
.append(" 金额").append(o.getAmount())
.append(" 最晚出票").append(o.getLimittime());
}
}
}
}
if (route.contains("/order/list")) {
sb.append("\n可查询订单列表、状态、金额等信息。");
}
if (route.contains("/order/waiting") || route.contains("/order/urgent")) {
long waiting = orderService.lambdaQuery().eq(Order::getStatus, "1").count();
sb.append("\n待处理订单").append(waiting).append("单。");
}
if (route.contains("/order/mine")) {
sb.append("\n这是我的订单页面,可查询当前用户认领的订单。");
}
if (route.contains("/refund")) {
long refundPending = refundService.lambdaQuery().eq(Refund::getRefundStatus, 0).count();
sb.append("\n待退票共").append(refundPending).append("单。");
}
if (route.contains("/change")) {
long changePending = changeService.lambdaQuery().eq(Change::getChangeStatus, 0).count();
sb.append("\n待改签共").append(changePending).append("单。");
}
if (route.contains("/report")) {
sb.append("\n这是报表页面,可查询业绩、利润、结算等统计数据。");
}
if (route.contains("/config")) {
sb.append("\n这是配置管理页面,包含航空公司、舱位、渠道、客户、航线、规则等配置。");
}
if (route.contains("/sale/list")) {
sb.append("\n这是销售列表页面,可查询待处理销售订单。");
}
if (route.contains("/policy")) {
sb.append("\n这是政策管理页面,包含价格政策、OTA政策等。");
}
if (route.contains("/data/crawl")) {
sb.append("\n这是数据抓取页面,用于管理爬虫任务。");
}
if (route.equals("/home/index") || route.equals("/home") || route.equals("/index")) {
long orderCount = orderService.lambdaQuery().eq(Order::getStatus, "1").count();
long refundCount = refundService.lambdaQuery().eq(Refund::getRefundStatus, 0).count();
long changeCount = changeService.lambdaQuery().eq(Change::getChangeStatus, 0).count();
sb.append("\n首页概览:待处理订单").append(orderCount)
.append("单,待退票").append(refundCount)
.append("单,待改签").append(changeCount).append("单。");
}
} catch (Exception e) {
sb.append("\n(查询业务数据时出现异常)");
}
return sb.toString();
}
}
@@ -2,8 +2,11 @@ package com.ruoyi.piao.controller;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.piao.domain.ResponseDTO;
import com.ruoyi.piao.service.MailService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@@ -14,4 +17,17 @@ public class HomeController {
return ResponseDTO.ok();
}
@Resource
MailService mailService;
@GetMapping("/mail")
@Anonymous
public ResponseDTO<String> sendMail(@RequestParam(defaultValue = "344656718@qq.com") String to,
@RequestParam(defaultValue = "测试邮件") String subject,
@RequestParam(defaultValue = "这是一封测试邮件") String content) {
mailService.sendEmail(to, subject, content);
return ResponseDTO.ok("邮件发送成功");
}
}
@@ -1,7 +1,6 @@
package com.ruoyi.piao.controller;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.annotation.Anonymous;
@@ -17,7 +16,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import java.util.HashMap;
import java.time.LocalDateTime;
import java.util.List;
@@ -191,112 +189,4 @@ public class MessageController {
}
}
@Resource
private ChatClient chatClient;
@GetMapping("/chat")
public String chat(@RequestParam String message,
@RequestParam(required = false) String context) {
StringBuilder systemPrompt = new StringBuilder("你是一个机票票务系统的AI助手,帮助用户解答关于票务系统的问题。" +
"用中文回答,简洁清晰,必要时可以给出数据统计。");
if (StrUtil.isNotBlank(context)) {
JSONObject ctx = JSON.parseObject(context);
String route = ctx.getString("route");
String pageTitle = ctx.getString("title");
if (StrUtil.isNotBlank(pageTitle)) {
systemPrompt.append("\n用户当前在「").append(pageTitle).append("」页面。");
}
if (route != null) {
systemPrompt.append(injectPageData(route));
}
Object pageDataObj = ctx.get("data");
if (pageDataObj != null) {
String pageData = pageDataObj instanceof String ? (String) pageDataObj : pageDataObj.toString();
systemPrompt.append("\n页面自定义数据:").append(pageData);
}
}
return chatClient.prompt()
.system(systemPrompt.toString())
.user(message)
.call()
.content();
}
private String injectPageData(String route) {
StringBuilder sb = new StringBuilder();
try {
if (route.contains("/order") || route.contains("/sale")) {
long pendingCount = orderService.lambdaQuery().eq(Order::getStatus, "1").count();
long issuingCount = orderService.lambdaQuery().eq(Order::getStatus, "21").count();
if (pendingCount > 0) {
List<Order> urgent = orderService.lambdaQuery()
.eq(Order::getStatus, "1")
.orderByAsc(Order::getLimittime)
.last("LIMIT 5")
.list();
sb.append("\n待处理订单共").append(pendingCount).append("单,出票中").append(issuingCount).append("单。");
if (!urgent.isEmpty()) {
sb.append("\n最紧急的5单:");
for (Order o : urgent) {
sb.append("\n- 订单").append(o.getId())
.append(" 航班").append(o.getFlightNumber())
.append(" ").append(o.getDepCode()).append("").append(o.getArrCode())
.append(" 金额").append(o.getAmount())
.append(" 最晚出票").append(o.getLimittime());
}
}
}
}
if (route.contains("/order/list")) {
sb.append("\n可查询订单列表、状态、金额等信息。");
}
if (route.contains("/order/waiting") || route.contains("/order/urgent")) {
long waiting = orderService.lambdaQuery().eq(Order::getStatus, "1").count();
sb.append("\n待处理订单").append(waiting).append("单。");
}
if (route.contains("/order/mine")) {
sb.append("\n这是我的订单页面,可查询当前用户认领的订单。");
}
if (route.contains("/refund")) {
long refundPending = refundService.lambdaQuery().eq(Refund::getRefundStatus, 0).count();
sb.append("\n待退票共").append(refundPending).append("单。");
}
if (route.contains("/change")) {
long changePending = changeService.lambdaQuery().eq(Change::getChangeStatus, 0).count();
sb.append("\n待改签共").append(changePending).append("单。");
}
if (route.contains("/report")) {
sb.append("\n这是报表页面,可查询业绩、利润、结算等统计数据。");
}
if (route.contains("/config")) {
sb.append("\n这是配置管理页面,包含航空公司、舱位、渠道、客户、航线、规则等配置。");
}
if (route.contains("/sale/list")) {
sb.append("\n这是销售列表页面,可查询待处理销售订单。");
}
if (route.contains("/policy")) {
sb.append("\n这是政策管理页面,包含价格政策、OTA政策等。");
}
if (route.contains("/data/crawl")) {
sb.append("\n这是数据抓取页面,用于管理爬虫任务。");
}
if (route.equals("/home/index") || route.equals("/home") || route.equals("/index")) {
long orderCount = orderService.lambdaQuery().eq(Order::getStatus, "1").count();
long refundCount = refundService.lambdaQuery().eq(Refund::getRefundStatus, 0).count();
long changeCount = changeService.lambdaQuery().eq(Change::getChangeStatus, 0).count();
sb.append("\n首页概览:待处理订单").append(orderCount)
.append("单,待退票").append(refundCount)
.append("单,待改签").append(changeCount).append("单。");
}
} catch (Exception e) {
sb.append("\n(查询业务数据时出现异常)");
}
return sb.toString();
}
}
@@ -114,7 +114,7 @@ public class SysConfigController extends BaseController
public AjaxResult editByKeyValue(@PathVariable String key,
@PathVariable String value)
{
SysConfig cfg = configService.selectConfigById(Long.parseLong(key));
SysConfig cfg = configService.selectConfigByConfigKey(key);
if (cfg == null) return error("参数未找到");
cfg.setUpdateBy(getUsername());
cfg.setConfigValue(value);
@@ -7,7 +7,7 @@ ruoyi:
# 版权年份
copyrightYear: 2025
# 上传文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath 或 docker 中的挂载目录)
profile: /app/upload/piao/
profile: /app/upload/piaowu/
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
@@ -16,7 +16,7 @@ ruoyi:
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8080
port: 8080
port: 1024
servlet:
# 应用的访问路径
context-path: /
@@ -63,9 +63,9 @@ spring:
druid:
# 主库数据源 Abcd1234 P0i8a1o9@#()
master:
url: jdbc:mysql://mysql/piaoruo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:mysql://piaowumysql:3306/piaowu?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: P0i8a1o9@#()
password: P2i0a2o6w@u
# 从库数据源
slave:
# 从数据源开关/默认关闭
@@ -136,10 +136,10 @@ spring:
enabled: true
data:
redis:
host: redis
host: piaowuredis
port: 6379
database: 0
password: Rds123!@$
password: Rds234!@$
ai:
openai:
@@ -5,7 +5,7 @@ ruoyi:
# 版本
version: 3.9.2
# 版权年份
copyrightYear: 2025
copyrightYear: 2026
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
profile: D:/ruoyi/uploadPath
# 获取ip地址开关
@@ -26,6 +26,14 @@ public interface ISysConfigService
*/
public String selectConfigByKey(String configKey);
/**
* 根据键名查询参数配置对象
*
* @param configKey 参数键名
* @return 参数配置对象
*/
public SysConfig selectConfigByConfigKey(String configKey);
/**
* 获取验证码开关
*
@@ -77,6 +77,20 @@ public class SysConfigServiceImpl implements ISysConfigService
return StringUtils.EMPTY;
}
/**
* 根据键名查询参数配置对象
*
* @param configKey 参数键名
* @return 参数配置对象
*/
@Override
public SysConfig selectConfigByConfigKey(String configKey)
{
SysConfig config = new SysConfig();
config.setConfigKey(configKey);
return configMapper.selectConfig(config);
}
/**
* 获取验证码开关
*
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

+16
View File
@@ -0,0 +1,16 @@
import { getRequest, postRequest } from '@/utils/request';
export const aiApi = {
hotline: () => {
return getRequest('/ai/hotline');
},
aiChat : (message, context) => {
let url = `/ai/chat?message=${encodeURIComponent(message)}`
if (context) {
url += `&context=${encodeURIComponent(JSON.stringify(context))}`
}
return getRequest(url);
},
}
-7
View File
@@ -7,11 +7,4 @@ export const messageApi = {
getMenuBadges : (param) => {
return postRequest('/message/menubadge', param);
},
aiChat : (message, context) => {
let url = `/message/chat?message=${encodeURIComponent(message)}`
if (context) {
url += `&context=${encodeURIComponent(JSON.stringify(context))}`
}
return getRequest(url);
},
}
+1 -1
View File
@@ -14,7 +14,7 @@
}
/** 按钮样式 **/
.skin-blue .ant-btn-primary {
background-color: #5FA4CC !important;
background-color: #53a7d1 !important;
color:white!important;
border:none!important;
}
+1 -1
View File
@@ -17,7 +17,7 @@
/** 按钮样式 **/
.skin-green .ant-btn-primary {
background-color:#009FA6 !important;
background-color: #23b67b !important;
color:white!important;
border:none!important;
}
+1 -1
View File
@@ -17,7 +17,7 @@
/** 按钮样式 **/
.skin-purple .ant-btn-primary {
background-color: #A8865D !important;
background-color: #9a64cf !important;
color:white!important;
border:none!important;
}
+1 -1
View File
@@ -14,7 +14,7 @@
/** 按钮样式 **/
.skin-red .ant-btn-primary {
background-color: #63B0B0 !important;
background-color: #f67f7f !important;
color: white !important;
border: none !important;
}
+1 -1
View File
@@ -14,7 +14,7 @@
/** 按钮样式 **/
.skin-yellow .ant-btn-primary {
background-color: #C87F0A !important;
background-color: #ecbe46 !important;
color: white !important;
border: none !important;
}
+1 -1
View File
@@ -41,7 +41,7 @@
.theme-dark .ant-menu-submenu-active{background-color: #304156 !important;color: #79b2ea!important; }
.theme-dark .ant-menu-item-active{background-color: #243448 !important; color: #418dea!important;}
.theme-dark .ant-menu-submenu-title {margin:4px 4px!important;padding:0px 20px!important;color: #BFCBD9!important;}
.theme-dark .ant-menu-submenu-title {margin:4px 0px!important;color: #BFCBD9!important;} /*padding:0px 20px!important;**/
.theme-dark .ant-menu-submenu-open{ color: #BFCBD9 !important;}
.theme-dart .ant-menu-submenu-expand-icon, .ant-menu-submenu-arrow{color:#BFCBD9!important; }
.theme-dark .ant-menu-submenu-selected { color: #418dea !important;}
+12 -11
View File
@@ -3,8 +3,9 @@
<div class="ai-chat-wrapper" :class="{ collapsed, resizing }" :style="wrapperStyle">
<div class="ai-chat-toggle" @click="collapsed = !collapsed">
<div class="ai-chat-toggle-inner">
<div class="ai-chat-drag-edge" @mousedown.prevent="startResize"></div>
<ZhihuiIcon :icon="collapsed ? 'DoubleLeftOutlined' : 'DoubleRightOutlined'" class="ai-chat-toggle-arrow" @click.stop="collapsed = !collapsed" />
<div class="ai-chat-drag-edge" @mousedown.stop="startResize"></div>
<ZhihuiIcon icon="DoubleLeftOutlined" v-if="collapsed" class="ai-chat-toggle-arrow"></ZhihuiIcon>
<ZhihuiIcon icon="DoubleRightOutlined" v-else class="ai-chat-toggle-arrow"></ZhihuiIcon>
</div>
</div>
<div class="ai-chat-body" v-show="!collapsed">
@@ -23,7 +24,7 @@
<!-- 浮动按钮 -->
<a-tooltip placement="left">
<a-button class="ai-chat-float-btn" :type="collapsed ? 'primary' : 'default'" shape="circle" size="large" @click="collapsed = !collapsed">
<a-button class="ai-chat-float-btn" :type="collapsed ? 'primary' : 'default'" shape="circle" size="small" @click="collapsed = !collapsed">
<template #icon><ZhihuiIcon :icon="collapsed ? 'RobotOutlined' : 'CloseOutlined'" /></template>
</a-button>
</a-tooltip>
@@ -43,7 +44,7 @@
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
import { useRoute } from 'vue-router'
import { ZhihuiIcon } from '@/utils/ZhihuiIcon.js'
import { messageApi } from '@/api/piao/message'
import { aiApi } from '@/api/piao/ai'
import zhihuiBus from '@/utils/zhihuiBus'
import ChatMessages from './ai-chat/ChatMessages.vue'
import ChatInput from './ai-chat/ChatInput.vue'
@@ -129,7 +130,7 @@ const sendMessage = async () => {
input.value = ''
loading.value = true
try {
const res = await messageApi.aiChat(text, pageContext.value)
const res = await aiApi.aiChat(text, pageContext.value)
messages.value.push({ role: 'assistant', content: res })
} catch {
messages.value.push({ role: 'assistant', content: '抱歉,我暂时无法回答,请稍后再试。' })
@@ -206,10 +207,10 @@ const sendMessage = async () => {
align-items: center;
justify-content: center;
flex: 1;
padding: 8px 0;
padding: 5px 0;
}
.ai-chat-toggle-arrow {
font-size: 13px;
font-size: 11px;
color: #bbb;
transition: color 0.2s, transform 0.2s;
}
@@ -266,11 +267,11 @@ const sendMessage = async () => {
}
.ai-chat-float-btn {
position: fixed;
top: 5px;
right: 100px;
top: 8px;
right: 110px;
z-index: 999;
width: 32px;
height: 32px;
width: 34px !important;
height: 34px !important;
font-size: 10px;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}
+8 -5
View File
@@ -132,7 +132,7 @@
<!-- 用户名称 -->
<a-dropdown placement="bottomRight" class="user-dropdown">
<a style="color: #fffeee" class="user-dropdown-link">
<img :src="avatarSrc" class="avatarIcon" />
<img :src="avatarSrc" class="avatarIcon" @error="onAvatarError" />
<span class="user-name">{{ vueStore.getters.nickName }}</span>
<ZhihuiIcon icon="DownOutlined" />
</a>
@@ -219,9 +219,12 @@ import zhihuiAudio from '@/utils/zhihuiAudio'; // 引入音频播放器
dayjs.locale('zh-cn');
const avatarError = ref(false);
const avatarSrc = computed(() => {
if (avatarError.value) return "/images/defaultavatar.png";
return store.getters.avatar ? import.meta.env.VITE_API_DOMAIN + store.getters.avatar : "/images/defaultavatar.png";
});
const onAvatarError = () => { avatarError.value = true; };
const vueStore = useStore();
const vueRouter = useRouter();
@@ -729,12 +732,12 @@ onUnmounted(() => {
}
.avatarIcon {
height: 30px;
width: 30px;
height: 33px;
width: 33px;
border-radius: 50%;
background-color: #e4f6f6;
background-color: #a8e4e4;
opacity: 0.9;
border: 1px solid #abcbe7;
border: 1px solid #abcbe7;margin-right:5px;
}
+8 -72
View File
@@ -221,7 +221,7 @@ import { message } from 'ant-design-vue';
import { ArrowDownOutlined, ArrowUpOutlined ,TransactionOutlined,ArrowRightOutlined,SolutionOutlined,ShoppingCartOutlined,MoneyCollectOutlined,ClockCircleOutlined} from '@ant-design/icons-vue';
import { chartApi } from '@/api/piao/chart';
import { listNotice } from '@/api/system/notice';
import { routeApi } from '@/api/piao/route';
import { aiApi } from '@/api/piao/ai';
import zhihuiBus from '@/utils/zhihuiBus';
// 定义响应式数据选项
@@ -599,91 +599,27 @@ const popLoading = ref(false);
const popularLoading = computed(() => {
return popLoading.value ? {
spinning: true,
tip: 'AI正在搜索最新热门航线...',
tip: 'AI正在实时搜索最新热门航线...',
size: 'large'
} : false;
});
const popularRoutes = ref([]);
const fetchPopularRoutes = async () => {
popLoading.value = true;
let timeoutId = null;
try {
// 创建一个超时Promise
const timeoutPromise = new Promise((_, reject) => {
timeoutId = setTimeout(() => {
reject(new Error('请求超时,请稍后重试'));
}, 10000); // 10秒超时
});
// 创建API请求Promise
const apiPromise = routeApi.popular(7);
// 使用Promise.race,哪个先完成就用哪个的结果
const res = await Promise.race([apiPromise, timeoutPromise]);
// 如果请求成功,清除超时计时器
clearTimeout(timeoutId);
// 检查响应是否包含错误
const res = await aiApi.hotline();
if (typeof res === 'string') {
try {
const parsed = JSON.parse(res);
if (parsed.error) {
// 后端返回的错误
showNotification('warning', parsed.message || '请求失败');
const data = JSON.parse(res);
popularRoutes.value = Array.isArray(data) ? data : fallbackRoutes;
} else if (res && res.data) {
popularRoutes.value = Array.isArray(res.data) ? res.data : fallbackRoutes;
} else {
popularRoutes.value = fallbackRoutes;
popLoading.value = false;
return;
}
} catch (e) {
// 不是JSON错误响应,继续正常处理
}
}
// 正常处理逻辑
const events = Array.isArray(res) ? res :
(typeof res === 'string' ? res.split('\n\n').filter(line => line.startsWith('data:')) : []);
let answerData = null;
for (const event of events) {
try {
const eventData = typeof event === 'string' ?
JSON.parse(event.replace('data: ', '')) : event;
if (eventData.event === 'agent_message' && eventData.answer && eventData.answer.trim()) {
const parsed = JSON.parse(eventData.answer);
if (parsed.data) {
answerData = parsed.data;
break;
}
}
} catch (e) {
console.warn('解析事件失败:', e);
}
}
popularRoutes.value = Array.isArray(answerData) ? answerData : fallbackRoutes;
} catch (error) {
console.error('获取热门航线失败:', error);
// 清除超时计时器(如果还在)
if (timeoutId) clearTimeout(timeoutId);
// 显示错误提示
if (error.message === '请求超时,请稍后重试') {
showNotification('warning', '请求超时,网络较慢或服务器响应延迟');
} else if (error.message.includes('Network Error')) {
showNotification('error', '网络错误,请检查网络连接');
} else {
showNotification('error', '获取数据失败');
}
popularRoutes.value = fallbackRoutes;
} finally {
// 确保无论如何都会关闭loading
popLoading.value = false;
}
};