feat: 添加任务状态级联触发器,优化支付和做同款功能

主要更新:
- 添加 MySQL 触发器实现 task_status 表到其他表的状态级联
- 移除控制器中的多表状态检查代码
- 完善做同款功能,支持参数传递
- 支付宝 USD 转 CNY 汇率转换
- 修复状态枚举映射问题

注意: 触发器仅在 task_status 更新时触发,部分代码仍直接更新业务表
This commit is contained in:
AIGC Developer
2025-12-08 13:54:02 +08:00
parent 624d560fb4
commit 3c37006ebd
84 changed files with 5325 additions and 1668 deletions

View File

@@ -1,5 +1,5 @@
#Updated by API Key Management
#Mon Nov 24 17:13:13 CST 2025
#Sat Dec 06 10:23:35 CST 2025
ai.api.base-url=https\://ai.comfly.chat
ai.api.key=sk-6J0Lpb0NYSwCCEbFUym8SZho1kJZPFN9au19VC78vJckTbCc
ai.image.api.base-url=https\://ai.comfly.chat
@@ -7,21 +7,26 @@ ai.image.api.key=sk-6J0Lpb0NYSwCCEbFUym8SZho1kJZPFN9au19VC78vJckTbCc
alipay.app-id=9021000157616562
alipay.charset=UTF-8
alipay.gateway-url=https\://openapi-sandbox.dl.alipaydev.com/gateway.do
alipay.notify-url=https\://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/notify
alipay.notify-url=https\://vionow.com/api/payments/alipay/notify
alipay.private-key=MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCH7wPeptkJlJuoKwDqxvfJJLTOAWVkHa/TLh+wiy1tEtmwcrOwEU3GuqfkUlhij71WJIZi8KBytCwbax1QGZA/oLXvTCGJJrYrsEL624X5gGCCPKWwHRDhewsQ5W8jFxaaMXxth8GKlSW61PZD2cOQClRVEm2xnWFZ+6/7WBI7082g7ayzGCD2eowXsJyWyuEBCUSbHXkSgxVhqj5wUGIXhr8ly+pdUlJmDX5K8UG2rjJYx+0AU5UZJbOAND7d3iyDsOulHDvth50t8MOWDnDCVJ2aAgUB5FZKtOFxOmzNTsMjvzYldFztF0khbypeeMVL2cxgioIgTvjBkUwd55hZAgMBAAECggEAUjk3pARUoEDt7skkYt87nsW/QCUECY0Tf7AUpxtovON8Hgkju8qbuyvIxokwwV2k72hkiZB33Soyy9r8/iiYYoR5yGfKmUV7R+30df03ivYmamD48BCE138v8GZ31Ufv+hEY7MADSCpzihGrbNtaOdSlslfVVmyWKHHfvy9EyD6yHJGYswLpHXC/QX1TuLRRxk6Uup8qENOG/6zjGWMfxoRZFwTt80ml1mKy32YZGyJqDaQpJcdYwAHOPcnJl1emw4E+oVjiLyksl643npuTkgnZXs1iWcWSS8ojF1w/0kVDzcNh9toLg+HDuQlIHOis01VQ7lYcG4oiMOnhX1QHIQKBgQC9fgBuILjBhuCI9fHvLRdzoNC9heD54YK7xGvEV/mv90k8xcmNx+Yg5C57ASaMRtOq3b7muPiCv5wOtMT4tUCcMIwSrTNlcBM6EoTagnaGfpzOMaHGMXO4vbaw+MIynHnvXFj1rZjG1lzkV/9K36LAaHD9ZKVJaBQ9mK+0CIq/3QKBgQC3pL5GbvXj6/4ahTraXzNDQQpPGVgbHxcOioEXL4ibaOPC58puTW8HDbRvVuhl/4EEOBRVX81BSgkN8XHwTSiZdih2iOqByg+o9kixs7nlFn3Iw9BBP2/g+Wqiyi2N+9g17kfWXXVOKYz/eMXLBeOo4KhQE9wqNGyZldYzX2ywrQKBgApJmvBfqmgnUG1fHOFlS06lvm9ro0ktqxFSmp8wP4gEHt/DxSuDXMUQXk2jRFp9ReSS4VhZVnSSvoA15DO0c2uHXzNsX8v0B7cxZjEOwCyRFyZCn4vJB4VSF2cIOlLRF/Wcx9+eqxqwbJ6hAGUqOwXDJc879ZVEp0So03EsvYupAoGAAnI+Wp/VxLB7FQ1bSFdmTmoKYh1bUBks7HOp3o4yiqduCUWfK7L6XKSxF56Xv+wUYuMAWlbJXCpJTpc9xk6w0MKDLXkLbqkrZjvJohxbyJJxIICDQKtAqUWJRxvcWXzWV3mSGWfrTRw+lZSdReQRMUm01EQ/dYx3OeCGFu8Zeo0CgYAlH5YSYdJxZSoDCJeoTrkxUlFoOg8UQ7SrsaLYLwpwcwpuiWJaTrg6jwFocj+XhjQ9RtRbSBHz2wKSLdl+pXbTbqECKk85zMFl6zG3etXtTJU/dD750Ty4i8zt3+JGhvglPrQBY1CfItgml2oXa/VUVMnLCUS0WSZuPRmPYZD8dg\=\=
alipay.public-key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAksEwzuR3ASrKtTzaANqdQYKOoD44itA1TWG/6onvQr8PHNEMgcguLuJNrdeuT2PDg23byzZ9qKfEM2D5U4zbpt0/uCYLfZQyAnAWWyMvnKPoSIgrtBjnxYK6HE6fuQV3geJTcZxvP/z8dGZB0V0s6a53rzbKSLh0p4w0hWfVXlQihq3Xh4vSKB+ojdhEkIblhpWPT42NPbjVNdwPzIhUGpRy3/nsgNqVBu+ZacQ5/rCvzXU1RE0allBbjcvjymKQTS7bAE0i1Mgo1eX8njvElsfQUv5P7xQdrvZagqtIuTdP19cmsSNGdIC9Z5Po3j0z3KWPR7MrKgDuJfzkWtJR4wIDAQAB
alipay.return-url=https\://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/return
alipay.return-url=https\://vionow.com/api/payments/alipay/return
alipay.server-url=https\://openapi-sandbox.dl.alipaydev.com/gateway.do
alipay.sign-type=RSA2
app.ffmpeg.path=C\:/Users/UI/AppData/Local/Microsoft/WinGet/Packages/Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe/ffmpeg-8.0-full_build/bin/ffmpeg.exe
app.temp.dir=./temp
jwt.expiration=86400000
jwt.expiration=7200000
jwt.secret=mySecretKey123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
logging.level.com.example.demo=DEBUG
logging.level.org.hibernate.SQL=WARN
logging.level.org.hibernate.orm.jdbc.bind=WARN
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=WARN
logging.level.org.springframework.security=DEBUG
logging.level.org.springframework.security=WARN
paypal.cancel-url=https\://vionow.com/api/payment/paypal/cancel
paypal.client-id=Adpi67TvppjhyyWhrALWwJhLFzv5S_vXoUHzWQchqZe48NaONSryg7QHKBubf0PRmkeJoaxGEKV5v9lT
paypal.client-secret=EDzZl-hddwtt2pNt5RpBIICdlrUS8QtcmAttU_kuANL8Vd937SC4xel_K2hArTovVqEtyL2ZS5IcQcQV
paypal.mode=sandbox
paypal.success-url=https\://vionow.com/api/payment/paypal/success
server.port=8080
server.tomcat.accept-count=100
server.tomcat.connection-timeout=20000
@@ -56,11 +61,5 @@ tencent.ses.region=ap-hongkong
tencent.ses.secret-id=AKIDoaEjFbqxxqZAcv8EE6oZCg2IQPG1fCxm
tencent.ses.secret-key=nR83I79FOSpGcqNo7JXkqnU8g7SjsxuG
tencent.ses.template-id=154360
# ============================================
# PayPal支付配置沙箱测试环境
# ============================================
paypal.client-id=Adpi67TvppjhyyWhrALWwJhLFzv5S_vXoUHzWQchqZe48NaONSryg7QHKBubf0PRmkeJoaxGEKV5v9lT
paypal.client-secret=EDzZl-hddwtt2pNt5RpBIICdlrUS8QtcmAttU_kuANL8Vd937SC4xel_K2hArTovVqEtyL2ZS5IcQcQV
paypal.mode=sandbox
paypal.success-url=http://localhost:8080/api/payment/paypal/success
paypal.cancel-url=http://localhost:8080/api/payment/paypal/cancel
alipay.domain=https\://vionow.com

View File

@@ -17,6 +17,20 @@ server.tomcat.max-http-post-size=600MB
# JPA配置 - 禁用open-in-view避免视图层执行SQL查询
spring.jpa.open-in-view=false
# HikariCP连接池配置
# 连接泄漏检测阈值毫秒设置为0禁用检测避免长时间任务触发误报
spring.datasource.hikari.leak-detection-threshold=0
# 最大连接池大小
spring.datasource.hikari.maximum-pool-size=20
# 最小空闲连接数
spring.datasource.hikari.minimum-idle=5
# 连接超时(毫秒)
spring.datasource.hikari.connection-timeout=30000
# 空闲连接超时(毫秒)
spring.datasource.hikari.idle-timeout=600000
# 连接最大存活时间(毫秒)
spring.datasource.hikari.max-lifetime=1800000
# 应用配置
app.upload.path=uploads
app.video.output.path=outputs
@@ -52,6 +66,8 @@ tencent.cos.secret-key=Xrxywju0wfAf3QiqlT2ZvGYgeS6WjnjT
tencent.cos.region=ap-nanjing
# COS存储桶名称例如my-bucket-1234567890
tencent.cos.bucket-name=test-1323844400
# COS文件夹前缀所有文件存储在此目录下
tencent.cos.prefix=test-sx
# ============================================
# PayPal支付配置
@@ -69,3 +85,18 @@ paypal.success-url=https://vionow.com/api/payment/paypal/success
# 支付取消回调URL
paypal.cancel-url=https://vionow.com/api/payment/paypal/cancel
# ============================================
# GZIP 压缩配置(提升传输性能)
# ============================================
server.compression.enabled=true
server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json,application/xml
server.compression.min-response-size=1024
# ============================================
# 日志配置
# ============================================
# 关闭 Spring Security DEBUG 日志
logging.level.org.springframework.security=INFO
# 减少 Tomcat HTTP 解析错误日志(扫描器/HTTPS误连等导致的
logging.level.org.apache.coyote.http11.Http11Processor=ERROR
logging.level.org.apache.coyote.AbstractProtocol=ERROR

View File

@@ -5,11 +5,11 @@
-- 注意:生产环境部署时,此文件应保持为空或仅包含必要的系统配置数据
-- ============================================
-- 管理员权限自动设置
-- 超级管理员权限自动设置
-- ============================================
-- 应用启动时自动将 984523799@qq.com 设置为管理员
-- 如果该用户存在,则更新其角色为管理员
-- 应用启动时自动将 984523799@qq.com 设置为超级管理员
-- 如果该用户存在,则更新其角色为超级管理员
UPDATE users
SET role = 'ROLE_ADMIN',
SET role = 'ROLE_SUPER_ADMIN',
updated_at = CURRENT_TIMESTAMP
WHERE email = '984523799@qq.com';

View File

@@ -0,0 +1,48 @@
-- 性能优化索引MySQL 兼容)
-- 注意:此文件需要手动在数据库中执行,如果索引已存在会报错(可忽略)
-- users 表索引
ALTER TABLE users ADD INDEX idx_users_phone (phone);
ALTER TABLE users ADD INDEX idx_users_is_active (is_active);
ALTER TABLE users ADD INDEX idx_users_last_active_time (last_active_time);
ALTER TABLE users ADD INDEX idx_users_created_at (created_at);
-- payments 表索引
ALTER TABLE payments ADD INDEX idx_payments_user_id (user_id);
ALTER TABLE payments ADD INDEX idx_payments_status (status);
ALTER TABLE payments ADD INDEX idx_payments_created_at (created_at);
ALTER TABLE payments ADD INDEX idx_payments_user_status (user_id, status);
-- orders 表索引
ALTER TABLE orders ADD INDEX idx_orders_user_id (user_id);
ALTER TABLE orders ADD INDEX idx_orders_status (status);
ALTER TABLE orders ADD INDEX idx_orders_created_at (created_at);
ALTER TABLE orders ADD INDEX idx_orders_user_status (user_id, status);
-- user_works 表索引(高频查询优化)
ALTER TABLE user_works ADD INDEX idx_user_works_username (username);
ALTER TABLE user_works ADD INDEX idx_user_works_status (status);
ALTER TABLE user_works ADD INDEX idx_user_works_task_id (task_id);
ALTER TABLE user_works ADD INDEX idx_user_works_created_at (created_at);
ALTER TABLE user_works ADD INDEX idx_user_works_username_status (username, status);
ALTER TABLE user_works ADD INDEX idx_user_works_is_public_status (is_public, status);
-- text_to_video_tasks 表索引
ALTER TABLE text_to_video_tasks ADD INDEX idx_text_to_video_tasks_task_id (task_id);
ALTER TABLE text_to_video_tasks ADD INDEX idx_text_to_video_tasks_username (username);
ALTER TABLE text_to_video_tasks ADD INDEX idx_text_to_video_tasks_status (status);
-- image_to_video_tasks 表索引
ALTER TABLE image_to_video_tasks ADD INDEX idx_image_to_video_tasks_task_id (task_id);
ALTER TABLE image_to_video_tasks ADD INDEX idx_image_to_video_tasks_username (username);
ALTER TABLE image_to_video_tasks ADD INDEX idx_image_to_video_tasks_status (status);
-- storyboard_video_tasks 表索引
ALTER TABLE storyboard_video_tasks ADD INDEX idx_storyboard_video_tasks_task_id (task_id);
ALTER TABLE storyboard_video_tasks ADD INDEX idx_storyboard_video_tasks_username (username);
ALTER TABLE storyboard_video_tasks ADD INDEX idx_storyboard_video_tasks_status (status);
-- points_freeze_records 表索引
ALTER TABLE points_freeze_records ADD INDEX idx_points_freeze_records_task_id (task_id);
ALTER TABLE points_freeze_records ADD INDEX idx_points_freeze_records_username (username);
ALTER TABLE points_freeze_records ADD INDEX idx_points_freeze_records_status (status);

View File

@@ -0,0 +1,126 @@
-- ============================================
-- 任务状态级联更新触发器
-- 当 task_status 表状态更新时,自动同步到其他关联表
-- ============================================
DELIMITER //
-- 删除已存在的触发器(如果存在)
DROP TRIGGER IF EXISTS trg_task_status_update//
-- 创建触发器:当 task_status 更新时,级联更新其他表
CREATE TRIGGER trg_task_status_update
AFTER UPDATE ON task_status
FOR EACH ROW
BEGIN
-- 只在状态发生变化时触发
IF NEW.status <> OLD.status THEN
-- 更新 task_queue 表
UPDATE task_queue
SET status = NEW.status,
updated_at = NOW(),
error_message = CASE WHEN NEW.status = 'FAILED' THEN NEW.error_message ELSE error_message END
WHERE task_id = NEW.task_id;
-- 更新 user_works 表
UPDATE user_works
SET status = CASE
WHEN NEW.status = 'COMPLETED' THEN 'COMPLETED'
WHEN NEW.status = 'FAILED' THEN 'FAILED'
WHEN NEW.status = 'PROCESSING' THEN 'PROCESSING'
WHEN NEW.status = 'PENDING' THEN 'PENDING'
WHEN NEW.status = 'CANCELLED' THEN 'CANCELLED'
ELSE status
END,
updated_at = NOW(),
result_url = CASE WHEN NEW.status = 'COMPLETED' AND NEW.result_url IS NOT NULL THEN NEW.result_url ELSE result_url END
WHERE task_id = NEW.task_id;
-- 更新 text_to_video_tasks 表(根据 task_id 前缀判断)
IF NEW.task_id LIKE 'txt2vid_%' THEN
UPDATE text_to_video_tasks
SET status = NEW.status,
updated_at = NOW(),
error_message = CASE WHEN NEW.status = 'FAILED' THEN NEW.error_message ELSE error_message END,
result_url = CASE WHEN NEW.status = 'COMPLETED' AND NEW.result_url IS NOT NULL THEN NEW.result_url ELSE result_url END
WHERE task_id = NEW.task_id;
END IF;
-- 更新 image_to_video_tasks 表
IF NEW.task_id LIKE 'img2vid_%' THEN
UPDATE image_to_video_tasks
SET status = NEW.status,
updated_at = NOW(),
error_message = CASE WHEN NEW.status = 'FAILED' THEN NEW.error_message ELSE error_message END,
result_url = CASE WHEN NEW.status = 'COMPLETED' AND NEW.result_url IS NOT NULL THEN NEW.result_url ELSE result_url END
WHERE task_id = NEW.task_id;
END IF;
-- 更新 storyboard_video_tasks 表(分镜视频,排除分镜图)
IF NEW.task_id LIKE 'storyboard_%' AND NEW.task_id NOT LIKE '%_image' THEN
UPDATE storyboard_video_tasks
SET status = NEW.status,
updated_at = NOW(),
error_message = CASE WHEN NEW.status = 'FAILED' THEN NEW.error_message ELSE error_message END,
result_url = CASE WHEN NEW.status = 'COMPLETED' AND NEW.result_url IS NOT NULL THEN NEW.result_url ELSE result_url END
WHERE task_id = NEW.task_id;
END IF;
-- 分镜图任务taskId 以 _image 结尾)
IF NEW.task_id LIKE '%_image' THEN
-- 分镜图关联到主任务,更新主任务的时间戳和错误信息
UPDATE storyboard_video_tasks
SET updated_at = NOW(),
error_message = CASE WHEN NEW.status = 'FAILED' THEN NEW.error_message ELSE error_message END
WHERE task_id = REPLACE(NEW.task_id, '_image', '');
END IF;
END IF;
END//
DELIMITER ;
-- ============================================
-- 可选:反向触发器(业务表更新时同步到 task_status
-- 根据需要启用
-- ============================================
/*
DELIMITER //
-- text_to_video_tasks 状态更新时同步
DROP TRIGGER IF EXISTS trg_text_to_video_status_update//
CREATE TRIGGER trg_text_to_video_status_update
AFTER UPDATE ON text_to_video_tasks
FOR EACH ROW
BEGIN
IF NEW.status <> OLD.status THEN
UPDATE task_status SET status = NEW.status, updated_at = NOW() WHERE task_id = NEW.task_id;
END IF;
END//
-- image_to_video_tasks 状态更新时同步
DROP TRIGGER IF EXISTS trg_image_to_video_status_update//
CREATE TRIGGER trg_image_to_video_status_update
AFTER UPDATE ON image_to_video_tasks
FOR EACH ROW
BEGIN
IF NEW.status <> OLD.status THEN
UPDATE task_status SET status = NEW.status, updated_at = NOW() WHERE task_id = NEW.task_id;
END IF;
END//
-- storyboard_video_tasks 状态更新时同步
DROP TRIGGER IF EXISTS trg_storyboard_status_update//
CREATE TRIGGER trg_storyboard_status_update
AFTER UPDATE ON storyboard_video_tasks
FOR EACH ROW
BEGIN
IF NEW.status <> OLD.status THEN
UPDATE task_status SET status = NEW.status, updated_at = NOW() WHERE task_id = NEW.task_id;
END IF;
END//
DELIMITER ;
*/

View File

@@ -0,0 +1,11 @@
-- 修复外键约束,添加级联删除
-- 1. 修复 payments 表的外键约束
ALTER TABLE payments DROP FOREIGN KEY payments_ibfk_1;
ALTER TABLE payments ADD CONSTRAINT payments_user_fk
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-- 2. 修复 orders 表的外键约束
ALTER TABLE orders DROP FOREIGN KEY orders_ibfk_1;
ALTER TABLE orders ADD CONSTRAINT orders_user_fk
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

View File

@@ -1,15 +1,15 @@
# 支付配置
# 支付宝配置 - 请替换为您的实际配置
alipay.app-id=您的APPID
alipay.private-key=您的应用私钥
alipay.public-key=支付宝公钥
# 支付宝沙箱配置
alipay.app-id=9021000157616562
alipay.private-key=MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCH7wPeptkJlJuoKwDqxvfJJLTOAWVkHa/TLh+wiy1tEtmwcrOwEU3GuqfkUlhij71WJIZi8KBytCwbax1QGZA/oLXvTCGJJrYrsEL624X5gGCCPKWwHRDhewsQ5W8jFxaaMXxth8GKlSW61PZD2cOQClRVEm2xnWFZ+6/7WBI7082g7ayzGCD2eowXsJyWyuEBCUSbHXkSgxVhqj5wUGIXhr8ly+pdUlJmDX5K8UG2rjJYx+0AU5UZJbOAND7d3iyDsOulHDvth50t8MOWDnDCVJ2aAgUB5FZKtOFxOmzNTsMjvzYldFztF0khbypeeMVL2cxgioIgTvjBkUwd55hZAgMBAAECggEAUjk3pARUoEDt7skkYt87nsW/QCUECY0Tf7AUpxtovON8Hgkju8qbuyvIxokwwV2k72hkiZB33Soyy9r8/iiYYoR5yGfKmUV7R+30df03ivYmamD48BCE138v8GZ31Ufv+hEY7MADSCpzihGrbNtaOdSlslfVVmyWKHHfvy9EyD6yHJGYswLpHXC/QX1TuLRRxk6Uup8qENOG/6zjGWMfxoRZFwTt80ml1mKy32YZGyJqDaQpJcdYwAHOPcnJl1emw4E+oVjiLyksl643npuTkgnZXs1iWcWSS8ojF1w/0kVDzcNh9toLg+HDuQlIHOis01VQ7lYcG4oiMOnhX1QHIQKBgQC9fgBuILjBhuCI9fHvLRdzoNC9heD54YK7xGvEV/mv90k8xcmNx+Yg5C57ASaMRtOq3b7muPiCv5wOtMT4tUCcMIwSrTNlcBM6EoTagnaGfpzOMaHGMXO4vbaw+MIynHnvXFj1rZjG1lzkV/9K36LAaHD9ZKVJaBQ9mK+0CIq/3QKBgQC3pL5GbvXj6/4ahTraXzNDQQpPGVgbHxcOioEXL4ibaOPC58puTW8HDbRvVuhl/4EEOBRVX81BSgkN8XHwTSiZdih2iOqByg+o9kixs7nlFn3Iw9BBP2/g+Wqiyi2N+9g17kfWXXVOKYz/eMXLBeOo4KhQE9wqNGyZldYzX2ywrQKBgApJmvBfqmgnUG1fHOFlS06lvm9ro0ktqxFSmp8wP4gEHt/DxSuDXMUQXk2jRFp9ReSS4VhZVnSSvoA15DO0c2uHXzNsX8v0B7cxZjEOwCyRFyZCn4vJB4VSF2cIOlLRF/Wcx9+eqxqwbJ6hAGUqOwXDJc879ZVEp0So03EsvYupAoGAAnI+Wp/VxLB7FQ1bSFdmTmoKYh1bUBks7HOp3o4yiqduCUWfK7L6XKSxF56Xv+wUYuMAWlbJXCpJTpc9xk6w0MKDLXkLbqkrZjvJohxbyJJxIICDQKtAqUWJRxvcWXzWV3mSGWfrTRw+lZSdReQRMUm01EQ/dYx3OeCGFu8Zeo0CgYAlH5YSYdJxZSoDCJeoTrkxUlFoOg8UQ7SrsaLYLwpwcwpuiWJaTrg6jwFocj+XhjQ9RtRbSBHz2wKSLdl+pXbTbqECKk85zMFl6zG3etXtTJU/dD750Ty4i8zt3+JGhvglPrQBY1CfItgml2oXa/VUVMnLCUS0WSZuPRmPYZD8dg==
alipay.public-key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAksEwzuR3ASrKtTzaANqdQYKOoD44itA1TWG/6onvQr8PHNEMgcguLuJNrdeuT2PDg23byzZ9qKfEM2D5U4zbpt0/uCYLfZQyAnAWWyMvnKPoSIgrtBjnxYK6HE6fuQV3geJTcZxvP/z8dGZB0V0s6a53rzbKSLh0p4w0hWfVXlQihq3Xh4vSKB+ojdhEkIblhpWPT42NPbjVNdwPzIhUGpRy3/nsgNqVBu+ZacQ5/rCvzXU1RE0allBbjcvjymKQTS7bAE0i1Mgo1eX8njvElsfQUv5P7xQdrvZagqtIuTdP19cmsSNGdIC9Z5Po3j0z3KWPR7MrKgDuJfzkWtJR4wIDAQAB
alipay.server-url=https://openapi-sandbox.dl.alipaydev.com/gateway.do
alipay.gateway-url=https://openapi-sandbox.dl.alipaydev.com/gateway.do
alipay.domain=https://curtly-aphorismatic-ginger.ngrok-free.dev
alipay.domain=https://vionow.com
alipay.charset=UTF-8
alipay.sign-type=RSA2
alipay.notify-url=https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/notify
alipay.return-url=https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/return
alipay.notify-url=https://vionow.com/api/payments/alipay/notify
alipay.return-url=https://vionow.com/api/payments/alipay/return
alipay.app-cert-path=classpath:cert/alipay/appCertPublicKey.crt
alipay.ali-pay-cert-path=classpath:cert/alipay/alipayCertPublicKey_RSA2.crt
alipay.ali-pay-root-cert-path=classpath:cert/alipay/alipayRootCert.crt

View File

@@ -32,7 +32,7 @@ CREATE TABLE IF NOT EXISTS payments (
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
paid_at TIMESTAMP NULL,
user_id BIGINT,
FOREIGN KEY (user_id) REFERENCES users(id)
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS orders (
@@ -55,7 +55,7 @@ CREATE TABLE IF NOT EXISTS orders (
delivered_at TIMESTAMP NULL,
cancelled_at TIMESTAMP NULL,
user_id BIGINT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id)
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS order_items (

View File

@@ -1,9 +1,9 @@
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org" th:fragment="layout(title, content)">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title th:text="${pageTitle} + ' - ' + ${siteName}">AIGC Demo</title>
<title th:replace="${title}">AIGC Demo</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
@@ -168,22 +168,22 @@
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" th:href="@{/}" th:classappend="${#httpServletRequest.requestURI == '/'} ? 'active' : ''">
<a class="nav-link" th:href="@{/}" th:classappend="${#httpServletRequest != null && #httpServletRequest.requestURI == '/'} ? 'active' : ''">
<i class="fas fa-home me-1"></i>首页
</a>
</li>
<li class="nav-item" sec:authorize="hasRole('ADMIN')">
<a class="nav-link" th:href="@{/settings}" th:classappend="${#strings.startsWith(#httpServletRequest.requestURI, '/settings')} ? 'active' : ''">
<a class="nav-link" th:href="@{/settings}" th:classappend="${#httpServletRequest != null && #strings.startsWith(#httpServletRequest.requestURI, '/settings')} ? 'active' : ''">
<i class="fas fa-gear me-1"></i>系统设置
</a>
</li>
<li class="nav-item" sec:authorize="hasRole('ADMIN')">
<a class="nav-link" th:href="@{/users}" th:classappend="${#strings.startsWith(#httpServletRequest.requestURI, '/users')} ? 'active' : ''">
<a class="nav-link" th:href="@{/users}" th:classappend="${#httpServletRequest != null && #strings.startsWith(#httpServletRequest.requestURI, '/users')} ? 'active' : ''">
<i class="fas fa-users me-1"></i>用户管理
</a>
</li>
<li class="nav-item" sec:authorize="isAuthenticated()">
<a class="nav-link" th:href="@{/payment/create}" th:classappend="${#strings.startsWith(#httpServletRequest.requestURI, '/payment')} ? 'active' : ''">
<a class="nav-link" th:href="@{/payment/create}" th:classappend="${#httpServletRequest != null && #strings.startsWith(#httpServletRequest.requestURI, '/payment')} ? 'active' : ''">
<i class="fas fa-credit-card me-1"></i>支付管理
</a>
</li>
@@ -265,7 +265,7 @@
</div>
<!-- Page Content -->
<div th:fragment="content">
<div th:replace="${content}">
<!-- Page specific content will be inserted here -->
</div>
</div>