Enhance database management features by adding an API endpoint to drop all tables with double confirmation. Implement configuration file upload and download functionalities, including backup of the existing configuration. Update UI elements for improved user experience, including pagination controls and toast notifications. Adjust Docker and git ignore files to optimize build processes.
This commit is contained in:
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
# 此文件用于确保 dist 目录被 Git 跟踪
|
||||
# dist 目录用于存放离线部署包
|
||||
Vendored
+243
@@ -0,0 +1,243 @@
|
||||
{
|
||||
"Update": "2026/01/14 09:14:43",
|
||||
"MySQL_DBInfo": {
|
||||
"host": "capacity-mysql",
|
||||
"port": 3306,
|
||||
"user": "root",
|
||||
"passwd": "gmcc123",
|
||||
"dbname": "CapacityReport"
|
||||
},
|
||||
"SheetFilter": [
|
||||
"指标(计数器)",
|
||||
"Template"
|
||||
],
|
||||
"ExtractField": [
|
||||
{
|
||||
"Field": "日期时间",
|
||||
"Extract": [
|
||||
"开始时间"
|
||||
],
|
||||
"Type": "datetime"
|
||||
},
|
||||
{
|
||||
"Field": "网元ID",
|
||||
"Extract": [
|
||||
"网元ID",
|
||||
"网元"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "eNodeBId",
|
||||
"Extract": [
|
||||
"eNodeBId",
|
||||
"eNodeB"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "cellLocalId",
|
||||
"Extract": [
|
||||
"cellId",
|
||||
"小区"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "基站名称",
|
||||
"Extract": [
|
||||
"eNodeB CU名称",
|
||||
"eNodeB名称"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "小区名称",
|
||||
"Extract": [
|
||||
"小区名称",
|
||||
"E-UTRAN FDD小区名称",
|
||||
"E-UTRAN TDD小区名称"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "上下行总流量_GB",
|
||||
"Extract": [
|
||||
"集团-上下行总业务量(GB)",
|
||||
"业务流量上下行(GB)",
|
||||
"YJ_业务流量上下行(GB)",
|
||||
"FDD总流量(G)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "ERAB流量",
|
||||
"Extract": [
|
||||
"ERAB流量(新高负荷)",
|
||||
"ERAB流量",
|
||||
"ERAB流量(新高负荷)",
|
||||
"ERAB流量(新高负荷)-FDD"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "上行流量_GB",
|
||||
"Extract": [
|
||||
"上行流量(新高负荷GB)",
|
||||
"上行流量(新高负荷GB)",
|
||||
"高负荷-上行流量(GB)",
|
||||
"FDD上行流量(G)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "下行流量_GB",
|
||||
"Extract": [
|
||||
"下行流量(新高负荷GB)",
|
||||
"下行流量(新高负荷GB)",
|
||||
"高负荷-下行流量(GB)",
|
||||
"FDD下行流量(G)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "用户面平均激活UE数",
|
||||
"Extract": [
|
||||
"用户面平均激活UE数",
|
||||
"YY-用户面平均激活UE数(个)",
|
||||
"用户面平均激活UE数(unit)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "RRC连接建立最大用户数",
|
||||
"Extract": [
|
||||
"YY-RRC连接建立最大用户数(个)",
|
||||
"RRC连接建立最大用户数(unit)",
|
||||
"RRC连接建立最大用户数"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "上行PUSCH利用率",
|
||||
"Extract": [
|
||||
"上行PUSCH利用率",
|
||||
"YY-上行PUSCH利用率",
|
||||
"上行PUSCH利用率-FDD"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "下行PDSCH利用率",
|
||||
"Extract": [
|
||||
"下行PDSCH利用率",
|
||||
"YY-下行PDSCH利用率",
|
||||
"下行PDSCH利用率-FDD"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "PDCCH资源利用率",
|
||||
"Extract": [
|
||||
"PDCCH资源利用率",
|
||||
"PDCCH资源利用率_1548034713403-33-2",
|
||||
"PDCCH资源使用率(%)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "用户面最大激活UE数",
|
||||
"Extract": [
|
||||
"开发者大会保障--最大激活UE数",
|
||||
"用户面最大激活UE数",
|
||||
"YY-用户面最大激活UE数(个)",
|
||||
"用户面最大激活UE数(unit)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "CU小区配置名称",
|
||||
"Extract": [
|
||||
"CU小区配置名称"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "gNBId",
|
||||
"Extract": [
|
||||
"gNBId"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "gNBplmn",
|
||||
"Extract": [
|
||||
"gNBplmn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "5G上下行总流量_GB",
|
||||
"Extract": [
|
||||
"5G上下行总流量(上行PDCP PDU数据量+下行PDCP成功发送数据量)(GB)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "5G上行流量_GB",
|
||||
"Extract": [
|
||||
"5G上行流量(上行PDCP PDU数据量)_1603677232210(GB)",
|
||||
"5G上行流量(上行PDCP PDU数据量)(GB)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "5G下行流量_GB",
|
||||
"Extract": [
|
||||
"5G下行流量(下行PDCP成功发送数据量)_1603677232245(GB)",
|
||||
"5G下行流量(下行PDCP成功发送数据量)(GB)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "小区平均激活UE数",
|
||||
"Extract": [
|
||||
"小区平均激活UE数"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "RRC连接最大连接用户数",
|
||||
"Extract": [
|
||||
"RRC连接最大连接用户数"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "RRC连接平均连接用户数",
|
||||
"Extract": [
|
||||
"RRC连接平均连接用户数"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "小区最大激活UE数",
|
||||
"Extract": [
|
||||
"小区最大激活UE数"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "上行PRB平均利用率",
|
||||
"Extract": [
|
||||
"上行PRB平均利用率"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "下行PRB平均利用率",
|
||||
"Extract": [
|
||||
"下行PRB平均利用率"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "小区下行RLC_SDU字节数_MByte",
|
||||
"Extract": [
|
||||
"小区下行RLC SDU字节数(MByte)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "小区上行RLC_SDU字节数_MByte",
|
||||
"Extract": [
|
||||
"小区上行RLC SDU字节数(MByte)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "PDCCH信道动态CCE占用率",
|
||||
"Extract": [
|
||||
"PDCCH信道CCE占用率(动态)(%)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Field": "平均单Flow流量_MB",
|
||||
"Extract": [
|
||||
"平均单Flow流量(MB)",
|
||||
"平均每flow流量(流量/flow(MB/flow))"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+471
@@ -0,0 +1,471 @@
|
||||
# Update: 2024/11/25 09:30:00
|
||||
|
||||
SET GLOBAL wait_timeout = 86400;
|
||||
DROP TABLE IF EXISTS `4G`;
|
||||
DROP TABLE IF EXISTS `5G`;
|
||||
DROP TABLE IF EXISTS `4G_Date`;
|
||||
DROP TABLE IF EXISTS `4G_MAX`;
|
||||
DROP TABLE IF EXISTS `CCE_MAX`;
|
||||
DROP TABLE IF EXISTS `ULPRB_MAX`;
|
||||
DROP TABLE IF EXISTS `DLPRB_MAX`;
|
||||
DROP TABLE IF EXISTS `4G_MAX_IDX`;
|
||||
DROP TABLE IF EXISTS `CCE_MAX_IDX`;
|
||||
DROP TABLE IF EXISTS `ULPRB_MAX_IDX`;
|
||||
DROP TABLE IF EXISTS `DLPRB_MAX_IDX`;
|
||||
DROP TABLE IF EXISTS `日流量`;
|
||||
DROP TABLE IF EXISTS `4G日均流量`;
|
||||
DROP TABLE IF EXISTS `4G_结果表`;
|
||||
|
||||
DROP TABLE IF EXISTS `5G_Date`;
|
||||
DROP TABLE IF EXISTS `5G_MAX`;
|
||||
DROP TABLE IF EXISTS `5G_MAX_IDX`;
|
||||
DROP TABLE IF EXISTS `5G日均流量`;
|
||||
DROP TABLE IF EXISTS `5G_结果表`;
|
||||
|
||||
|
||||
CREATE TABLE `4G` AS SELECT * FROM `4G_UD`;
|
||||
CREATE TABLE `5G` AS SELECT * FROM `5G_UD`;
|
||||
|
||||
UPDATE 4G SET `日期时间` = DATE_FORMAT(`日期时间`, '%Y-%m-%d %H:%i:%s');
|
||||
UPDATE 5G SET `日期时间` = DATE_FORMAT(`日期时间`, '%Y-%m-%d %H:%i:%s');
|
||||
|
||||
ALTER TABLE `4G`
|
||||
ADD COLUMN `日期` date NULL FIRST,
|
||||
MODIFY COLUMN `日期时间` datetime,
|
||||
ADD COLUMN `CGI` varchar(100) NULL AFTER `日期时间`,
|
||||
MODIFY COLUMN `网元ID` int,
|
||||
MODIFY COLUMN `基站名称` varchar(200),
|
||||
MODIFY COLUMN `小区名称` varchar(200),
|
||||
MODIFY COLUMN `cellLocalId` int,
|
||||
MODIFY COLUMN `eNodeBId` int,
|
||||
MODIFY COLUMN `上下行总流量_GB` float,
|
||||
MODIFY COLUMN `ERAB流量` float,
|
||||
MODIFY COLUMN `上行流量_GB` float,
|
||||
MODIFY COLUMN `下行流量_GB` float,
|
||||
MODIFY COLUMN `用户面平均激活UE数` float,
|
||||
MODIFY COLUMN `RRC连接建立最大用户数` int,
|
||||
MODIFY COLUMN `上行PUSCH利用率` float,
|
||||
MODIFY COLUMN `下行PDSCH利用率` float,
|
||||
MODIFY COLUMN `PDCCH资源利用率` float,
|
||||
MODIFY COLUMN `用户面最大激活UE数` int;
|
||||
|
||||
ALTER TABLE `5G`
|
||||
ADD COLUMN `日期` date NULL FIRST,
|
||||
MODIFY COLUMN `日期时间` datetime,
|
||||
ADD COLUMN `NCGI` varchar(100) NULL AFTER `日期时间`,
|
||||
MODIFY COLUMN `网元ID` int,
|
||||
MODIFY COLUMN `CU小区配置名称` varchar(200),
|
||||
MODIFY COLUMN `cellLocalId` int,
|
||||
MODIFY COLUMN `gNBId` int,
|
||||
MODIFY COLUMN `gNBplmn` varchar(200),
|
||||
MODIFY COLUMN `5G上下行总流量_GB` float,
|
||||
MODIFY COLUMN `5G上行流量_GB` float,
|
||||
MODIFY COLUMN `5G下行流量_GB` float,
|
||||
MODIFY COLUMN `小区平均激活UE数` float,
|
||||
MODIFY COLUMN `RRC连接最大连接用户数` int,
|
||||
MODIFY COLUMN `RRC连接平均连接用户数` float,
|
||||
MODIFY COLUMN `小区最大激活UE数` float,
|
||||
MODIFY COLUMN `上行PRB平均利用率` float,
|
||||
MODIFY COLUMN `下行PRB平均利用率` float,
|
||||
MODIFY COLUMN `小区下行RLC_SDU字节数_MByte` float,
|
||||
MODIFY COLUMN `小区上行RLC_SDU字节数_MByte` float,
|
||||
MODIFY COLUMN `PDCCH信道动态CCE占用率` float,
|
||||
MODIFY COLUMN `平均单Flow流量_MB` float;
|
||||
|
||||
UPDATE 4G SET `日期` = DATE_FORMAT(`日期时间`, '%Y-%m-%d'), CGI = CONCAT("460-00-",eNodeBId,"-", cellLocalId);
|
||||
UPDATE 5G SET gNBplmn = "460-00" WHERE gNBplmn IS NULL;
|
||||
UPDATE 5G SET `日期` = DATE_FORMAT(`日期时间`, '%Y-%m-%d'), NCGI = CONCAT(gNBplmn, "-",gNBId,"-", cellLocalId);
|
||||
|
||||
ALTER TABLE 4G
|
||||
ADD INDEX(`日期`),
|
||||
ADD INDEX(`日期时间`),
|
||||
ADD INDEX(`CGI`),
|
||||
ADD INDEX `TC`(`日期时间`, `CGI`),
|
||||
ADD INDEX `DC`(`日期`, `CGI`);
|
||||
|
||||
ALTER TABLE 5G
|
||||
ADD INDEX(`日期`),
|
||||
ADD INDEX(`日期时间`),
|
||||
ADD INDEX(`NCGI`),
|
||||
ADD INDEX `TC`(`日期时间`, `NCGI`),
|
||||
ADD INDEX `DC`(`日期`, `NCGI`);
|
||||
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `CCE_MAX_IDX`(
|
||||
SELECT
|
||||
`日期`,
|
||||
CGI,
|
||||
MAX( `PDCCH资源利用率`) AS `PDCCH资源利用率_忙时`
|
||||
FROM 4G
|
||||
GROUP BY `日期`, CGI
|
||||
);
|
||||
|
||||
ALTER TABLE `CCE_MAX_IDX`
|
||||
ADD COLUMN `日期时间` datetime,
|
||||
ADD INDEX `DC`(`日期`, `CGI`, `PDCCH资源利用率_忙时`),
|
||||
ADD INDEX `TC`(`日期时间`, `CGI`);
|
||||
|
||||
UPDATE `CCE_MAX_IDX` INNER JOIN 4G
|
||||
ON
|
||||
`CCE_MAX_IDX`.`日期` = 4G.`日期` AND
|
||||
`CCE_MAX_IDX`.CGI=4G.CGI AND
|
||||
`CCE_MAX_IDX`.`PDCCH资源利用率_忙时`=4G.`PDCCH资源利用率`
|
||||
SET
|
||||
`CCE_MAX_IDX`.`日期时间`=4G.`日期时间`;
|
||||
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `CCE_MAX` (
|
||||
SELECT 4G.*
|
||||
FROM `CCE_MAX_IDX` LEFT JOIN 4G
|
||||
ON `CCE_MAX_IDX`.CGI=4G.CGI AND
|
||||
`CCE_MAX_IDX`.`日期时间`=4G.`日期时间`
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `CCE_MAX_IDX`;
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `ULPRB_MAX_IDX`(
|
||||
SELECT
|
||||
`日期`,
|
||||
CGI,
|
||||
MAX( `上行PUSCH利用率`) AS `上行PUSCH利用率_忙时`
|
||||
FROM 4G
|
||||
GROUP BY `日期`, CGI
|
||||
);
|
||||
|
||||
ALTER TABLE `ULPRB_MAX_IDX`
|
||||
ADD COLUMN `日期时间` datetime,
|
||||
ADD INDEX `DC`(`日期`, `CGI`, `上行PUSCH利用率_忙时`),
|
||||
ADD INDEX `TC`(`日期时间`, `CGI`);
|
||||
|
||||
UPDATE `ULPRB_MAX_IDX` INNER JOIN 4G
|
||||
ON
|
||||
`ULPRB_MAX_IDX`.`日期` = 4G.`日期` AND
|
||||
`ULPRB_MAX_IDX`.CGI=4G.CGI AND
|
||||
`ULPRB_MAX_IDX`.`上行PUSCH利用率_忙时`=4G.`上行PUSCH利用率`
|
||||
SET
|
||||
`ULPRB_MAX_IDX`.`日期时间`=4G.`日期时间`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `ULPRB_MAX` (
|
||||
SELECT 4G.*
|
||||
FROM `ULPRB_MAX_IDX` LEFT JOIN 4G
|
||||
ON `ULPRB_MAX_IDX`.CGI=4G.CGI AND
|
||||
`ULPRB_MAX_IDX`.`日期时间`=4G.`日期时间`
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `ULPRB_MAX_IDX`;
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `DLPRB_MAX_IDX`(
|
||||
SELECT
|
||||
`日期`,
|
||||
CGI,
|
||||
MAX( `下行PDSCH利用率`) AS `下行PDSCH利用率_忙时`
|
||||
FROM 4G
|
||||
GROUP BY `日期`, CGI
|
||||
);
|
||||
|
||||
ALTER TABLE `DLPRB_MAX_IDX`
|
||||
ADD COLUMN `日期时间` datetime,
|
||||
ADD INDEX `DC`(`日期`, `CGI`, `下行PDSCH利用率_忙时`),
|
||||
ADD INDEX `TC`(`日期时间`, `CGI`);
|
||||
|
||||
UPDATE `DLPRB_MAX_IDX` INNER JOIN 4G
|
||||
ON
|
||||
`DLPRB_MAX_IDX`.`日期` = 4G.`日期` AND
|
||||
`DLPRB_MAX_IDX`.CGI=4G.CGI AND
|
||||
`DLPRB_MAX_IDX`.`下行PDSCH利用率_忙时`=4G.`下行PDSCH利用率`
|
||||
SET
|
||||
`DLPRB_MAX_IDX`.`日期时间`=4G.`日期时间`;
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `DLPRB_MAX` (
|
||||
SELECT 4G.*
|
||||
FROM `DLPRB_MAX_IDX` LEFT JOIN 4G
|
||||
ON `DLPRB_MAX_IDX`.CGI=4G.CGI AND
|
||||
`DLPRB_MAX_IDX`.`日期时间`=4G.`日期时间`
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `DLPRB_MAX_IDX`;
|
||||
|
||||
ALTER TABLE `CCE_MAX` ADD INDEX `DC`(`日期`, `CGI`);
|
||||
ALTER TABLE `DLPRB_MAX` ADD INDEX `DC`(`日期`, `CGI`);
|
||||
ALTER TABLE `ULPRB_MAX` ADD INDEX `DC`(`日期`, `CGI`);
|
||||
|
||||
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `4G_Date` (
|
||||
SELECT `日期`, CGI FROM 4G GROUP BY `日期`, CGI
|
||||
);
|
||||
ALTER TABLE `4G_Date` ADD INDEX `DC`(`日期`, CGI);
|
||||
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `4G_MAX_IDX` (
|
||||
SELECT
|
||||
4G_Date.`日期`,
|
||||
4G_Date.CGI,
|
||||
GREATEST(`ULPRB_MAX`.`上行PUSCH利用率`, DLPRB_MAX.`下行PDSCH利用率`,CCE_MAX.`PDCCH资源利用率`) AS `最大值`
|
||||
FROM
|
||||
4G_Date
|
||||
INNER JOIN
|
||||
DLPRB_MAX
|
||||
ON
|
||||
4G_Date.`日期` = DLPRB_MAX.`日期` AND
|
||||
4G_Date.CGI = DLPRB_MAX.CGI
|
||||
INNER JOIN
|
||||
CCE_MAX
|
||||
ON
|
||||
4G_Date.`日期` = CCE_MAX.`日期` AND
|
||||
4G_Date.CGI = CCE_MAX.CGI
|
||||
INNER JOIN
|
||||
ULPRB_MAX
|
||||
ON
|
||||
4G_Date.`日期` = ULPRB_MAX.`日期` AND
|
||||
4G_Date.CGI = ULPRB_MAX.CGI
|
||||
);
|
||||
DROP TABLE IF EXISTS `4G_Date`;
|
||||
ALTER TABLE `4G_MAX_IDX` ADD INDEX `DC`(`日期`, CGI), ADD INDEX (`最大值`);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `4G_MAX` (
|
||||
SELECT * FROM 4G LIMIT 0
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE `4G_MAX` ADD INDEX (`日期`), ADD INDEX (`CGI`), ADD INDEX `DC` (`日期`,CGI), ADD INDEX `idx`(`CGI`, `基站名称`, `小区名称`);
|
||||
|
||||
ALTER TABLE DLPRB_MAX ADD COLUMN `insert` INT NOT NULL DEFAULT 0;
|
||||
ALTER TABLE CCE_MAX ADD COLUMN `insert` INT NOT NULL DEFAULT 0;
|
||||
|
||||
|
||||
|
||||
|
||||
TRUNCATE `4G_MAX`;
|
||||
INSERT INTO `4G_MAX`
|
||||
SELECT ULPRB_MAX.* FROM ULPRB_MAX INNER JOIN `4G_MAX_IDX`
|
||||
ON
|
||||
ULPRB_MAX.`日期` = 4G_MAX_IDX.`日期` AND
|
||||
ULPRB_MAX.CGI = 4G_MAX_IDX.`CGI` AND
|
||||
ULPRB_MAX.`上行PUSCH利用率` = 4G_MAX_IDX.`最大值`;
|
||||
|
||||
UPDATE DLPRB_MAX INNER JOIN 4G_MAX ON DLPRB_MAX.`日期` = 4G_MAX.`日期` AND DLPRB_MAX.CGI = 4G_MAX.CGI SET DLPRB_MAX.`insert` = 1;
|
||||
ALTER TABLE DLPRB_MAX ADD INDEX (`insert`);
|
||||
DELETE FROM DLPRB_MAX WHERE `insert` = 1;
|
||||
ALTER TABLE DLPRB_MAX DROP COLUMN `insert`;
|
||||
INSERT INTO `4G_MAX`
|
||||
SELECT DLPRB_MAX.* FROM DLPRB_MAX INNER JOIN `4G_MAX_IDX`
|
||||
ON
|
||||
DLPRB_MAX.`日期` = 4G_MAX_IDX.`日期` AND
|
||||
DLPRB_MAX.CGI = 4G_MAX_IDX.`CGI` AND
|
||||
DLPRB_MAX.`下行PDSCH利用率` = 4G_MAX_IDX.`最大值`;
|
||||
|
||||
UPDATE CCE_MAX INNER JOIN 4G_MAX ON CCE_MAX.`日期` = 4G_MAX.`日期` AND CCE_MAX.CGI = 4G_MAX.CGI SET CCE_MAX.`insert` = 1;
|
||||
ALTER TABLE CCE_MAX ADD INDEX (`insert`);
|
||||
DELETE FROM CCE_MAX WHERE `insert` = 1;
|
||||
ALTER TABLE CCE_MAX DROP COLUMN `insert`;
|
||||
INSERT INTO `4G_MAX`
|
||||
SELECT CCE_MAX.* FROM CCE_MAX INNER JOIN `4G_MAX_IDX`
|
||||
ON
|
||||
CCE_MAX.`日期` = 4G_MAX_IDX.`日期` AND
|
||||
CCE_MAX.CGI = 4G_MAX_IDX.`CGI` AND
|
||||
CCE_MAX.`PDCCH资源利用率` = 4G_MAX_IDX.`最大值`;
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS `CCE_MAX`;
|
||||
DROP TABLE IF EXISTS `ULPRB_MAX`;
|
||||
DROP TABLE IF EXISTS `DLPRB_MAX`;
|
||||
DROP TABLE IF EXISTS `4G_MAX_IDX`;
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `日流量`(SELECT `日期`,CGI, SUM(`上下行总流量_GB`) AS `日流量` FROM 4G GROUP BY `日期`,CGI);
|
||||
ALTER TABLE `日流量` ADD INDEX (`CGI`);
|
||||
DROP TABLE IF EXISTS `4G日均流量`;
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `4G日均流量` (
|
||||
SELECT CGI, AVG(`日流量`) AS `日均流量`, COUNT(`日期`) AS `流量有效天数` FROM `日流量` WHERE `日流量` > 0 GROUP BY CGI
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `4G_结果表` (
|
||||
SELECT CGI, `基站名称`, `小区名称`,
|
||||
ROUND(AVG(`上下行总流量_GB`),6) AS `自忙时流量(GB)`,
|
||||
ROUND(AVG(`ERAB流量`),6) AS `ERAB流量`,
|
||||
ROUND(AVG(`上行流量_GB`),6) AS `上行流量(GB)`,
|
||||
ROUND(AVG(`下行流量_GB`),6) AS `下行流量(GB)`,
|
||||
ROUND(AVG(`用户面平均激活UE数`),6) AS `用户面平均激活UE数`,
|
||||
ROUND(AVG(`RRC连接建立最大用户数`),6) AS `YY-RRC连接建立最大用户数`,
|
||||
ROUND(AVG(`上行PUSCH利用率`) / 100,6) AS `上行PUSCH利用率`,
|
||||
ROUND(AVG(`下行PDSCH利用率`) / 100,6) AS `下行PDSCH利用率`,
|
||||
ROUND(AVG(`PDCCH资源利用率`) / 100,6) AS `PDCCH资源利用率`,
|
||||
ROUND(AVG(`用户面最大激活UE数`),6) AS `用户面最大激活UE数`
|
||||
FROM 4G_MAX GROUP BY CGI, `基站名称`, `小区名称`
|
||||
);
|
||||
DROP TABLE IF EXISTS `4G_MAX`;
|
||||
ALTER TABLE `4G_结果表` ADD COLUMN `日均流量(GB)` DOUBLE AFTER `小区名称`, ADD INDEX (`CGI`);
|
||||
ALTER TABLE `4G日均流量` ADD INDEX (CGI);
|
||||
UPDATE `4G_结果表` INNER JOIN `4G日均流量`
|
||||
ON `4G_结果表`.CGI=`4G日均流量`.CGI
|
||||
SET `4G_结果表`.`日均流量(GB)` = ROUND(`4G日均流量`.`日均流量`,6);
|
||||
|
||||
DROP TABLE IF EXISTS `日流量`;
|
||||
DROP TABLE IF EXISTS `4G日均流量`;
|
||||
DROP TABLE IF EXISTS `4G`;
|
||||
|
||||
|
||||
# 5G脚本
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `ULPRB_MAX_IDX`(
|
||||
SELECT
|
||||
`日期`,
|
||||
NCGI,
|
||||
MAX(`上行PRB平均利用率`) AS `上行PRB平均利用率_忙时`
|
||||
FROM 5G
|
||||
GROUP BY `日期`, NCGI
|
||||
);
|
||||
|
||||
ALTER TABLE `ULPRB_MAX_IDX`
|
||||
ADD COLUMN `日期时间` datetime,
|
||||
ADD INDEX `DC`(`日期`, `NCGI`, `上行PRB平均利用率_忙时`),
|
||||
ADD INDEX `TC`(`日期时间`, `NCGI`);
|
||||
|
||||
UPDATE `ULPRB_MAX_IDX` INNER JOIN 5G
|
||||
ON
|
||||
`ULPRB_MAX_IDX`.`日期` = 5G.`日期` AND
|
||||
`ULPRB_MAX_IDX`.NCGI=5G.NCGI AND
|
||||
`ULPRB_MAX_IDX`.`上行PRB平均利用率_忙时`=5G.`上行PRB平均利用率`
|
||||
SET
|
||||
`ULPRB_MAX_IDX`.`日期时间`=5G.`日期时间`;
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `ULPRB_MAX` (
|
||||
SELECT 5G.*
|
||||
FROM `ULPRB_MAX_IDX` LEFT JOIN 5G
|
||||
ON `ULPRB_MAX_IDX`.NCGI=5G.NCGI AND
|
||||
`ULPRB_MAX_IDX`.`日期时间`=5G.`日期时间`
|
||||
);
|
||||
|
||||
# 下行PRB MAX表
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `DLPRB_MAX_IDX`(
|
||||
SELECT
|
||||
`日期`,
|
||||
NCGI,
|
||||
MAX( `下行PRB平均利用率`) AS `下行PRB平均利用率_忙时`
|
||||
FROM 5G
|
||||
GROUP BY `日期`, NCGI
|
||||
);
|
||||
|
||||
ALTER TABLE `DLPRB_MAX_IDX`
|
||||
ADD COLUMN `日期时间` datetime,
|
||||
ADD INDEX `DC`(`日期`, `NCGI`, `下行PRB平均利用率_忙时`),
|
||||
ADD INDEX `TC`(`日期时间`, `NCGI`);
|
||||
|
||||
UPDATE `DLPRB_MAX_IDX` INNER JOIN 5G
|
||||
ON
|
||||
`DLPRB_MAX_IDX`.`日期` = 5G.`日期` AND
|
||||
`DLPRB_MAX_IDX`.NCGI=5G.NCGI AND
|
||||
`DLPRB_MAX_IDX`.`下行PRB平均利用率_忙时`=5G.`下行PRB平均利用率`
|
||||
SET
|
||||
`DLPRB_MAX_IDX`.`日期时间`=5G.`日期时间`;
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `DLPRB_MAX` (
|
||||
SELECT 5G.*
|
||||
FROM `DLPRB_MAX_IDX` LEFT JOIN 5G
|
||||
ON `DLPRB_MAX_IDX`.NCGI=5G.NCGI AND
|
||||
`DLPRB_MAX_IDX`.`日期时间`=5G.`日期时间`
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `DLPRB_MAX_IDX`;
|
||||
ALTER TABLE `DLPRB_MAX` ADD INDEX `DC`(`日期`, `NCGI`);
|
||||
ALTER TABLE `ULPRB_MAX` ADD INDEX `DC`(`日期`, `NCGI`);
|
||||
|
||||
# 5G 统计MAX数据
|
||||
|
||||
DROP TABLE IF EXISTS `5G_Date`;
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `5G_Date` (
|
||||
SELECT `日期`, NCGI FROM 5G GROUP BY `日期`, NCGI
|
||||
);
|
||||
ALTER TABLE `5G_Date` ADD INDEX `DC`(`日期`, NCGI);
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `5G_MAX_IDX` (
|
||||
SELECT
|
||||
5G_Date.`日期`,
|
||||
5G_Date.NCGI,
|
||||
GREATEST(ULPRB_MAX.`上行PRB平均利用率`, DLPRB_MAX.`下行PRB平均利用率`) AS `最大值`
|
||||
FROM
|
||||
5G_Date
|
||||
INNER JOIN
|
||||
DLPRB_MAX
|
||||
ON
|
||||
5G_Date.`日期` = DLPRB_MAX.`日期` AND
|
||||
5G_Date.NCGI = DLPRB_MAX.NCGI
|
||||
INNER JOIN
|
||||
ULPRB_MAX
|
||||
ON
|
||||
5G_Date.`日期` = ULPRB_MAX.`日期` AND
|
||||
5G_Date.NCGI = ULPRB_MAX.NCGI
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `5G_Date`;
|
||||
ALTER TABLE `5G_MAX_IDX` ADD INDEX `DC`(`日期`, NCGI), ADD INDEX (`最大值`);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `5G_MAX` (
|
||||
SELECT * FROM 5G LIMIT 0
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE `5G_MAX` ADD INDEX (`日期`), ADD INDEX (`NCGI`), ADD INDEX `DC` (`日期`,NCGI), ADD INDEX `idx`(`NCGI`, `CU小区配置名称`);
|
||||
|
||||
ALTER TABLE DLPRB_MAX ADD COLUMN `insert` INT NOT NULL DEFAULT 0;
|
||||
TRUNCATE `5G_MAX`;
|
||||
INSERT INTO `5G_MAX`
|
||||
SELECT ULPRB_MAX.* FROM ULPRB_MAX INNER JOIN `5G_MAX_IDX`
|
||||
ON
|
||||
ULPRB_MAX.`日期` = 5G_MAX_IDX.`日期` AND
|
||||
ULPRB_MAX.NCGI = 5G_MAX_IDX.`NCGI` AND
|
||||
ULPRB_MAX.`上行PRB平均利用率` = 5G_MAX_IDX.`最大值`;
|
||||
|
||||
UPDATE DLPRB_MAX INNER JOIN 5G_MAX ON DLPRB_MAX.`日期` = 5G_MAX.`日期` AND DLPRB_MAX.NCGI = 5G_MAX.NCGI SET DLPRB_MAX.`insert` = 1;
|
||||
ALTER TABLE DLPRB_MAX ADD INDEX (`insert`);
|
||||
DELETE FROM DLPRB_MAX WHERE `insert` = 1;
|
||||
ALTER TABLE DLPRB_MAX DROP COLUMN `insert`;
|
||||
INSERT INTO `5G_MAX`
|
||||
SELECT DLPRB_MAX.* FROM DLPRB_MAX INNER JOIN `5G_MAX_IDX`
|
||||
ON
|
||||
DLPRB_MAX.`日期` = 5G_MAX_IDX.`日期` AND
|
||||
DLPRB_MAX.NCGI = 5G_MAX_IDX.`NCGI` AND
|
||||
DLPRB_MAX.`下行PRB平均利用率` = 5G_MAX_IDX.`最大值`;
|
||||
|
||||
DROP TABLE IF EXISTS `ULPRB_MAX`;
|
||||
DROP TABLE IF EXISTS `DLPRB_MAX`;
|
||||
DROP TABLE IF EXISTS `5G_MAX_IDX`;
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `日流量`(SELECT `日期`,NCGI, SUM(`5G上下行总流量_GB`) AS `日流量` FROM 5G GROUP BY `日期`,NCGI);
|
||||
ALTER TABLE `日流量` ADD INDEX (`NCGI`);
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS `5G日均流量` (
|
||||
SELECT NCGI, AVG(`日流量`) AS `日均流量`, COUNT(`日期`) AS `流量有效天数` FROM `日流量` WHERE `日流量` > 0 GROUP BY NCGI
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `5G_结果表` (
|
||||
SELECT NCGI, `CU小区配置名称`,
|
||||
ROUND(AVG(`5G上下行总流量_GB`),6) AS `5G上下行总流量(上行PDCP PDU数据量+下行PDCP成功发送数据量)(GB)`,
|
||||
ROUND(AVG(`5G上行流量_GB`),6) AS `5G上行流量(上行PDCP PDU数据量)(GB)`,
|
||||
ROUND(AVG(`5G下行流量_GB`),6) AS `5G下行流量(下行PDCP成功发送数据量)(GB)`,
|
||||
ROUND(AVG(`小区平均激活UE数`),6) AS `小区平均激活UE数`,
|
||||
ROUND(AVG(`RRC连接最大连接用户数`),6) AS `RRC连接最大连接用户数`,
|
||||
ROUND(AVG(`RRC连接平均连接用户数`),6) AS `RRC连接平均连接用户数`,
|
||||
ROUND(AVG(`小区最大激活UE数`),6) AS `小区最大激活UE数`,
|
||||
ROUND(AVG(`上行PRB平均利用率`) / 100,6) AS `上行PRB平均利用率`,
|
||||
ROUND(AVG(`下行PRB平均利用率`) / 100,6) AS `下行PRB平均利用率`,
|
||||
ROUND(AVG(`PDCCH信道动态CCE占用率`) / 100,6) AS `PDCCH信道CCE占用率(动态)(%)`,
|
||||
ROUND(AVG(`小区下行RLC_SDU字节数_MByte`),6) AS `小区下行RLC SDU字节数(MByte)`,
|
||||
ROUND(AVG(`小区上行RLC_SDU字节数_MByte`),6) AS `小区上行RLC SDU字节数(MByte)`,
|
||||
ROUND(AVG(`平均单Flow流量_MB`),6) AS `单Flow流量(MB)`
|
||||
FROM 5G_MAX GROUP BY NCGI, `CU小区配置名称`
|
||||
);
|
||||
|
||||
ALTER TABLE `5G_结果表` ADD COLUMN `日均流量(GB)` DOUBLE AFTER `CU小区配置名称`, ADD INDEX (`NCGI`);
|
||||
ALTER TABLE `5G日均流量` ADD INDEX (NCGI);
|
||||
UPDATE `5G_结果表` INNER JOIN `5G日均流量`
|
||||
ON `5G_结果表`.NCGI=`5G日均流量`.NCGI
|
||||
SET `5G_结果表`.`日均流量(GB)` = ROUND(`5G日均流量`.`日均流量`,6);
|
||||
|
||||
DROP TABLE IF EXISTS `日流量`;
|
||||
DROP TABLE IF EXISTS `5G日均流量`;
|
||||
DROP TABLE IF EXISTS `4G`;
|
||||
DROP TABLE IF EXISTS `5G`;
|
||||
Vendored
+220
@@ -0,0 +1,220 @@
|
||||
@echo off
|
||||
chcp 65001 >nul
|
||||
REM CapacityReport 镜像构建和导出脚本 (Windows)
|
||||
REM 在有外网的 Windows 机器上运行此脚本,生成离线部署包
|
||||
@REM set http_proxy=http://127.0.0.1:7897
|
||||
@REM set https_proxy=http://127.0.0.1:7897
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
set SCRIPT_DIR=%~dp0
|
||||
set "PROJECT_ROOT=%~dp0..\"
|
||||
set DIST_DIR=%~dp0
|
||||
REM 规范化路径(去掉末尾的反斜杠,如果有的话)
|
||||
if "%PROJECT_ROOT:~-1%"=="\" set "PROJECT_ROOT=%PROJECT_ROOT:~0,-1%"
|
||||
|
||||
echo ==========================================
|
||||
echo CapacityReport 离线部署包构建脚本
|
||||
echo ==========================================
|
||||
echo.
|
||||
|
||||
REM 清理旧的构建文件
|
||||
echo 清理旧的构建文件...
|
||||
if exist "%DIST_DIR%images\capacity-images.tar" (
|
||||
del /f /q "%DIST_DIR%images\capacity-images.tar"
|
||||
echo - 已删除旧镜像文件
|
||||
)
|
||||
if exist "%DIST_DIR%Configure.json" (
|
||||
del /f /q "%DIST_DIR%Configure.json"
|
||||
echo - 已删除旧 Configure.json
|
||||
)
|
||||
if exist "%DIST_DIR%ReportScript.sql" (
|
||||
del /f /q "%DIST_DIR%ReportScript.sql"
|
||||
echo - 已删除旧 ReportScript.sql
|
||||
)
|
||||
if exist "%DIST_DIR%mysql\conf.d\custom.cnf" (
|
||||
del /f /q "%DIST_DIR%mysql\conf.d\custom.cnf"
|
||||
echo - 已删除旧 mysql\conf.d\custom.cnf
|
||||
)
|
||||
if exist "%DIST_DIR%mysql\init\01-init-db.sql" (
|
||||
del /f /q "%DIST_DIR%mysql\init\01-init-db.sql"
|
||||
echo - 已删除旧 mysql\init\01-init-db.sql
|
||||
)
|
||||
echo 清理完成
|
||||
echo.
|
||||
|
||||
REM 检查 Docker 是否安装
|
||||
where docker >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo 错误: 未检测到 Docker,请先安装 Docker Desktop
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM 检查 Docker Compose 是否安装
|
||||
docker compose version >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
docker-compose version >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo 错误: 未检测到 Docker Compose,请先安装 Docker Compose
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
echo 步骤 1: 拉取基础镜像...
|
||||
REM 检查 Dockerfile 中的 Python 版本
|
||||
set PYTHON_TAG=
|
||||
for /f "tokens=2 delims=:" %%a in ('findstr /R "^FROM python:" "!PROJECT_ROOT!\Dockerfile"') do (
|
||||
set "PYTHON_TAG=%%a"
|
||||
goto :found_python
|
||||
)
|
||||
:found_python
|
||||
if defined PYTHON_TAG (
|
||||
REM 去掉可能的空格
|
||||
for /f "tokens=1 delims= " %%b in ("!PYTHON_TAG!") do (
|
||||
set "PYTHON_TAG=%%b"
|
||||
)
|
||||
echo 从 Dockerfile 检测到 Python 镜像标签: !PYTHON_TAG!
|
||||
) else (
|
||||
echo 错误: 无法从 Dockerfile 中找到 Python 镜像标签
|
||||
echo 请确保 Dockerfile 中包含 "FROM python:xxx" 行
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM 检查 Python 镜像是否已存在
|
||||
docker images --format "{{.Repository}}:{{.Tag}}" | findstr /C:"python:!PYTHON_TAG!" >nul
|
||||
if %errorlevel% equ 0 (
|
||||
echo Python 镜像 python:!PYTHON_TAG! 已存在,跳过拉取
|
||||
) else (
|
||||
echo 正在拉取 python:!PYTHON_TAG!...
|
||||
docker pull python:!PYTHON_TAG!
|
||||
if %errorlevel% neq 0 (
|
||||
echo 错误: 拉取 Python 镜像失败
|
||||
echo 提示: 如果遇到网络问题,请检查网络连接或稍后重试
|
||||
echo 镜像标签: python:!PYTHON_TAG!
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
REM 检查 MySQL 镜像是否已存在
|
||||
docker images --format "{{.Repository}}:{{.Tag}}" | findstr /C:"mysql:8.0.44" >nul
|
||||
if %errorlevel% equ 0 (
|
||||
echo MySQL 镜像 mysql:8.0.44 已存在,跳过拉取
|
||||
) else (
|
||||
echo 正在拉取 mysql:8.0.44...
|
||||
docker pull mysql:8.0.44
|
||||
if %errorlevel% neq 0 (
|
||||
echo 错误: 拉取 MySQL 镜像失败
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
echo.
|
||||
echo 步骤 2: 构建应用镜像...
|
||||
cd /d "!PROJECT_ROOT!"
|
||||
docker build -t capacity-report-app:latest -f Dockerfile .
|
||||
if %errorlevel% neq 0 (
|
||||
echo 错误: 构建应用镜像失败
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo 步骤 3: 标记 MySQL 镜像...
|
||||
docker tag mysql:8.0.44 capacity-mysql:8.0.44
|
||||
if %errorlevel% neq 0 (
|
||||
echo 错误: 标记 MySQL 镜像失败
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo 步骤 4: 导出镜像到 dist 目录...
|
||||
if not exist "%DIST_DIR%images" mkdir "%DIST_DIR%images"
|
||||
echo 正在导出镜像到单个 tar 文件:
|
||||
echo - capacity-report-app:latest (应用镜像)
|
||||
echo - capacity-mysql:8.0.44 (MySQL 镜像)
|
||||
docker save capacity-report-app:latest capacity-mysql:8.0.44 -o "%DIST_DIR%images\capacity-images.tar"
|
||||
if %errorlevel% neq 0 (
|
||||
echo 错误: 导出镜像失败
|
||||
exit /b 1
|
||||
)
|
||||
echo 镜像导出完成: %DIST_DIR%images\capacity-images.tar
|
||||
echo 注意: 此文件包含应用镜像和 MySQL 镜像,部署时会自动加载所有镜像
|
||||
|
||||
echo.
|
||||
echo 步骤 5: 复制必要文件到 dist 目录...
|
||||
REM 创建必要的目录结构
|
||||
if not exist "%DIST_DIR%mysql\conf.d" mkdir "%DIST_DIR%mysql\conf.d"
|
||||
if not exist "%DIST_DIR%mysql\init" mkdir "%DIST_DIR%mysql\init"
|
||||
|
||||
REM 复制配置文件
|
||||
echo 正在复制配置文件...
|
||||
if exist "!PROJECT_ROOT!\Configure.json" (
|
||||
copy "!PROJECT_ROOT!\Configure.json" "!DIST_DIR!" >nul
|
||||
echo - Configure.json 已复制
|
||||
REM 更新为 Docker 环境配置
|
||||
echo 正在更新 Configure.json 为 Docker 环境配置...
|
||||
powershell -NoProfile -Command "$json = Get-Content \"%DIST_DIR%Configure.json\" -Raw -Encoding UTF8 | ConvertFrom-Json; $json.MySQL_DBInfo.host = 'capacity-mysql'; $json.MySQL_DBInfo.port = 3306; $json.MySQL_DBInfo.user = 'root'; $json.MySQL_DBInfo.passwd = 'gmcc123'; $json.MySQL_DBInfo.dbname = 'CapacityReport'; $json | ConvertTo-Json -Depth 10 | Set-Content \"%DIST_DIR%Configure.json\" -Encoding UTF8"
|
||||
if %errorlevel% equ 0 (
|
||||
echo - 已更新数据库配置: host=capacity-mysql, port=3306, user=root, passwd=gmcc123
|
||||
) else (
|
||||
echo 警告: 无法自动更新 Configure.json,请手动修改数据库配置
|
||||
)
|
||||
) else (
|
||||
echo 警告: Configure.json 不存在: !PROJECT_ROOT!\Configure.json
|
||||
)
|
||||
|
||||
if exist "!PROJECT_ROOT!\ReportScript.sql" (
|
||||
copy "!PROJECT_ROOT!\ReportScript.sql" "!DIST_DIR!" >nul
|
||||
echo - ReportScript.sql 已复制
|
||||
) else (
|
||||
echo 警告: ReportScript.sql 不存在: !PROJECT_ROOT!\ReportScript.sql
|
||||
)
|
||||
|
||||
if exist "!PROJECT_ROOT!\mysql\conf.d\custom.cnf" (
|
||||
copy "!PROJECT_ROOT!\mysql\conf.d\custom.cnf" "!DIST_DIR!mysql\conf.d\" >nul
|
||||
echo - mysql\conf.d\custom.cnf 已复制
|
||||
) else (
|
||||
echo 警告: mysql\conf.d\custom.cnf 不存在: !PROJECT_ROOT!\mysql\conf.d\custom.cnf
|
||||
)
|
||||
|
||||
if exist "!PROJECT_ROOT!\mysql\init\01-init-db.sql" (
|
||||
copy "!PROJECT_ROOT!\mysql\init\01-init-db.sql" "!DIST_DIR!mysql\init\" >nul
|
||||
echo - mysql\init\01-init-db.sql 已复制
|
||||
) else (
|
||||
echo 警告: mysql\init\01-init-db.sql 不存在: !PROJECT_ROOT!\mysql\init\01-init-db.sql
|
||||
)
|
||||
|
||||
echo.
|
||||
echo 步骤 6: 计算文件大小...
|
||||
for %%A in ("%DIST_DIR%images\capacity-images.tar") do (
|
||||
set SIZE=%%~zA
|
||||
set /a SIZE_MB=!SIZE!/1024/1024
|
||||
echo 镜像文件大小: !SIZE_MB! MB
|
||||
)
|
||||
|
||||
echo.
|
||||
echo 步骤 7: 清理临时目录...
|
||||
if exist "%DIST_DIR%cache" (
|
||||
rd /s /q "%DIST_DIR%cache" 2>nul
|
||||
echo - 已删除 cache 目录
|
||||
)
|
||||
if exist "%DIST_DIR%logs" (
|
||||
rd /s /q "%DIST_DIR%logs" 2>nul
|
||||
echo - 已删除 logs 目录
|
||||
)
|
||||
|
||||
echo.
|
||||
echo ==========================================
|
||||
echo 构建完成!
|
||||
echo ==========================================
|
||||
echo.
|
||||
echo 离线部署包位置: %DIST_DIR%
|
||||
echo.
|
||||
echo 部署步骤:
|
||||
echo 1. 将整个 dist 目录传输到目标 Linux 机器
|
||||
echo 2. 在目标机器上执行: sh dist/deploy.sh
|
||||
echo.
|
||||
echo 端口映射:
|
||||
echo - 应用端口: 19081 (原 9081)
|
||||
echo - MySQL 端口: 13306 (原 3306)
|
||||
echo.
|
||||
|
||||
endlocal
|
||||
Vendored
+313
@@ -0,0 +1,313 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
CapacityReport 镜像构建和导出脚本 (Windows)
|
||||
在有外网的 Windows 机器上运行此脚本,生成离线部署包
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
# 脚本所在目录
|
||||
SCRIPT_DIR = Path(__file__).parent.absolute()
|
||||
PROJECT_ROOT = SCRIPT_DIR.parent
|
||||
DIST_DIR = SCRIPT_DIR
|
||||
|
||||
# 颜色输出(Windows 支持)
|
||||
import platform
|
||||
if platform.system() == 'Windows':
|
||||
try:
|
||||
import ctypes
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
|
||||
except:
|
||||
pass
|
||||
|
||||
class Colors:
|
||||
GREEN = '\033[92m'
|
||||
YELLOW = '\033[93m'
|
||||
RED = '\033[91m'
|
||||
RESET = '\033[0m'
|
||||
|
||||
def print_step(msg):
|
||||
print(f"\n{Colors.GREEN}{msg}{Colors.RESET}")
|
||||
|
||||
def print_info(msg):
|
||||
print(f" {msg}")
|
||||
|
||||
def print_warning(msg):
|
||||
print(f"{Colors.YELLOW}警告: {msg}{Colors.RESET}")
|
||||
|
||||
def print_error(msg):
|
||||
print(f"{Colors.RED}错误: {msg}{Colors.RESET}")
|
||||
|
||||
def run_cmd(cmd, check=True, capture_output=False):
|
||||
"""执行命令"""
|
||||
if isinstance(cmd, str):
|
||||
cmd = cmd.split()
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
check=check,
|
||||
capture_output=capture_output,
|
||||
text=True
|
||||
)
|
||||
return result
|
||||
except subprocess.CalledProcessError as e:
|
||||
if check:
|
||||
print_error(f"命令执行失败: {' '.join(cmd)}")
|
||||
sys.exit(1)
|
||||
return None
|
||||
except FileNotFoundError:
|
||||
print_error(f"命令未找到: {cmd[0]}")
|
||||
sys.exit(1)
|
||||
|
||||
def check_command(cmd):
|
||||
"""检查命令是否存在"""
|
||||
try:
|
||||
if cmd == "docker":
|
||||
subprocess.run([cmd, "--version"], capture_output=True, check=True)
|
||||
elif cmd == "docker-compose":
|
||||
subprocess.run([cmd, "version"], capture_output=True, check=True)
|
||||
return True
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
return False
|
||||
|
||||
def get_python_tag_from_dockerfile():
|
||||
"""从 Dockerfile 中提取 Python 镜像标签"""
|
||||
dockerfile_path = PROJECT_ROOT / "Dockerfile"
|
||||
if not dockerfile_path.exists():
|
||||
print_error(f"Dockerfile 不存在: {dockerfile_path}")
|
||||
sys.exit(1)
|
||||
|
||||
with open(dockerfile_path, 'r', encoding='utf-8') as f:
|
||||
for line in f:
|
||||
match = re.match(r'^FROM\s+python:(.+?)(?:\s|$)', line, re.IGNORECASE)
|
||||
if match:
|
||||
tag = match.group(1).strip()
|
||||
return tag
|
||||
|
||||
print_error("无法从 Dockerfile 中找到 Python 镜像标签")
|
||||
print_error("请确保 Dockerfile 中包含 'FROM python:xxx' 行")
|
||||
sys.exit(1)
|
||||
|
||||
def image_exists(image_name):
|
||||
"""检查镜像是否已存在"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["docker", "images", "--format", "{{.Repository}}:{{.Tag}}"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
return image_name in result.stdout
|
||||
except:
|
||||
return False
|
||||
|
||||
def format_size(size_bytes):
|
||||
"""格式化文件大小"""
|
||||
for unit in ['B', 'KB', 'MB', 'GB']:
|
||||
if size_bytes < 1024.0:
|
||||
return f"{size_bytes:.1f} {unit}"
|
||||
size_bytes /= 1024.0
|
||||
return f"{size_bytes:.1f} TB"
|
||||
|
||||
def main():
|
||||
print("=" * 50)
|
||||
print("CapacityReport 离线部署包构建脚本")
|
||||
print("=" * 50)
|
||||
print()
|
||||
|
||||
# 清理旧的构建文件
|
||||
print_step("清理旧的构建文件...")
|
||||
files_to_clean = [
|
||||
DIST_DIR / "images" / "capacity-images.tar",
|
||||
DIST_DIR / "Configure.json",
|
||||
DIST_DIR / "ReportScript.sql",
|
||||
DIST_DIR / "mysql" / "conf.d" / "custom.cnf",
|
||||
DIST_DIR / "mysql" / "init" / "01-init-db.sql",
|
||||
]
|
||||
|
||||
for file_path in files_to_clean:
|
||||
if file_path.exists():
|
||||
if file_path.is_file():
|
||||
file_path.unlink()
|
||||
print_info(f"已删除旧 {file_path.name}")
|
||||
elif file_path.is_dir():
|
||||
shutil.rmtree(file_path)
|
||||
print_info(f"已删除旧 {file_path.name}")
|
||||
|
||||
print_info("清理完成")
|
||||
|
||||
# 检查 Docker
|
||||
print_step("检查 Docker 环境...")
|
||||
if not check_command("docker"):
|
||||
print_error("未检测到 Docker,请先安装 Docker Desktop")
|
||||
sys.exit(1)
|
||||
print_info("Docker: OK")
|
||||
|
||||
# 检查 Docker Compose
|
||||
docker_compose_cmd = None
|
||||
try:
|
||||
subprocess.run(["docker", "compose", "version"], capture_output=True, check=True)
|
||||
docker_compose_cmd = "docker compose"
|
||||
print_info("Docker Compose: OK (docker compose)")
|
||||
except:
|
||||
if check_command("docker-compose"):
|
||||
docker_compose_cmd = "docker-compose"
|
||||
print_info("Docker Compose: OK (docker-compose)")
|
||||
else:
|
||||
print_error("未检测到 Docker Compose,请先安装 Docker Compose")
|
||||
sys.exit(1)
|
||||
|
||||
# 步骤 1: 拉取基础镜像
|
||||
print_step("步骤 1: 拉取基础镜像...")
|
||||
|
||||
# 获取 Python 版本
|
||||
python_tag = get_python_tag_from_dockerfile()
|
||||
python_image = f"python:{python_tag}"
|
||||
print_info(f"从 Dockerfile 检测到 Python 镜像标签: {python_tag}")
|
||||
|
||||
# 检查并拉取 Python 镜像
|
||||
if image_exists(python_image):
|
||||
print_info(f"Python 镜像 {python_image} 已存在,跳过拉取")
|
||||
else:
|
||||
print_info(f"正在拉取 {python_image}...")
|
||||
run_cmd(["docker", "pull", python_image])
|
||||
print_info(f"Python 镜像拉取完成")
|
||||
|
||||
# 检查并拉取 MySQL 镜像
|
||||
mysql_image = "mysql:8.0.44"
|
||||
if image_exists(mysql_image):
|
||||
print_info(f"MySQL 镜像 {mysql_image} 已存在,跳过拉取")
|
||||
else:
|
||||
print_info(f"正在拉取 {mysql_image}...")
|
||||
run_cmd(["docker", "pull", mysql_image])
|
||||
print_info(f"MySQL 镜像拉取完成")
|
||||
|
||||
# 步骤 2: 构建应用镜像
|
||||
print_step("步骤 2: 构建应用镜像...")
|
||||
os.chdir(PROJECT_ROOT)
|
||||
run_cmd(["docker", "build", "-t", "capacity-report-app:latest", "-f", "Dockerfile", "."])
|
||||
print_info("应用镜像构建完成")
|
||||
|
||||
# 步骤 3: 标记 MySQL 镜像
|
||||
print_step("步骤 3: 标记 MySQL 镜像...")
|
||||
run_cmd(["docker", "tag", mysql_image, "capacity-mysql:8.0.44"])
|
||||
print_info("MySQL 镜像标记完成")
|
||||
|
||||
# 步骤 4: 导出镜像
|
||||
print_step("步骤 4: 导出镜像到 dist 目录...")
|
||||
images_dir = DIST_DIR / "images"
|
||||
images_dir.mkdir(exist_ok=True)
|
||||
|
||||
tar_file = images_dir / "capacity-images.tar"
|
||||
print_info("正在导出镜像到单个 tar 文件:")
|
||||
print_info(" - capacity-report-app:latest (应用镜像)")
|
||||
print_info(" - capacity-mysql:8.0.44 (MySQL 镜像)")
|
||||
|
||||
run_cmd([
|
||||
"docker", "save",
|
||||
"capacity-report-app:latest",
|
||||
"capacity-mysql:8.0.44",
|
||||
"-o", str(tar_file)
|
||||
])
|
||||
|
||||
print_info(f"镜像导出完成: {tar_file}")
|
||||
print_info("注意: 此文件包含应用镜像和 MySQL 镜像,部署时会自动加载所有镜像")
|
||||
|
||||
# 步骤 5: 复制必要文件
|
||||
print_step("步骤 5: 复制必要文件到 dist 目录...")
|
||||
|
||||
# 创建必要的目录结构
|
||||
(DIST_DIR / "mysql" / "conf.d").mkdir(parents=True, exist_ok=True)
|
||||
(DIST_DIR / "mysql" / "init").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# 复制配置文件
|
||||
print_info("正在复制配置文件...")
|
||||
|
||||
files_to_copy = [
|
||||
(PROJECT_ROOT / "Configure.json", DIST_DIR / "Configure.json"),
|
||||
(PROJECT_ROOT / "ReportScript.sql", DIST_DIR / "ReportScript.sql"),
|
||||
(PROJECT_ROOT / "mysql" / "conf.d" / "custom.cnf", DIST_DIR / "mysql" / "conf.d" / "custom.cnf"),
|
||||
(PROJECT_ROOT / "mysql" / "init" / "01-init-db.sql", DIST_DIR / "mysql" / "init" / "01-init-db.sql"),
|
||||
]
|
||||
|
||||
for src, dst in files_to_copy:
|
||||
if src.exists():
|
||||
shutil.copy2(src, dst)
|
||||
print_info(f"{src.name} 已复制")
|
||||
else:
|
||||
print_warning(f"{src.name} 不存在: {src}")
|
||||
|
||||
# 更新 Configure.json 为 Docker 环境配置
|
||||
config_file = DIST_DIR / "Configure.json"
|
||||
if config_file.exists():
|
||||
print_info("正在更新 Configure.json 为 Docker 环境配置...")
|
||||
try:
|
||||
with open(config_file, 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
|
||||
config['MySQL_DBInfo'] = {
|
||||
'host': 'capacity-mysql',
|
||||
'port': 3306,
|
||||
'user': 'root',
|
||||
'passwd': 'gmcc123',
|
||||
'dbname': 'CapacityReport'
|
||||
}
|
||||
|
||||
with open(config_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(config, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print_info("已更新数据库配置: host=capacity-mysql, port=3306, user=root, passwd=gmcc123")
|
||||
except Exception as e:
|
||||
print_warning(f"无法自动更新 Configure.json: {e}")
|
||||
print_warning("请手动修改数据库配置")
|
||||
|
||||
# 步骤 6: 计算文件大小
|
||||
print_step("步骤 6: 计算文件大小...")
|
||||
if tar_file.exists():
|
||||
size = tar_file.stat().st_size
|
||||
print_info(f"镜像文件大小: {format_size(size)}")
|
||||
|
||||
# 步骤 7: 清理临时目录
|
||||
print_step("步骤 7: 清理临时目录...")
|
||||
temp_dirs = [DIST_DIR / "cache", DIST_DIR / "logs"]
|
||||
for temp_dir in temp_dirs:
|
||||
if temp_dir.exists():
|
||||
shutil.rmtree(temp_dir, ignore_errors=True)
|
||||
print_info(f"已删除 {temp_dir.name} 目录")
|
||||
|
||||
# 完成
|
||||
print()
|
||||
print("=" * 50)
|
||||
print("构建完成!")
|
||||
print("=" * 50)
|
||||
print()
|
||||
print(f"离线部署包位置: {DIST_DIR}")
|
||||
print()
|
||||
print("部署步骤:")
|
||||
print("1. 将整个 dist 目录传输到目标 Linux 机器")
|
||||
print("2. 在目标机器上执行: sh dist/deploy.sh")
|
||||
print()
|
||||
print("端口映射:")
|
||||
print(" - 应用端口: 19081 (原 9081)")
|
||||
print(" - MySQL 端口: 13306 (原 3306)")
|
||||
print()
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n构建已取消")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print_error(f"构建失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
Vendored
+240
@@ -0,0 +1,240 @@
|
||||
#!/bin/bash
|
||||
# CapacityReport Deployment Script
|
||||
# Run this script on offline machine to import images and start services
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo "=========================================="
|
||||
echo "CapacityReport Deployment"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Set permissions for dist directory and make scripts executable
|
||||
echo "Setting permissions..."
|
||||
chmod -R 0777 "$SCRIPT_DIR" 2>/dev/null || true
|
||||
find "$SCRIPT_DIR" -type f \( -name "*.sh" -o -name "*.py" \) -exec chmod +x {} \; 2>/dev/null || true
|
||||
echo " Permissions set"
|
||||
|
||||
echo ""
|
||||
|
||||
# Check Docker
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo "Error: Docker not found, please install Docker"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check Docker Compose
|
||||
DOCKER_COMPOSE_CMD=""
|
||||
if docker compose version &> /dev/null; then
|
||||
DOCKER_COMPOSE_CMD="docker compose"
|
||||
elif command -v docker-compose &> /dev/null; then
|
||||
DOCKER_COMPOSE_CMD="docker-compose"
|
||||
else
|
||||
echo "Error: Docker Compose not found, please install Docker Compose"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check image file
|
||||
if [ ! -f "images/capacity-images.tar" ]; then
|
||||
echo "Error: Image file not found: images/capacity-images.tar"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Step 1: Checking ports..."
|
||||
# 检查端口是否被占用
|
||||
check_port() {
|
||||
local port=$1
|
||||
local name=$2
|
||||
local in_use=false
|
||||
|
||||
# 尝试多种方法检查端口
|
||||
if command -v lsof &> /dev/null; then
|
||||
if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; then
|
||||
in_use=true
|
||||
fi
|
||||
elif command -v netstat &> /dev/null; then
|
||||
if netstat -tuln 2>/dev/null | grep -q ":$port "; then
|
||||
in_use=true
|
||||
fi
|
||||
elif command -v ss &> /dev/null; then
|
||||
if ss -tuln 2>/dev/null | grep -q ":$port "; then
|
||||
in_use=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$in_use" = true ]; then
|
||||
echo "Warning: Port $port ($name) is in use"
|
||||
read -p "Continue? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
check_port 19081 "App"
|
||||
check_port 13306 "MySQL"
|
||||
|
||||
echo ""
|
||||
echo "Step 2: Loading images..."
|
||||
docker load -i images/capacity-images.tar >/dev/null 2>&1
|
||||
|
||||
echo ""
|
||||
echo "Step 3: Verifying images..."
|
||||
if docker images | grep -q "capacity-report-app.*latest"; then
|
||||
echo " App image: OK"
|
||||
else
|
||||
echo " App image: FAILED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if docker images | grep -q "capacity-mysql.*8.0.44"; then
|
||||
echo " MySQL image: OK"
|
||||
else
|
||||
echo " MySQL image: FAILED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Step 4: Creating directories..."
|
||||
mkdir -p cache logs
|
||||
chmod 777 cache logs 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo "Step 5: Checking config..."
|
||||
if [ ! -f "Configure.json" ]; then
|
||||
echo " Creating default Configure.json..."
|
||||
cat > Configure.json << 'EOF'
|
||||
{
|
||||
"MySQL_DBInfo": {
|
||||
"host": "capacity-mysql",
|
||||
"port": 3306,
|
||||
"user": "root",
|
||||
"passwd": "gmcc123",
|
||||
"dbname": "CapacityReport"
|
||||
},
|
||||
"ExtractField": []
|
||||
}
|
||||
EOF
|
||||
else
|
||||
# Update config for Docker environment
|
||||
if command -v python3 &> /dev/null || command -v python &> /dev/null; then
|
||||
(command -v python3 >/dev/null && python3 || python) << 'PYEOF'
|
||||
import json
|
||||
import sys
|
||||
|
||||
try:
|
||||
with open('Configure.json', 'r', encoding='utf-8') as f:
|
||||
config = json.load(f)
|
||||
|
||||
db_info = config.get('MySQL_DBInfo', {})
|
||||
needs_update = False
|
||||
|
||||
if db_info.get('host') != 'capacity-mysql':
|
||||
db_info['host'] = 'capacity-mysql'
|
||||
needs_update = True
|
||||
|
||||
if db_info.get('port') != 3306:
|
||||
db_info['port'] = 3306
|
||||
needs_update = True
|
||||
|
||||
if db_info.get('user') != 'root':
|
||||
db_info['user'] = 'root'
|
||||
needs_update = True
|
||||
|
||||
if db_info.get('passwd') != 'gmcc123':
|
||||
db_info['passwd'] = 'gmcc123'
|
||||
needs_update = True
|
||||
|
||||
if db_info.get('dbname') != 'CapacityReport':
|
||||
db_info['dbname'] = 'CapacityReport'
|
||||
needs_update = True
|
||||
|
||||
if needs_update:
|
||||
with open('Configure.json', 'w', encoding='utf-8') as f:
|
||||
json.dump(config, f, ensure_ascii=False, indent=2)
|
||||
print(" Updated Configure.json")
|
||||
except:
|
||||
pass
|
||||
PYEOF
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "ReportScript.sql" ]; then
|
||||
touch ReportScript.sql
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Step 6: Starting services..."
|
||||
$DOCKER_COMPOSE_CMD down 2>/dev/null || true
|
||||
$DOCKER_COMPOSE_CMD up -d >/dev/null 2>&1
|
||||
|
||||
echo ""
|
||||
echo "Step 7: Waiting for services..."
|
||||
for i in {1..30}; do
|
||||
if docker exec capacity-mysql mysqladmin ping -h localhost -u root -pgmcc123 --silent 2>/dev/null; then
|
||||
echo " MySQL: Ready"
|
||||
break
|
||||
fi
|
||||
if [ $i -eq 30 ]; then
|
||||
echo " MySQL: Timeout"
|
||||
exit 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if command -v curl &> /dev/null; then
|
||||
for i in {1..30}; do
|
||||
if curl -f http://localhost:19081/health >/dev/null 2>&1; then
|
||||
echo " App: Ready"
|
||||
break
|
||||
fi
|
||||
if [ $i -eq 30 ]; then
|
||||
echo " App: Timeout"
|
||||
echo " Check logs: $DOCKER_COMPOSE_CMD logs capacity-app"
|
||||
exit 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
else
|
||||
for i in {1..30}; do
|
||||
if docker ps --filter "name=capacity-report-app" --filter "status=running" --format "{{.Names}}" | grep -q "capacity-report-app"; then
|
||||
if docker inspect capacity-report-app --format='{{.State.Health.Status}}' 2>/dev/null | grep -q "healthy"; then
|
||||
echo " App: Ready"
|
||||
break
|
||||
elif [ $i -gt 10 ]; then
|
||||
echo " App: Running"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
if [ $i -eq 30 ]; then
|
||||
echo " App: Timeout"
|
||||
exit 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Deployment completed!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "Access: http://localhost:19081"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " Logs: $DOCKER_COMPOSE_CMD logs -f"
|
||||
echo " Stop: $DOCKER_COMPOSE_CMD down"
|
||||
echo " Restart: $DOCKER_COMPOSE_CMD restart"
|
||||
echo " Status: $DOCKER_COMPOSE_CMD ps"
|
||||
echo ""
|
||||
echo "Database:"
|
||||
echo " Host: localhost"
|
||||
echo " Port: 13306"
|
||||
echo " User: root"
|
||||
echo " Password: gmcc123"
|
||||
echo " Database: CapacityReport"
|
||||
echo ""
|
||||
Vendored
+79
@@ -0,0 +1,79 @@
|
||||
# CapacityReport Docker 编排文件
|
||||
# 用于内网离线部署
|
||||
#
|
||||
# 使用方法:
|
||||
# sh deploy.sh # 一键导入镜像并启动服务
|
||||
# docker-compose up -d # 启动所有服务
|
||||
# docker-compose down # 停止所有服务
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# 容量报表应用
|
||||
capacity-app:
|
||||
image: capacity-report-app:latest
|
||||
container_name: capacity-report-app
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "19081:9081"
|
||||
volumes:
|
||||
# 持久化数据
|
||||
- ./cache:/app/cache
|
||||
- ./Configure.json:/app/Configure.json
|
||||
- ./ReportScript.sql:/app/ReportScript.sql
|
||||
# 日志目录
|
||||
- ./logs:/var/log/supervisor
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
- PYTHONUNBUFFERED=1
|
||||
- SUPERVISOR_ENABLED=1
|
||||
depends_on:
|
||||
capacity-mysql:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- capacity-network
|
||||
|
||||
# MySQL 数据库
|
||||
capacity-mysql:
|
||||
image: capacity-mysql:8.0.44
|
||||
container_name: capacity-mysql
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "13306:3306"
|
||||
volumes:
|
||||
# 数据持久化
|
||||
- capacity-mysql-data:/var/lib/mysql
|
||||
# 自定义配置(启用 LOAD DATA INFILE)
|
||||
- ./mysql/conf.d:/etc/mysql/conf.d:ro
|
||||
# 初始化脚本(仅在首次启动时执行)
|
||||
- ./mysql/init:/docker-entrypoint-initdb.d:ro
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
- MYSQL_ROOT_PASSWORD=gmcc123
|
||||
- MYSQL_DATABASE=CapacityReport
|
||||
command:
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
- --local-infile=ON
|
||||
- --secure-file-priv=
|
||||
- --max_allowed_packet=256M
|
||||
- --innodb_buffer_pool_size=512M
|
||||
- --innodb_log_file_size=128M
|
||||
- --innodb_flush_log_at_trx_commit=2
|
||||
- --sync_binlog=0
|
||||
networks:
|
||||
- capacity-network
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-pgmcc123"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
networks:
|
||||
capacity-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
capacity-mysql-data:
|
||||
driver: local
|
||||
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
# MySQL 自定义配置 - CapacityReport
|
||||
# 启用 LOAD DATA LOCAL INFILE 支持
|
||||
|
||||
[mysqld]
|
||||
# 字符集
|
||||
character-set-server = utf8mb4
|
||||
collation-server = utf8mb4_unicode_ci
|
||||
|
||||
# 启用 LOAD DATA LOCAL INFILE
|
||||
local_infile = ON
|
||||
secure_file_priv = ""
|
||||
|
||||
# 性能优化
|
||||
max_allowed_packet = 256M
|
||||
innodb_buffer_pool_size = 512M
|
||||
innodb_log_file_size = 128M
|
||||
innodb_flush_log_at_trx_commit = 2
|
||||
sync_binlog = 0
|
||||
|
||||
# 连接设置
|
||||
max_connections = 200
|
||||
wait_timeout = 28800
|
||||
interactive_timeout = 28800
|
||||
|
||||
# 日志(可选,生产环境建议注释掉)
|
||||
# general_log = 1
|
||||
# general_log_file = /var/lib/mysql/general.log
|
||||
|
||||
[mysql]
|
||||
# 客户端设置
|
||||
local_infile = ON
|
||||
default-character-set = utf8mb4
|
||||
|
||||
[client]
|
||||
default-character-set = utf8mb4
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
-- MySQL 初始化脚本 - 确保数据库以正确的字符集创建
|
||||
-- 此脚本仅在首次初始化时执行(数据目录为空时)
|
||||
|
||||
-- 如果数据库不存在,则创建(使用 utf8mb4 字符集)
|
||||
CREATE DATABASE IF NOT EXISTS CapacityReport
|
||||
CHARACTER SET utf8mb4
|
||||
COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- 切换到数据库
|
||||
USE CapacityReport;
|
||||
|
||||
-- 输出确认信息
|
||||
SELECT 'CapacityReport database initialized with utf8mb4 charset' AS status;
|
||||
Reference in New Issue
Block a user