镜像制作

This commit is contained in:
2025-11-24 11:50:15 +08:00
parent 12592c5a24
commit 07bd166257
53 changed files with 3822 additions and 2140 deletions

View File

@@ -0,0 +1,184 @@
server:
port: 8081
servlet:
context-path: /schoolNewsServ
encoding:
charset: UTF-8
enabled: true
force: true
spring:
application:
name: school-news-admin
# 数据源配置 - Docker环境
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://${MYSQL_HOST:mysql}:${MYSQL_PORT:3306}/${MYSQL_DATABASE:school_news}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
username: ${MYSQL_USER:root}
password: ${MYSQL_PASSWORD:123456}
hikari:
maximum-pool-size: 30
minimum-idle: 10
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
# Redis配置 - Docker环境
data:
redis:
host: ${REDIS_HOST:redis}
port: ${REDIS_PORT:6379}
password: ${REDIS_PASSWORD:123456}
database: 0
timeout: 10000
lettuce:
pool:
max-active: 50
max-wait: 3000
max-idle: 20
min-idle: 5
shutdown-timeout: 100ms
# 邮件配置
mail:
host: smtp.qq.com
port: 587
username: 3223905473@qq.com
password: xmdmxvtjumxocicc
default-encoding: UTF-8
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
# 短信服务配置
sms:
enabled: false
provider: aliyun
access-key-id: LTAI5t68do3qVXx5Rufugt3X
access-key-secret: 2vD9ToIff49Vph4JQXsn0Cy8nXQfzA
sign-name: 星洋智慧
template-code: SMS_491985030
region-id: cn-hangzhou
endpoint: dysmsapi.aliyuncs.com
# 认证配置
school-news:
auth:
jwt-secret: schoolNewsSecretKeyForJWT2025SecureEnough
jwt-expiration: 86400
max-login-attempts: 5
lockout-duration: 30
white-list:
- "/auth/login"
- "/auth/logout"
- "/auth/register"
- "/auth/captcha"
- "/auth/send-sms-code"
- "/auth/send-email-code"
- "/auth/health"
- "/actuator/**"
- "/swagger-ui/**"
- "/v3/api-docs/**"
- "/favicon.ico"
- "/error"
- "/public/**"
- "/static/**"
- "/file/download/**"
- "/ai/chat/stream/**"
# 爬虫配置 - Docker环境
crawler:
# 容器内Python路径
pythonPath: /usr/bin/python3
# 容器内爬虫脚本根目录
basePath: /app/crawler
crontab:
items:
- name: 人民日报新闻爬取
methods:
- name: 关键字搜索爬取
clazz: newsCrewerTask
excuete_method: execute
path: crawler/RmrbSearch.py
params:
- name: query
description: 搜索关键字
type: String
value: ""
- name: total
description: 总新闻数量
type: Integer
value: 10
- name: 排行榜爬取
clazz: newsCrewerTask
excuete_method: execute
path: crawler/RmrbHotPoint.py
- name: 往日精彩头条爬取
clazz: newsCrewerTask
excuete_method: execute
path: crawler/RmrbTrending.py
params:
- name: startDate
description: 开始日期
type: String
value: ""
- name: endDate
description: 结束日期
type: String
value: ""
- name: yesterday
description: 是否是昨天
type: Boolean
value: true
# dify
dify:
knowledgeApiKey: dataset-nupqKP4LONpzdXmGthIrbjeJ
# 文件存储配置
file:
storage:
storages:
- type: local
enabled: true
base-path: /app/uploads
# MyBatis Plus配置
mybatis-plus:
type-aliases-package: org.xyzh.common.dto
mapper-locations: classpath*:mapper/*.xml
global-config:
db-config:
logic-delete-field: deleted
logic-delete-value: 1
logic-not-delete-value: 0
insert-strategy: not_null
update-strategy: not_null
select-strategy: not_empty
configuration:
map-underscore-to-camel-case: true
cache-enabled: true
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
# 日志配置
logging:
config: classpath:log4j2-spring.xml
charset:
console: UTF-8
file: UTF-8
# 管理端点配置
management:
endpoints:
web:
exposure:
include: health,info,metrics,env
endpoint:
health:
show-details: when-authorized
debug: false

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
校园新闻管理系统 - Docker环境日志配置
-->
<configuration status="WARN" monitorInterval="30">
<Properties>
<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_NAME" value="school-news-admin" />
<property name="file.encoding" value="UTF-8" />
<property name="console.encoding" value="UTF-8" />
<property name="stdout.encoding" value="UTF-8" />
<property name="stderr.encoding" value="UTF-8" />
</Properties>
<appenders>
<console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</console>
<File name="Filelog" fileName="${FILE_PATH}/${FILE_NAME}-test.log" append="false">
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
</File>
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/${FILE_NAME}-info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/${FILE_NAME}-warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/${FILE_NAME}-error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<DatabaseAppender name="DatabaseAppender" ignoreExceptions="false">
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</DatabaseAppender>
</appenders>
<loggers>
<logger name="org.mybatis" level="info" additivity="false">
<AppenderRef ref="Console"/>
</logger>
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.xyzh" level="info" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="Filelog"/>
<AppenderRef ref="RollingFileInfo"/>
<AppenderRef ref="RollingFileWarn"/>
<AppenderRef ref="RollingFileError"/>
<AppenderRef ref="DatabaseAppender"/>
</Logger>
<root level="info">
<appender-ref ref="Console"/>
<appender-ref ref="Filelog"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
<appender-ref ref="DatabaseAppender"/>
</root>
</loggers>
</configuration>

View File

@@ -0,0 +1,74 @@
/**
* 前端应用配置文件
*
* 此文件用于Docker部署时的配置外挂
* 挂载方式docker-compose.yml 中配置
* volumes:
* - ./config/web-app-config.js:/app/config/app-config.js
*
* 修改步骤:
* 1. 编辑此文件
* 2. 重启容器docker-compose restart school-news-web
* 3. 刷新浏览器即可生效
*
* 注意:此文件结构必须与 schoolNewsWeb/public/app-config.js 保持一致
*/
(function() {
'use strict';
window.APP_RUNTIME_CONFIG = {
// 环境标识
env: 'production',
// API 配置
api: {
baseUrl: '/schoolNewsServ', // API基础路径
timeout: 30000 // 请求超时时间(毫秒)
},
// 应用基础路径
baseUrl: '/schoolNewsWeb/',
// 文件配置
file: {
downloadUrl: '/schoolNewsServ/file/download/',
uploadUrl: '/schoolNewsServ/file/upload/',
maxSize: {
image: 5, // MB
video: 100, // MB
document: 10 // MB
},
acceptTypes: {
image: 'image/*',
video: 'video/*',
document: '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx'
}
},
// Token 配置
token: {
key: 'token',
refreshThreshold: 300000 // 5分钟毫秒
},
// 公共路径
publicImgPath: '/schoolNewsWeb/img',
publicWebPath: '/schoolNewsWeb',
// 功能开关(可自由扩展)
features: {
enableDebug: false, // 是否启用调试模式
enableMockData: false // 是否启用Mock数据
}
};
// 配置加载完成标记
window.__CONFIG_LOADED__ = true;
// 控制台输出配置信息
if (console && console.log) {
console.log('%c[配置]%c Docker配置已加载', 'color: green; font-weight: bold', 'color: inherit');
console.log('[配置] 环境:', window.APP_RUNTIME_CONFIG.env);
console.log('[配置] API地址:', window.APP_RUNTIME_CONFIG.api.baseUrl);
}
})();

View File

@@ -0,0 +1,57 @@
/**
* @description 应用配置 - Docker生产环境
* @author yslg
* @since 2025-10-18
*/
// 生产环境配置
const isDev = false;
// API 基础路径 - Docker环境使用相对路径
export const API_BASE_URL = '/schoolNewsServ';
// 文件下载路径
export const FILE_DOWNLOAD_URL = `${API_BASE_URL}/file/download/`;
// 应用配置
export const APP_CONFIG = {
// 应用标题
title: '校园新闻管理系统',
// 基础路径
baseUrl: '/schoolNewsWeb/',
// API 配置
api: {
baseUrl: API_BASE_URL,
timeout: 30000
},
// 文件配置
file: {
downloadUrl: FILE_DOWNLOAD_URL,
uploadUrl: `${API_BASE_URL}/file/upload`,
maxSize: {
image: 5, // MB
video: 100, // MB
document: 10 // MB
},
acceptTypes: {
image: 'image/*',
video: 'video/*',
document: '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx'
}
},
// Token 配置
token: {
key: 'token',
refreshThreshold: 5 * 60 * 1000 // 提前5分钟刷新
}
};
// 公共资源路径 - Docker环境
export const PUBLIC_IMG_PATH = '/schoolNewsWeb/img';
export const PUBLIC_WEB_PATH = '/schoolNewsWeb';
export default APP_CONFIG;

View File

@@ -0,0 +1,81 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
import { resolve } from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
VitePWA({
registerType: 'autoUpdate',
workbox: {
cleanupOutdatedCaches: true,
skipWaiting: true,
clientsClaim: true
}
})
],
// 基础路径
base: '/schoolNewsWeb/',
file: {
downloadUrl: "http://school-news-serv:8081/schoolNewsServ/file/download/"
},
// 输出目录
build: {
outDir: 'dist',
assetsDir: 'static',
sourcemap: false,
chunkSizeWarningLimit: 1500,
rollupOptions: {
output: {
manualChunks: {
'vue-vendor': ['vue', 'vue-router', 'vuex'],
'element-plus': ['element-plus']
}
}
}
},
// 路径别名
resolve: {
alias: {
'@': resolve(__dirname, 'src')
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
},
// 环境变量
define: {
'process.env.BASE_URL': JSON.stringify('/schoolNewsWeb/'),
'process.env.VITE_API_BASE_URL': JSON.stringify('/api'),
'process.env.VITE_APP_TITLE': JSON.stringify('校园新闻管理系统')
},
// 开发服务器配置(生产环境无效)
server: {
host: '0.0.0.0',
port: 8080,
open: '/schoolNewsWeb/',
// 代理配置
proxy: {
'/api': {
target: 'http://school-news-serv:8081/schoolNewsServ',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
// CSS 配置
css: {
preprocessorOptions: {
scss: {
additionalData: ''
}
}
}
})