前端打包
This commit is contained in:
@@ -17,15 +17,16 @@ RUN mkdir -p /docker-entrypoint-initdb.d /opt/sql
|
|||||||
# 复制所有SQL文件(保持目录结构)
|
# 复制所有SQL文件(保持目录结构)
|
||||||
COPY schoolNewsServ/.bin/mysql/sql/ /opt/sql/
|
COPY schoolNewsServ/.bin/mysql/sql/ /opt/sql/
|
||||||
|
|
||||||
# 复制并调整reInit.sh为Docker环境
|
# 复制并调整reInit.sh为Docker环境,设置执行权限
|
||||||
COPY schoolNewsServ/.bin/mysql/sql/reInit.sh /opt/sql/
|
COPY schoolNewsServ/.bin/mysql/sql/reInit.sh /opt/sql/
|
||||||
RUN sed -i 's/DB_HOST="localhost"/DB_HOST="localhost"/' /opt/sql/reInit.sh && \
|
RUN sed -i 's/DB_HOST="localhost"/DB_HOST="localhost"/' /opt/sql/reInit.sh && \
|
||||||
sed -i 's/DB_PORT="3306"/DB_PORT="3306"/' /opt/sql/reInit.sh && \
|
sed -i 's/DB_PORT="3306"/DB_PORT="3306"/' /opt/sql/reInit.sh && \
|
||||||
sed -i 's/DB_USER="root"/DB_USER="root"/' /opt/sql/reInit.sh && \
|
sed -i 's/DB_USER="root"/DB_USER="root"/' /opt/sql/reInit.sh && \
|
||||||
sed -i 's/DB_PASSWORD="123456"/DB_PASSWORD="${MYSQL_ROOT_PASSWORD}"/' /opt/sql/reInit.sh && \
|
sed -i 's/DB_PASSWORD="123456"/DB_PASSWORD="${MYSQL_ROOT_PASSWORD}"/' /opt/sql/reInit.sh && \
|
||||||
sed -i 's/DB_NAME="school_news"/DB_NAME="${MYSQL_DATABASE}"/' /opt/sql/reInit.sh && \
|
sed -i 's/DB_NAME="school_news"/DB_NAME="${MYSQL_DATABASE}"/' /opt/sql/reInit.sh && \
|
||||||
chmod +x /opt/sql/reInit.sh
|
sed -i 's|LOG_FILE="$SCRIPT_DIR/reInit.log"|LOG_FILE="/tmp/reInit.log"|' /opt/sql/reInit.sh && \
|
||||||
|
chmod +x /opt/sql/reInit.sh && \
|
||||||
|
chmod +x /opt/sql/sensitiveData/importSensitiveWords.sh
|
||||||
# 创建Docker初始化适配脚本
|
# 创建Docker初始化适配脚本
|
||||||
RUN cat > /docker-entrypoint-initdb.d/01-init-database.sh <<'EOF'
|
RUN cat > /docker-entrypoint-initdb.d/01-init-database.sh <<'EOF'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
@@ -54,10 +55,8 @@ export DB_PASSWORD="${MYSQL_ROOT_PASSWORD}"
|
|||||||
export DB_NAME="${MYSQL_DATABASE}"
|
export DB_NAME="${MYSQL_DATABASE}"
|
||||||
export MYSQL_PWD="${MYSQL_ROOT_PASSWORD}"
|
export MYSQL_PWD="${MYSQL_ROOT_PASSWORD}"
|
||||||
|
|
||||||
# 直接调用reInit.sh的初始化函数
|
|
||||||
echo "执行数据库初始化..."
|
|
||||||
|
|
||||||
# Source reInit.sh并调用其初始化函数
|
# Source reInit.sh并调用其初始化函数
|
||||||
|
echo "执行数据库初始化(使用reInit.sh)..."
|
||||||
source reInit.sh
|
source reInit.sh
|
||||||
|
|
||||||
# 调用reInit.sh的核心函数(跳过备份和删除)
|
# 调用reInit.sh的核心函数(跳过备份和删除)
|
||||||
@@ -76,11 +75,9 @@ UPDATE tb_sys_config
|
|||||||
SET config_value = '/app/crawler'
|
SET config_value = '/app/crawler'
|
||||||
WHERE config_key = 'crawler.basePath';
|
WHERE config_key = 'crawler.basePath';
|
||||||
|
|
||||||
-- 如果配置不存在则插入
|
UPDATE _db_init_status
|
||||||
INSERT IGNORE INTO tb_sys_config (config_key, config_value, config_desc, created_at)
|
SET status = 'success'
|
||||||
VALUES
|
WHERE script_name = '01-init-database.sql';
|
||||||
('crawler.pythonPath', '/usr/bin/python3', 'Docker容器内Python路径', NOW()),
|
|
||||||
('crawler.basePath', '/app/crawler', 'Docker容器内爬虫脚本路径', NOW());
|
|
||||||
|
|
||||||
SELECT '✅ 数据库初始化完成!' AS message;
|
SELECT '✅ 数据库初始化完成!' AS message;
|
||||||
SELECT '默认用户: admin, 密码: admin123' AS tip;
|
SELECT '默认用户: admin, 密码: admin123' AS tip;
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!--
|
<!--
|
||||||
校园新闻管理系统 - Docker环境日志配置
|
校园新闻管理系统 - Admin模块日志配置
|
||||||
-->
|
-->
|
||||||
<configuration status="WARN" monitorInterval="30">
|
<configuration status="WARN" monitorInterval="30">
|
||||||
|
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
|
||||||
|
|
||||||
|
<!--变量配置-->
|
||||||
<Properties>
|
<Properties>
|
||||||
|
<!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
|
||||||
|
<!-- %logger{36} 表示 Logger 名字最长36个字符 -->
|
||||||
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
|
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
|
||||||
<property name="FILE_PATH" value="/app/logs" />
|
<!-- 定义日志存储的路径 -->
|
||||||
|
<property name="FILE_PATH" value="./logs" />
|
||||||
|
<!-- Admin模块日志文件名 -->
|
||||||
<property name="FILE_NAME" value="school-news-admin" />
|
<property name="FILE_NAME" value="school-news-admin" />
|
||||||
|
<!-- 设置系统属性 -->
|
||||||
<property name="file.encoding" value="UTF-8" />
|
<property name="file.encoding" value="UTF-8" />
|
||||||
<property name="console.encoding" value="UTF-8" />
|
<property name="console.encoding" value="UTF-8" />
|
||||||
<property name="stdout.encoding" value="UTF-8" />
|
<property name="stdout.encoding" value="UTF-8" />
|
||||||
@@ -14,60 +22,171 @@
|
|||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
<appenders>
|
<appenders>
|
||||||
|
|
||||||
<console name="Console" target="SYSTEM_OUT">
|
<console name="Console" target="SYSTEM_OUT">
|
||||||
|
<!--输出日志的格式-->
|
||||||
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
|
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
|
||||||
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
|
<!--控制台输出debug及以上级别的信息-->
|
||||||
|
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||||
</console>
|
</console>
|
||||||
|
|
||||||
|
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
|
||||||
<File name="Filelog" fileName="${FILE_PATH}/${FILE_NAME}-test.log" append="false">
|
<File name="Filelog" fileName="${FILE_PATH}/${FILE_NAME}-test.log" append="false">
|
||||||
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
|
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
|
||||||
</File>
|
</File>
|
||||||
|
|
||||||
|
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
|
||||||
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/${FILE_NAME}-info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
|
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/${FILE_NAME}-info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
|
||||||
|
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
|
||||||
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
|
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||||
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
|
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
|
||||||
<Policies>
|
<Policies>
|
||||||
|
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
|
||||||
<TimeBasedTriggeringPolicy interval="1"/>
|
<TimeBasedTriggeringPolicy interval="1"/>
|
||||||
<SizeBasedTriggeringPolicy size="10MB"/>
|
<SizeBasedTriggeringPolicy size="10MB"/>
|
||||||
</Policies>
|
</Policies>
|
||||||
|
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
|
||||||
<DefaultRolloverStrategy max="15"/>
|
<DefaultRolloverStrategy max="15"/>
|
||||||
</RollingFile>
|
</RollingFile>
|
||||||
|
|
||||||
|
<!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
|
||||||
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/${FILE_NAME}-warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
|
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/${FILE_NAME}-warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
|
||||||
|
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
|
||||||
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
|
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||||
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
|
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
|
||||||
<Policies>
|
<Policies>
|
||||||
|
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
|
||||||
<TimeBasedTriggeringPolicy interval="1"/>
|
<TimeBasedTriggeringPolicy interval="1"/>
|
||||||
<SizeBasedTriggeringPolicy size="10MB"/>
|
<SizeBasedTriggeringPolicy size="10MB"/>
|
||||||
</Policies>
|
</Policies>
|
||||||
|
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
|
||||||
<DefaultRolloverStrategy max="15"/>
|
<DefaultRolloverStrategy max="15"/>
|
||||||
</RollingFile>
|
</RollingFile>
|
||||||
|
|
||||||
|
<!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
|
||||||
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/${FILE_NAME}-error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
|
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/${FILE_NAME}-error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
|
||||||
|
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
|
||||||
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
|
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||||
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
|
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
|
||||||
<Policies>
|
<Policies>
|
||||||
|
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
|
||||||
<TimeBasedTriggeringPolicy interval="1"/>
|
<TimeBasedTriggeringPolicy interval="1"/>
|
||||||
<SizeBasedTriggeringPolicy size="10MB"/>
|
<SizeBasedTriggeringPolicy size="10MB"/>
|
||||||
</Policies>
|
</Policies>
|
||||||
|
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
|
||||||
<DefaultRolloverStrategy max="15"/>
|
<DefaultRolloverStrategy max="15"/>
|
||||||
</RollingFile>
|
</RollingFile>
|
||||||
|
|
||||||
|
<!-- 数据库日志Appender - 异步写入DEBUG级别及以上的日志到数据库 -->
|
||||||
<DatabaseAppender name="DatabaseAppender" ignoreExceptions="false">
|
<DatabaseAppender name="DatabaseAppender" ignoreExceptions="false">
|
||||||
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
|
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||||
</DatabaseAppender>
|
</DatabaseAppender>
|
||||||
|
|
||||||
</appenders>
|
</appenders>
|
||||||
|
|
||||||
|
<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
|
||||||
|
<!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
|
||||||
<loggers>
|
<loggers>
|
||||||
<logger name="org.mybatis" level="info" additivity="false">
|
|
||||||
|
<!--过滤掉spring的一些无用的DEBUG信息-->
|
||||||
|
<logger name="org.mybatis" level="debug" additivity="false">
|
||||||
<AppenderRef ref="Console"/>
|
<AppenderRef ref="Console"/>
|
||||||
</logger>
|
</logger>
|
||||||
|
<!--监控系统信息-->
|
||||||
|
<!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,不会在 父Logger 的appender里输出。-->
|
||||||
<Logger name="org.springframework" level="info" additivity="false">
|
<Logger name="org.springframework" level="info" additivity="false">
|
||||||
<AppenderRef ref="Console"/>
|
<AppenderRef ref="Console"/>
|
||||||
</Logger>
|
</Logger>
|
||||||
|
|
||||||
<Logger name="org.xyzh" level="info" additivity="false">
|
<!-- MyBatis Mapper 日志配置 - 打印SQL -->
|
||||||
|
<Logger name="org.xyzh.achievement.mapper" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
</Logger>
|
||||||
|
<Logger name="org.xyzh.ai.mapper" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
</Logger>
|
||||||
|
<Logger name="org.xyzh.system.mapper" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
</Logger>
|
||||||
|
<Logger name="org.xyzh.news.mapper" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
</Logger>
|
||||||
|
<Logger name="org.xyzh.study.mapper" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
</Logger>
|
||||||
|
<Logger name="org.xyzh.crontab.mapper" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
</Logger>
|
||||||
|
<Logger name="org.xyzh.message.mapper" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
</Logger>
|
||||||
|
<!-- 项目包日志配置 - Auth模块 -->
|
||||||
|
<Logger name="org.xyzh.auth" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<AppenderRef ref="Filelog"/>
|
||||||
|
<AppenderRef ref="RollingFileInfo"/>
|
||||||
|
<AppenderRef ref="RollingFileWarn"/>
|
||||||
|
<AppenderRef ref="RollingFileError"/>
|
||||||
|
<AppenderRef ref="DatabaseAppender"/>
|
||||||
|
</Logger>
|
||||||
|
|
||||||
|
<!-- 项目包日志配置 - System模块 -->
|
||||||
|
<Logger name="org.xyzh.system" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<AppenderRef ref="Filelog"/>
|
||||||
|
<AppenderRef ref="RollingFileInfo"/>
|
||||||
|
<AppenderRef ref="RollingFileWarn"/>
|
||||||
|
<AppenderRef ref="RollingFileError"/>
|
||||||
|
<AppenderRef ref="DatabaseAppender"/>
|
||||||
|
</Logger>
|
||||||
|
|
||||||
|
<!-- 项目包日志配置 - News模块 -->
|
||||||
|
<Logger name="org.xyzh.news" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<AppenderRef ref="Filelog"/>
|
||||||
|
<AppenderRef ref="RollingFileInfo"/>
|
||||||
|
<AppenderRef ref="RollingFileWarn"/>
|
||||||
|
<AppenderRef ref="RollingFileError"/>
|
||||||
|
<AppenderRef ref="DatabaseAppender"/>
|
||||||
|
</Logger>
|
||||||
|
|
||||||
|
<!-- 项目包日志配置 - Common模块 -->
|
||||||
|
<Logger name="org.xyzh.common" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<AppenderRef ref="Filelog"/>
|
||||||
|
<AppenderRef ref="RollingFileInfo"/>
|
||||||
|
<AppenderRef ref="RollingFileWarn"/>
|
||||||
|
<AppenderRef ref="RollingFileError"/>
|
||||||
|
<AppenderRef ref="DatabaseAppender"/>
|
||||||
|
</Logger>
|
||||||
|
|
||||||
|
<!-- 项目包日志配置 - Achievement模块 -->
|
||||||
|
<Logger name="org.xyzh.achievement" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<AppenderRef ref="Filelog"/>
|
||||||
|
<AppenderRef ref="RollingFileInfo"/>
|
||||||
|
<AppenderRef ref="RollingFileWarn"/>
|
||||||
|
<AppenderRef ref="RollingFileError"/>
|
||||||
|
<AppenderRef ref="DatabaseAppender"/>
|
||||||
|
</Logger>
|
||||||
|
|
||||||
|
<Logger name="org.xyzh.crontab" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<AppenderRef ref="Filelog"/>
|
||||||
|
<AppenderRef ref="RollingFileInfo"/>
|
||||||
|
<AppenderRef ref="RollingFileWarn"/>
|
||||||
|
<AppenderRef ref="RollingFileError"/>
|
||||||
|
<AppenderRef ref="DatabaseAppender"/>
|
||||||
|
</Logger>
|
||||||
|
<Logger name="org.xyzh.message" level="debug" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<AppenderRef ref="Filelog"/>
|
||||||
|
<AppenderRef ref="RollingFileInfo"/>
|
||||||
|
<AppenderRef ref="RollingFileWarn"/>
|
||||||
|
<AppenderRef ref="RollingFileError"/>
|
||||||
|
<AppenderRef ref="DatabaseAppender"/>
|
||||||
|
</Logger>
|
||||||
|
<Logger name="org.xyzh.sensitive" level="debug" additivity="false">
|
||||||
<AppenderRef ref="Console"/>
|
<AppenderRef ref="Console"/>
|
||||||
<AppenderRef ref="Filelog"/>
|
<AppenderRef ref="Filelog"/>
|
||||||
<AppenderRef ref="RollingFileInfo"/>
|
<AppenderRef ref="RollingFileInfo"/>
|
||||||
@@ -85,4 +204,5 @@
|
|||||||
<appender-ref ref="DatabaseAppender"/>
|
<appender-ref ref="DatabaseAppender"/>
|
||||||
</root>
|
</root>
|
||||||
</loggers>
|
</loggers>
|
||||||
|
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ services:
|
|||||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-123456}
|
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-123456}
|
||||||
TZ: Asia/Shanghai
|
TZ: Asia/Shanghai
|
||||||
ports:
|
ports:
|
||||||
- "${MYSQL_PORT:-3306}:3306"
|
- "${MYSQL_PORT:-3307}:3306"
|
||||||
volumes:
|
volumes:
|
||||||
# 数据持久化(命名卷)
|
# 数据持久化(命名卷)
|
||||||
- mysql-data:/var/lib/mysql
|
- mysql-data:/var/lib/mysql
|
||||||
@@ -26,14 +26,16 @@ services:
|
|||||||
- --default-authentication-plugin=mysql_native_password
|
- --default-authentication-plugin=mysql_native_password
|
||||||
- --max_connections=1000
|
- --max_connections=1000
|
||||||
- --max_allowed_packet=64M
|
- --max_allowed_packet=64M
|
||||||
|
- --local-infile=1
|
||||||
networks:
|
networks:
|
||||||
- school-news-network
|
- school-news-network
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-p${MYSQL_ROOT_PASSWORD:-123456}"]
|
# 只有当 MySQL 可访问且敏感词表中至少有一条 deny 记录时,才认为 healthy
|
||||||
|
test: ["CMD-SHELL", "mysql -uroot -p${MYSQL_ROOT_PASSWORD:-123456} -D ${MYSQL_DATABASE:-school_news} -e \"SELECT 'ok' FROM tb_sensitive_word WHERE type='deny' LIMIT 1;\" 2>/dev/null | grep -q ok"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 5s
|
timeout: 10s
|
||||||
retries: 5
|
retries: 10
|
||||||
start_period: 30s
|
start_period: 60s
|
||||||
|
|
||||||
# Redis缓存
|
# Redis缓存
|
||||||
redis:
|
redis:
|
||||||
@@ -143,8 +145,10 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "${NGINX_PORT:-80}:80"
|
- "${NGINX_PORT:-80}:80"
|
||||||
volumes:
|
volumes:
|
||||||
# Nginx配置文件(命名卷)
|
# 仅挂载自定义 Nginx 主配置文件
|
||||||
- nginx-config:/etc/nginx:ro
|
- ./volumes/nginx/config/nginx.conf:/etc/nginx/nginx.conf
|
||||||
|
# 仅挂载站点配置目录(conf.d),保留镜像内的 mime.types 等其他文件
|
||||||
|
- nginx-conf-d:/etc/nginx/conf.d:ro
|
||||||
# 日志目录(命名卷)
|
# 日志目录(命名卷)
|
||||||
- nginx-logs:/var/log/nginx
|
- nginx-logs:/var/log/nginx
|
||||||
networks:
|
networks:
|
||||||
@@ -233,12 +237,19 @@ volumes:
|
|||||||
device: ./volumes/web/logs
|
device: ./volumes/web/logs
|
||||||
|
|
||||||
# ===== Nginx =====
|
# ===== Nginx =====
|
||||||
nginx-config:
|
nginx-conf-file:
|
||||||
driver: local
|
driver: local
|
||||||
driver_opts:
|
driver_opts:
|
||||||
type: none
|
type: none
|
||||||
o: bind
|
o: bind
|
||||||
device: ./volumes/nginx/config
|
device: ./volumes/nginx/config/nginx.conf
|
||||||
|
|
||||||
|
nginx-conf-d:
|
||||||
|
driver: local
|
||||||
|
driver_opts:
|
||||||
|
type: none
|
||||||
|
o: bind
|
||||||
|
device: ./volumes/nginx/config/conf.d
|
||||||
|
|
||||||
nginx-logs:
|
nginx-logs:
|
||||||
driver: local
|
driver: local
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ CREATE TABLE IF NOT EXISTS _db_init_status (
|
|||||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
script_name VARCHAR(255) NOT NULL UNIQUE,
|
script_name VARCHAR(255) NOT NULL UNIQUE,
|
||||||
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
status VARCHAR(50) DEFAULT 'success'
|
status VARCHAR(50) DEFAULT 'init'
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
-- 记录初始化标记
|
-- 记录初始化标记
|
||||||
|
|||||||
@@ -1,231 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
##############################################
|
|
||||||
# 数据库初始化SQL准备脚本
|
|
||||||
# 功能:将SQL文件复制到Docker初始化目录
|
|
||||||
# 基于:schoolNewsServ/.bin/mysql/sql/reInit.sh
|
|
||||||
##############################################
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# 颜色定义
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
log_info() {
|
|
||||||
echo -e "${GREEN}[INFO]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warn() {
|
|
||||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error() {
|
|
||||||
echo -e "${RED}[ERROR]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 路径定义
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
SQL_SOURCE_DIR="../../schoolNewsServ/.bin/mysql/sql"
|
|
||||||
INIT_DB_DIR="$SCRIPT_DIR"
|
|
||||||
|
|
||||||
echo "========================================"
|
|
||||||
echo "数据库初始化SQL准备"
|
|
||||||
echo "========================================"
|
|
||||||
log_info "源SQL目录: $SQL_SOURCE_DIR"
|
|
||||||
log_info "目标目录: $INIT_DB_DIR"
|
|
||||||
echo "========================================"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 检查源目录
|
|
||||||
if [ ! -d "$SQL_SOURCE_DIR" ]; then
|
|
||||||
log_error "源SQL目录不存在: $SQL_SOURCE_DIR"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 备份现有SQL文件
|
|
||||||
if ls "$INIT_DB_DIR"/*.sql 1> /dev/null 2>&1; then
|
|
||||||
log_warn "发现现有SQL文件,正在备份..."
|
|
||||||
BACKUP_DIR="$INIT_DB_DIR/backup_$(date +%Y%m%d_%H%M%S)"
|
|
||||||
mkdir -p "$BACKUP_DIR"
|
|
||||||
mv "$INIT_DB_DIR"/*.sql "$BACKUP_DIR/" 2>/dev/null || true
|
|
||||||
log_info "已备份到: $BACKUP_DIR"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 创建02-create-tables.sql
|
|
||||||
log_info "创建表结构脚本: 02-create-tables.sql"
|
|
||||||
cat > "$INIT_DB_DIR/02-create-tables.sql" << 'EOF'
|
|
||||||
-- ========================================
|
|
||||||
-- 校园新闻管理系统 - 表结构创建脚本
|
|
||||||
-- 自动生成时间: $(date '+%Y-%m-%d %H:%M:%S')
|
|
||||||
-- 基于: schoolNewsServ/.bin/mysql/sql/
|
|
||||||
-- ========================================
|
|
||||||
|
|
||||||
USE school_news;
|
|
||||||
|
|
||||||
-- 检查是否已执行过此脚本
|
|
||||||
SET @executed = (SELECT COUNT(*) FROM _db_init_status WHERE script_name = '02-create-tables.sql');
|
|
||||||
|
|
||||||
-- 如果已执行过,记录并退出
|
|
||||||
SELECT CASE
|
|
||||||
WHEN @executed > 0 THEN '表结构已存在,跳过创建'
|
|
||||||
ELSE '开始创建表结构...'
|
|
||||||
END AS message;
|
|
||||||
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# 合并所有createTable*.sql文件
|
|
||||||
log_info "合并表结构文件..."
|
|
||||||
TABLE_FILES=(
|
|
||||||
"createTableUser.sql"
|
|
||||||
"createTablePermission.sql"
|
|
||||||
"createTablePermissionControl.sql"
|
|
||||||
"createTableResource.sql"
|
|
||||||
"createTableCourse.sql"
|
|
||||||
"createTableLearning.sql"
|
|
||||||
"createTableUserCenter.sql"
|
|
||||||
"createTableAI.sql"
|
|
||||||
"createTableSystem.sql"
|
|
||||||
"createTableAchievement.sql"
|
|
||||||
"createTableCrontab.sql"
|
|
||||||
"createTableMessage.sql"
|
|
||||||
"createTableSensitive.sql"
|
|
||||||
)
|
|
||||||
|
|
||||||
for file in "${TABLE_FILES[@]}"; do
|
|
||||||
if [ -f "$SQL_SOURCE_DIR/$file" ]; then
|
|
||||||
echo "" >> "$INIT_DB_DIR/02-create-tables.sql"
|
|
||||||
echo "-- ========================================" >> "$INIT_DB_DIR/02-create-tables.sql"
|
|
||||||
echo "-- $file" >> "$INIT_DB_DIR/02-create-tables.sql"
|
|
||||||
echo "-- ========================================" >> "$INIT_DB_DIR/02-create-tables.sql"
|
|
||||||
cat "$SQL_SOURCE_DIR/$file" >> "$INIT_DB_DIR/02-create-tables.sql"
|
|
||||||
log_info " ✓ $file"
|
|
||||||
else
|
|
||||||
log_warn " ✗ $file (文件不存在)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# 添加执行状态记录
|
|
||||||
cat >> "$INIT_DB_DIR/02-create-tables.sql" << 'EOF'
|
|
||||||
|
|
||||||
-- 记录执行状态
|
|
||||||
INSERT IGNORE INTO _db_init_status (script_name)
|
|
||||||
VALUES ('02-create-tables.sql');
|
|
||||||
|
|
||||||
SELECT '表结构创建完成' AS message;
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 创建03-init-data.sql
|
|
||||||
log_info "创建初始数据脚本: 03-init-data.sql"
|
|
||||||
cat > "$INIT_DB_DIR/03-init-data.sql" << 'EOF'
|
|
||||||
-- ========================================
|
|
||||||
-- 校园新闻管理系统 - 初始数据导入脚本
|
|
||||||
-- 自动生成时间: $(date '+%Y-%m-%d %H:%M:%S')
|
|
||||||
-- 基于: schoolNewsServ/.bin/mysql/sql/
|
|
||||||
-- ========================================
|
|
||||||
|
|
||||||
USE school_news;
|
|
||||||
|
|
||||||
-- 检查是否已执行过此脚本
|
|
||||||
SET @executed = (SELECT COUNT(*) FROM _db_init_status WHERE script_name = '03-init-data.sql');
|
|
||||||
|
|
||||||
SELECT CASE
|
|
||||||
WHEN @executed > 0 THEN '初始数据已存在,跳过导入'
|
|
||||||
ELSE '开始导入初始数据...'
|
|
||||||
END AS message;
|
|
||||||
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# 合并初始数据文件
|
|
||||||
log_info "合并初始数据文件..."
|
|
||||||
DATA_FILES=(
|
|
||||||
"initMenuData.sql"
|
|
||||||
"initAllData.sql"
|
|
||||||
"initCrontabMetaData.sql"
|
|
||||||
)
|
|
||||||
|
|
||||||
for file in "${DATA_FILES[@]}"; do
|
|
||||||
if [ -f "$SQL_SOURCE_DIR/$file" ]; then
|
|
||||||
echo "" >> "$INIT_DB_DIR/03-init-data.sql"
|
|
||||||
echo "-- ========================================" >> "$INIT_DB_DIR/03-init-data.sql"
|
|
||||||
echo "-- $file" >> "$INIT_DB_DIR/03-init-data.sql"
|
|
||||||
echo "-- ========================================" >> "$INIT_DB_DIR/03-init-data.sql"
|
|
||||||
cat "$SQL_SOURCE_DIR/$file" >> "$INIT_DB_DIR/03-init-data.sql"
|
|
||||||
log_info " ✓ $file"
|
|
||||||
else
|
|
||||||
log_warn " ✗ $file (文件不存在)"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# 添加爬虫配置初始化
|
|
||||||
cat >> "$INIT_DB_DIR/03-init-data.sql" << 'EOF'
|
|
||||||
|
|
||||||
-- ========================================
|
|
||||||
-- Docker环境爬虫配置
|
|
||||||
-- ========================================
|
|
||||||
INSERT IGNORE INTO tb_sys_config (config_key, config_value, config_desc, created_at)
|
|
||||||
VALUES
|
|
||||||
('crawler.pythonPath', '/usr/bin/python3', 'Docker容器内Python路径', NOW()),
|
|
||||||
('crawler.basePath', '/app/crawler', 'Docker容器内爬虫脚本路径', NOW());
|
|
||||||
|
|
||||||
-- 记录执行状态
|
|
||||||
INSERT IGNORE INTO _db_init_status (script_name)
|
|
||||||
VALUES ('03-init-data.sql');
|
|
||||||
|
|
||||||
SELECT '初始数据导入完成' AS message;
|
|
||||||
SELECT '默认用户: admin, 密码: admin123' AS tip;
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 生成统计信息
|
|
||||||
log_info "生成文件统计..."
|
|
||||||
cat > "$INIT_DB_DIR/00-init-summary.txt" << EOF
|
|
||||||
========================================
|
|
||||||
数据库初始化脚本准备完成
|
|
||||||
========================================
|
|
||||||
生成时间: $(date '+%Y-%m-%d %H:%M:%S')
|
|
||||||
源目录: $SQL_SOURCE_DIR
|
|
||||||
|
|
||||||
生成的文件:
|
|
||||||
01-init-database.sql - 数据库创建(已存在)
|
|
||||||
02-create-tables.sql - 表结构创建
|
|
||||||
03-init-data.sql - 初始数据导入
|
|
||||||
|
|
||||||
执行顺序:
|
|
||||||
1. 创建数据库和初始化标记表
|
|
||||||
2. 创建所有业务表
|
|
||||||
3. 导入初始数据(用户、菜单、系统配置等)
|
|
||||||
|
|
||||||
默认账户:
|
|
||||||
用户名: admin
|
|
||||||
密码: admin123
|
|
||||||
角色: 管理员
|
|
||||||
|
|
||||||
注意事项:
|
|
||||||
1. 脚本具有幂等性,可以重复执行
|
|
||||||
2. 使用 _db_init_status 表跟踪执行状态
|
|
||||||
3. Docker容器启动时自动执行这些脚本
|
|
||||||
4. 如需重新初始化,删除数据卷: docker-compose down -v
|
|
||||||
|
|
||||||
========================================
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
log_info "========================================"
|
|
||||||
log_info "准备完成!"
|
|
||||||
log_info "========================================"
|
|
||||||
log_info "生成的文件:"
|
|
||||||
ls -lh "$INIT_DB_DIR"/*.sql 2>/dev/null | awk '{print " " $9 " (" $5 ")"}'
|
|
||||||
echo ""
|
|
||||||
log_info "下一步:"
|
|
||||||
echo " 1. 检查生成的SQL文件"
|
|
||||||
echo " 2. 运行Docker构建: ./build.sh"
|
|
||||||
echo " 3. 启动服务: cd docker && docker-compose up -d"
|
|
||||||
log_info "========================================"
|
|
||||||
@@ -32,6 +32,7 @@ mkdir -p "${VOLUMES_DIR}/nginx/logs"
|
|||||||
# 复制配置文件模板
|
# 复制配置文件模板
|
||||||
echo "复制配置文件模板..."
|
echo "复制配置文件模板..."
|
||||||
[ -f redis/redis.conf ] && cp redis/redis.conf "${VOLUMES_DIR}/redis/config/" || echo " ⚠️ redis.conf 不存在"
|
[ -f redis/redis.conf ] && cp redis/redis.conf "${VOLUMES_DIR}/redis/config/" || echo " ⚠️ redis.conf 不存在"
|
||||||
|
[ -f mysql/my.cnf ] && cp mysql/my.cnf "${VOLUMES_DIR}/mysql/" || echo " ⚠️ my.cnf 不存在"
|
||||||
[ -f config/application.yml ] && cp config/application.yml "${VOLUMES_DIR}/serv/config/" || echo " ⚠️ application.yml 不存在"
|
[ -f config/application.yml ] && cp config/application.yml "${VOLUMES_DIR}/serv/config/" || echo " ⚠️ application.yml 不存在"
|
||||||
[ -f config/log4j2-spring.xml ] && cp config/log4j2-spring.xml "${VOLUMES_DIR}/serv/config/" || echo " ⚠️ log4j2-spring.xml 不存在"
|
[ -f config/log4j2-spring.xml ] && cp config/log4j2-spring.xml "${VOLUMES_DIR}/serv/config/" || echo " ⚠️ log4j2-spring.xml 不存在"
|
||||||
[ -f config/web-app-config.js ] && cp config/web-app-config.js "${VOLUMES_DIR}/web/config/app-config.js" || echo " ⚠️ web-app-config.js 不存在"
|
[ -f config/web-app-config.js ] && cp config/web-app-config.js "${VOLUMES_DIR}/web/config/app-config.js" || echo " ⚠️ web-app-config.js 不存在"
|
||||||
|
|||||||
@@ -1,23 +1,20 @@
|
|||||||
# ====================================
|
|
||||||
# Nginx主配置文件
|
|
||||||
# 可通过docker-compose.yml挂载自定义配置
|
|
||||||
# ====================================
|
|
||||||
|
|
||||||
user nginx;
|
user nginx;
|
||||||
worker_processes auto;
|
worker_processes auto;
|
||||||
|
|
||||||
error_log /var/log/nginx/error.log notice;
|
error_log /var/log/nginx/error.log notice;
|
||||||
pid /var/run/nginx.pid;
|
pid /run/nginx.pid;
|
||||||
|
|
||||||
|
|
||||||
events {
|
events {
|
||||||
worker_connections 1024;
|
worker_connections 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
http {
|
http {
|
||||||
include /etc/nginx/mime.types;
|
include /etc/nginx/mime.types;
|
||||||
default_type application/octet-stream;
|
default_type application/octet-stream;
|
||||||
|
|
||||||
# 日志格式
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
@@ -25,20 +22,11 @@ http {
|
|||||||
access_log /var/log/nginx/access.log main;
|
access_log /var/log/nginx/access.log main;
|
||||||
|
|
||||||
sendfile on;
|
sendfile on;
|
||||||
tcp_nopush on;
|
#tcp_nopush on;
|
||||||
tcp_nodelay on;
|
|
||||||
keepalive_timeout 65;
|
keepalive_timeout 65;
|
||||||
types_hash_max_size 2048;
|
|
||||||
|
|
||||||
# Gzip压缩
|
#gzip on;
|
||||||
gzip on;
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_min_length 1024;
|
|
||||||
gzip_types text/plain text/css text/xml text/javascript
|
|
||||||
application/json application/javascript application/xml+rss
|
|
||||||
application/rss+xml font/truetype font/opentype
|
|
||||||
application/vnd.ms-fontobject image/svg+xml;
|
|
||||||
|
|
||||||
# 包含站点配置
|
|
||||||
include /etc/nginx/conf.d/*.conf;
|
include /etc/nginx/conf.d/*.conf;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,70 +93,34 @@ echo ""
|
|||||||
log_info "开始导入敏感词..."
|
log_info "开始导入敏感词..."
|
||||||
START_TIME=$(date +%s)
|
START_TIME=$(date +%s)
|
||||||
|
|
||||||
# 创建临时SQL文件
|
# 预处理:转义单引号,生成临时词表文件(仅一列:word)
|
||||||
TEMP_SQL=$(mktemp)
|
TEMP_WORDS=$(mktemp)
|
||||||
trap "rm -f ${TEMP_SQL}" EXIT
|
trap "rm -f ${TEMP_WORDS}" EXIT
|
||||||
|
sed "s/'/''/g" "${DICT_FILE}" > "${TEMP_WORDS}"
|
||||||
|
|
||||||
# 生成SQL语句
|
# 使用 LOAD DATA LOCAL INFILE 批量导入,极大提升导入性能
|
||||||
log_info "生成SQL语句..."
|
log_info "使用 LOAD DATA LOCAL INFILE 批量导入敏感词..."
|
||||||
cat > "${TEMP_SQL}" <<EOF
|
if mysql --local-infile=1 -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USER}" -p"${DB_PASSWORD}" "${DB_NAME}" <<EOF
|
||||||
-- 敏感词批量导入
|
|
||||||
USE ${DB_NAME};
|
|
||||||
|
|
||||||
-- 设置字符集
|
|
||||||
SET NAMES utf8mb4;
|
SET NAMES utf8mb4;
|
||||||
|
-- 清除现有的 deny 类型敏感词
|
||||||
-- 清除现有的deny类型敏感词
|
|
||||||
DELETE FROM tb_sensitive_word WHERE type = 'deny';
|
DELETE FROM tb_sensitive_word WHERE type = 'deny';
|
||||||
|
|
||||||
-- 批量插入敏感词
|
-- 从预处理文件批量导入敏感词(LOCAL 由客户端读取,避免 secure-file-priv 限制)
|
||||||
INSERT INTO tb_sensitive_word (word, type) VALUES
|
LOAD DATA LOCAL INFILE '${TEMP_WORDS}'
|
||||||
|
INTO TABLE tb_sensitive_word
|
||||||
|
CHARACTER SET utf8mb4
|
||||||
|
LINES TERMINATED BY '\n'
|
||||||
|
(word)
|
||||||
|
SET type = 'deny';
|
||||||
EOF
|
EOF
|
||||||
|
then
|
||||||
# 读取敏感词并生成INSERT语句
|
|
||||||
COUNTER=0
|
|
||||||
while IFS= read -r word || [ -n "$word" ]; do
|
|
||||||
# 跳过空行
|
|
||||||
[ -z "$word" ] && continue
|
|
||||||
|
|
||||||
# 转义单引号
|
|
||||||
word=$(echo "$word" | sed "s/'/''/g")
|
|
||||||
|
|
||||||
COUNTER=$((COUNTER + 1))
|
|
||||||
|
|
||||||
# 添加到SQL(最后一个不加逗号)
|
|
||||||
if [ $COUNTER -eq ${TOTAL_WORDS} ]; then
|
|
||||||
echo "('${word}', 'deny');" >> "${TEMP_SQL}"
|
|
||||||
else
|
|
||||||
echo "('${word}', 'deny')," >> "${TEMP_SQL}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 进度提示(每1000个)
|
|
||||||
if [ $((COUNTER % 1000)) -eq 0 ]; then
|
|
||||||
log_info "已处理 ${COUNTER}/${TOTAL_WORDS} 个敏感词..."
|
|
||||||
fi
|
|
||||||
done < "${DICT_FILE}"
|
|
||||||
|
|
||||||
# 添加查询语句
|
|
||||||
cat >> "${TEMP_SQL}" <<EOF
|
|
||||||
|
|
||||||
-- 验证导入结果
|
|
||||||
SELECT COUNT(*) AS '导入数量' FROM tb_sensitive_word WHERE type = 'deny';
|
|
||||||
EOF
|
|
||||||
|
|
||||||
log_info "SQL语句生成完成(${COUNTER}个敏感词)"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 执行SQL
|
|
||||||
log_info "执行数据库导入..."
|
|
||||||
if mysql -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USER}" -p"${DB_PASSWORD}" < "${TEMP_SQL}"; then
|
|
||||||
END_TIME=$(date +%s)
|
END_TIME=$(date +%s)
|
||||||
DURATION=$((END_TIME - START_TIME))
|
DURATION=$((END_TIME - START_TIME))
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "=================================================="
|
echo "=================================================="
|
||||||
log_info "导入完成!"
|
log_info "导入完成!"
|
||||||
log_info "成功导入: ${COUNTER} 个敏感词"
|
log_info "成功导入: ${TOTAL_WORDS} 个敏感词(基于文件统计)"
|
||||||
log_info "耗时: ${DURATION} 秒"
|
log_info "耗时: ${DURATION} 秒"
|
||||||
echo "=================================================="
|
echo "=================================================="
|
||||||
else
|
else
|
||||||
@@ -172,10 +136,10 @@ IMPORTED_COUNT=$(mysql -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USER}" -p"${DB_PASS
|
|||||||
echo ""
|
echo ""
|
||||||
log_info "数据库中当前有 ${IMPORTED_COUNT} 个 deny 类型敏感词"
|
log_info "数据库中当前有 ${IMPORTED_COUNT} 个 deny 类型敏感词"
|
||||||
|
|
||||||
if [ "${IMPORTED_COUNT}" -eq "${COUNTER}" ]; then
|
if [ "${IMPORTED_COUNT}" -eq "${TOTAL_WORDS}" ]; then
|
||||||
log_info "✅ 验证通过:导入数量与预期一致"
|
log_info "✅ 验证通过:导入数量与预期一致"
|
||||||
else
|
else
|
||||||
log_warn "⚠️ 导入数量不匹配:预期 ${COUNTER},实际 ${IMPORTED_COUNT}"
|
log_warn "⚠️ 导入数量不匹配:预期 ${TOTAL_WORDS},实际 ${IMPORTED_COUNT}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import axios, { AxiosResponse, AxiosError, InternalAxiosRequestConfig } from "axios";
|
import axios, { AxiosResponse, AxiosError, InternalAxiosRequestConfig } from "axios";
|
||||||
import { ElLoading, ElMessage } from "element-plus";
|
import { ElLoading, ElMessage } from "element-plus";
|
||||||
import type { ResultDomain } from "@/types";
|
import type { ResultDomain } from "@/types";
|
||||||
|
import { API_BASE_URL } from "@/config";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 扩展AxiosRequestConfig以支持自定义配置
|
* 扩展AxiosRequestConfig以支持自定义配置
|
||||||
@@ -67,9 +68,13 @@ export const TokenManager = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建axios实例
|
* 创建axios实例
|
||||||
|
*
|
||||||
|
* 说明:
|
||||||
|
* - 统一使用配置模块提供的 API_BASE_URL 作为基础路径
|
||||||
|
* - API_BASE_URL 在开发环境来自 devConfig,在生产环境来自 window.APP_RUNTIME_CONFIG
|
||||||
*/
|
*/
|
||||||
const request = axios.create({
|
const request = axios.create({
|
||||||
baseURL: import.meta.env.VITE_API_BASE_URL || "/api",
|
baseURL: API_BASE_URL,
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json;charset=UTF-8',
|
'Content-Type': 'application/json;charset=UTF-8',
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import type { SysMenu } from '@/types';
|
|||||||
import { MenuType } from '@/types/enums';
|
import { MenuType } from '@/types/enums';
|
||||||
import { routes } from '@/router';
|
import { routes } from '@/router';
|
||||||
|
|
||||||
|
// 预注册所有视图组件,构建时由 Vite 解析并生成按需加载的 chunk
|
||||||
|
const VIEW_MODULES = import.meta.glob('../views/**/*.vue');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 布局组件映射
|
* 布局组件映射
|
||||||
*/
|
*/
|
||||||
@@ -281,69 +284,44 @@ function findFirstMenuWithUrl(menus: SysMenu[]): SysMenu | null {
|
|||||||
* @returns 组件异步加载函数
|
* @returns 组件异步加载函数
|
||||||
*/
|
*/
|
||||||
function getComponent(componentName: string) {
|
function getComponent(componentName: string) {
|
||||||
// 检查是否是布局组件
|
// 1. 若是布局组件,直接返回预定义映射
|
||||||
if (LAYOUT_MAP[componentName]) {
|
if (LAYOUT_MAP[componentName]) {
|
||||||
return LAYOUT_MAP[componentName];
|
return LAYOUT_MAP[componentName];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理页面组件路径
|
// 2. 将后台给的 component 字段转换为 ../views/**.vue 形式的 key
|
||||||
let componentPath = componentName;
|
let componentPath = componentName;
|
||||||
|
|
||||||
// 如果不是以@/开头的完整路径,则添加@/views/前缀
|
// 如果不是以 @/ 开头,则认为是相对 views 根目录的路径,例如 "user/home/HomeView"
|
||||||
if (!componentPath.startsWith('@/')) {
|
if (!componentPath.startsWith('@/')) {
|
||||||
// 确保路径以/开头
|
|
||||||
if (!componentPath.startsWith('/')) {
|
if (!componentPath.startsWith('/')) {
|
||||||
componentPath = '/' + componentPath;
|
componentPath = '/' + componentPath;
|
||||||
}
|
}
|
||||||
// 添加@/views前缀
|
componentPath = '@/views' + componentPath; // => '@/views/user/home/HomeView'
|
||||||
componentPath = '@/views' + componentPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将@/别名转换为相对路径,因为Vite动态导入可能无法正确解析别名
|
// 将别名 @/ 转为相对于当前文件的路径,必须与 import.meta.glob 中的模式一致
|
||||||
if (componentPath.startsWith('@/')) {
|
componentPath = componentPath.replace(/^@\//, '../'); // => '../views/user/home/HomeView'
|
||||||
componentPath = componentPath.replace('@/', '../');
|
|
||||||
}
|
// 补全 .vue 后缀
|
||||||
|
|
||||||
// 如果没有.vue扩展名,添加它
|
|
||||||
if (!componentPath.endsWith('.vue')) {
|
if (!componentPath.endsWith('.vue')) {
|
||||||
componentPath += '.vue';
|
componentPath += '.vue';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. 从 VIEW_MODULES 中查找对应的 loader
|
||||||
// 动态导入组件
|
const loader = VIEW_MODULES[componentPath];
|
||||||
return () => {
|
|
||||||
return import(/* @vite-ignore */ componentPath)
|
if (!loader) {
|
||||||
.then(module => {
|
console.error('[路由生成] 未找到组件模块', {
|
||||||
return module;
|
原始组件名: componentName,
|
||||||
})
|
期望路径: componentPath,
|
||||||
.catch(error => {
|
可用模块: Object.keys(VIEW_MODULES)
|
||||||
console.error('[路由生成] 组件加载失败:', {
|
});
|
||||||
原始组件名: componentName,
|
// 找不到时退回到 404 组件
|
||||||
最终路径: componentPath,
|
return () => import('@/views/public/error/404.vue');
|
||||||
错误: error
|
}
|
||||||
});
|
|
||||||
// 返回404组件
|
return loader as () => Promise<any>;
|
||||||
return import('@/views/public/error/404.vue').catch(() =>
|
|
||||||
Promise.resolve({
|
|
||||||
template: `<div class="component-error">
|
|
||||||
<h3>组件加载失败</h3>
|
|
||||||
<p>无法加载组件: ${componentPath}</p>
|
|
||||||
<p>原始组件名: ${componentName}</p>
|
|
||||||
<p>错误: ${error instanceof Error ? error.message : String(error)}</p>
|
|
||||||
</div>`,
|
|
||||||
style: `
|
|
||||||
.component-error {
|
|
||||||
padding: 20px;
|
|
||||||
text-align: center;
|
|
||||||
color: #f56565;
|
|
||||||
background: #fed7d7;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user