同步页面权限、业务功能、SQL脚本及项目文档

This commit is contained in:
Developer
2026-10-22 09:05:16 +08:00
parent ffac9fcc61
commit 9f64ad5c82
201 changed files with 343899 additions and 637 deletions

View File

@@ -0,0 +1,206 @@
// 修改人:Ld 修改时间:2026-09-17 11:20:00; 生成正式库本月订单与所属合同关联明细 Excel。
import fs from "node:fs/promises";
import path from "node:path";
import { SpreadsheetFile, Workbook } from "@oai/artifact-tool";
const outputDir = path.resolve("outputs/order_contract_links_202609");
const jsonPath = path.join(outputDir, "order_contract_links_202609.json");
const summaryPath = path.join(outputDir, "extract_summary.json");
const outputPath = path.join(outputDir, "正式库订单关联合同明细_2026-09.xlsx");
const rows = JSON.parse(await fs.readFile(jsonPath, "utf8"));
const extractSummary = JSON.parse(await fs.readFile(summaryPath, "utf8"));
const workbook = Workbook.create();
const summarySheet = workbook.worksheets.add("汇总");
const detailSheet = workbook.worksheets.add("明细");
summarySheet.tabColor = "#1F4E78";
detailSheet.tabColor = "#5B9BD5";
summarySheet.showGridLines = false;
detailSheet.showGridLines = false;
const headers = [
"订单流水号",
"订单编号",
"订单类型",
"订单类型名称",
"补货类型",
"项目流水号",
"所属合同编号",
"所属合同类型",
"所属合同类型名称",
"关联类型",
"是否已关联合同",
"下单日期",
"下单人",
"客户名称",
"收货人员",
"合同经手人",
"合同签订日期",
"合同交货日期",
"审核期限",
"通用装配期限",
"采购期限",
"精工期限",
"专机装配期限",
"订单备注",
"合同备注",
"合同状态",
"订单状态",
"下达部门",
];
const detailValues = [
headers,
...rows.map((row) => headers.map((header) => row[header] ?? "")),
];
detailSheet.getRangeByIndexes(0, 0, detailValues.length, headers.length).values = detailValues;
const detailRange = detailSheet.getRangeByIndexes(0, 0, detailValues.length, headers.length);
detailRange.format.font = { name: "Arial", size: 10, color: "#1F2937" };
detailSheet.getRangeByIndexes(0, 0, 1, headers.length).format = {
fill: "#1F4E78",
font: { name: "Arial", size: 10, bold: true, color: "#FFFFFF" },
};
detailSheet.getRangeByIndexes(0, 0, detailValues.length, headers.length).format.borders = {
preset: "all",
style: "thin",
color: "#D9E2F3",
};
detailSheet.freezePanes.freezeRows(1);
detailSheet.freezePanes.freezeColumns(2);
detailSheet.getRange("A:A").format.numberFormat = "0";
detailSheet.getRange("C:C").format.numberFormat = "0";
detailSheet.getRange("F:F").format.numberFormat = "0";
detailSheet.getRange("H:H").format.numberFormat = "0";
detailSheet.getRange("L:L").format.numberFormat = "yyyy-mm-dd hh:mm";
detailSheet.getRange("Q:W").format.numberFormat = "yyyy-mm-dd";
detailSheet.getRange("N:N").format.columnWidth = 24;
detailSheet.getRange("X:Y").format.columnWidth = 34;
detailSheet.getRange("A:AB").format.autofitColumns();
detailSheet.getRange("A1:AB1").format.verticalAlignment = "center";
detailSheet.getRange("A1:AB1").format.wrapText = true;
detailSheet.getRange("A:AB").format.verticalAlignment = "center";
detailSheet.tables.add(`A1:AB${Math.max(detailValues.length, 2)}`, true, "OrderContractLinks");
const total = rows.length;
const linked = rows.filter((row) => row["是否已关联合同"] === "是").length;
const missing = total - linked;
const replenishment = rows.filter((row) => Number(row["订单类型"]) === 3).length;
const linkedReplenishment = rows.filter((row) => row["关联类型"] === "补货挂销售合同").length;
const independentReplenishment = rows.filter((row) => row["关联类型"] === "补货独立合同").length;
const typeCounts = new Map();
const relationCounts = new Map();
for (const row of rows) {
const typeName = row["订单类型名称"] || "未定义";
typeCounts.set(typeName, (typeCounts.get(typeName) || 0) + 1);
const relation = row["关联类型"] || "未定义";
relationCounts.set(relation, (relationCounts.get(relation) || 0) + 1);
}
summarySheet.getRange("B2").values = [["正式库订单关联合同明细"]];
summarySheet.getRange("B3").values = [[`期间:${extractSummary.开始日期} 至 ${extractSummary.结束日期}(不含结束日)`]];
summarySheet.getRange("B4").values = [[`数据源:${extractSummary.数据库},导出时间:${extractSummary.导出时间}`]];
summarySheet.getRange("B2").format.font = { name: "Arial", size: 14, bold: true, color: "#111827" };
summarySheet.getRange("B3:B4").format.font = { name: "Arial", size: 10, italic: true, color: "#4B5563" };
summarySheet.getRange("B5:I5").format.borders = { preset: "doubleBottom", style: "thin", color: "#1F4E78" };
summarySheet.getRange("B7:C12").values = [
["指标", "数量"],
["本月订单数", total],
["已关联合同数", linked],
["未关联合同数", missing],
["补货订单数", replenishment],
["补货挂销售合同数", linkedReplenishment],
];
summarySheet.getRange("E8:F8").values = [["补货独立合同数", independentReplenishment]];
summarySheet.getRange("B7:C7").format = {
fill: "#1F4E78",
font: { name: "Arial", size: 10, bold: true, color: "#FFFFFF" },
};
summarySheet.getRange("E8:F8").format = {
fill: "#EAF2F8",
font: { name: "Arial", size: 10, bold: true, color: "#1F2937" },
};
summarySheet.getRange("B7:C12").format.borders = { preset: "all", style: "thin", color: "#D9E2F3" };
summarySheet.getRange("E8:F8").format.borders = { preset: "all", style: "thin", color: "#D9E2F3" };
summarySheet.getRange("C8:C12").format.numberFormat = "#,##0";
summarySheet.getRange("F8:F8").format.numberFormat = "#,##0";
const typeRows = [["订单类型名称", "数量"], ...Array.from(typeCounts.entries()).sort((a, b) => b[1] - a[1])];
summarySheet.getRangeByIndexes(14, 1, typeRows.length, 2).values = typeRows;
summarySheet.getRangeByIndexes(14, 1, 1, 2).format = {
fill: "#1F4E78",
font: { name: "Arial", size: 10, bold: true, color: "#FFFFFF" },
};
summarySheet.getRangeByIndexes(14, 1, typeRows.length, 2).format.borders = {
preset: "all",
style: "thin",
color: "#D9E2F3",
};
summarySheet.getRangeByIndexes(15, 2, Math.max(typeRows.length - 1, 1), 1).format.numberFormat = "#,##0";
const relationRows = [["关联类型", "数量"], ...Array.from(relationCounts.entries()).sort((a, b) => b[1] - a[1])];
summarySheet.getRangeByIndexes(14, 4, relationRows.length, 2).values = relationRows;
summarySheet.getRangeByIndexes(14, 4, 1, 2).format = {
fill: "#1F4E78",
font: { name: "Arial", size: 10, bold: true, color: "#FFFFFF" },
};
summarySheet.getRangeByIndexes(14, 4, relationRows.length, 2).format.borders = {
preset: "all",
style: "thin",
color: "#D9E2F3",
};
summarySheet.getRangeByIndexes(15, 5, Math.max(relationRows.length - 1, 1), 1).format.numberFormat = "#,##0";
summarySheet.getRange("B24").values = [["说明"]];
summarySheet.getRange("B25").values = [["订单所属合同按 合同管理_订单信息_基础表.项目流水号 = PDM_项目名称.项目流水号 关联。"]];
summarySheet.getRange("B26").values = [["普通补货通常关联系统生成的补货合同,关联合同补货会指向对应销售合同。"]];
summarySheet.getRange("B24").format.font = { name: "Arial", size: 11, bold: true, color: "#111827" };
summarySheet.getRange("B25:B26").format.font = { name: "Arial", size: 10, color: "#374151" };
summarySheet.getRange("B:I").format.autofitColumns();
summarySheet.getRange("B:B").format.columnWidth = 22;
summarySheet.getRange("E:E").format.columnWidth = 22;
summarySheet.getRange("B2:I26").format.verticalAlignment = "center";
workbook.recalculate();
const summaryPreview = await workbook.render({
sheetName: "汇总",
range: "B2:F26",
scale: 1,
format: "png",
});
await fs.writeFile(path.join(outputDir, "summary_preview.png"), new Uint8Array(await summaryPreview.arrayBuffer()));
const detailPreview = await workbook.render({
sheetName: "明细",
range: "A1:AB20",
scale: 1,
format: "png",
});
await fs.writeFile(path.join(outputDir, "detail_preview.png"), new Uint8Array(await detailPreview.arrayBuffer()));
const check = await workbook.inspect({
kind: "table",
sheetId: "汇总",
range: "B7:F20",
include: "values",
tableMaxRows: 20,
tableMaxCols: 6,
});
console.log(check.ndjson);
const errors = await workbook.inspect({
kind: "match",
searchTerm: "#REF!|#DIV/0!|#VALUE!|#NAME\\?|#N/A|#NUM!|#NULL!|#SPILL!|#CALC!",
options: { useRegex: true, maxResults: 300 },
summary: "final formula error scan",
});
console.log(errors.ndjson);
await fs.mkdir(outputDir, { recursive: true });
const xlsx = await SpreadsheetFile.exportXlsx(workbook);
await xlsx.save(outputPath);
console.log(`xlsx=${outputPath}`);
console.log(`rows=${rows.length}`);

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

View File

@@ -0,0 +1,117 @@
# 修改人:Ld 修改时间:2026-09-17 11:20:00; 从正式库导出本月订单与所属合同关联数据,供 Excel 生成脚本使用。
$ErrorActionPreference = 'Stop'
$outputDir = Join-Path (Get-Location) 'outputs/order_contract_links_202609'
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null
$connectionString = 'Server=192.168.1.27;Database=ERPTOOL_JY;User ID=sa;Password=126.com;TrustServerCertificate=True;Connection Timeout=10'
$connection = New-Object System.Data.SqlClient.SqlConnection $connectionString
$connection.Open()
try {
$command = $connection.CreateCommand()
$command.CommandTimeout = 120
$command.CommandText = @"
DECLARE @开始日期 DATETIME = '2026-09-01';
DECLARE @结束日期 DATETIME = '2026-10-01';
SELECT
o.订单流水号,
o.订单编号,
o.订单类型,
CASE
WHEN o.订单类型 = 1 THEN N'模块销售订单'
WHEN o.订单类型 = 2 THEN N'专机销售订单'
WHEN o.订单类型 = 3 AND o.订单编号 LIKE N'BHWG%' THEN N'外购补货订单'
WHEN o.订单类型 = 3 AND o.订单编号 LIKE N'BHZZ%' THEN N'自制补货订单'
WHEN o.订单类型 = 3 THEN N'补货订单'
WHEN o.订单类型 = 5 THEN N'售后订单'
WHEN o.订单类型 = 6 THEN N'新模块订单'
WHEN o.订单类型 = 7 THEN N'新专机订单'
ELSE N'未定义'
END AS 订单类型名称,
CASE
WHEN o.订单类型 = 3 AND o.订单编号 LIKE N'BHWG%' THEN N'外购补货'
WHEN o.订单类型 = 3 AND o.订单编号 LIKE N'BHZZ%' THEN N'自制补货'
ELSE N''
END AS 补货类型,
o.项目流水号,
p.合同编号 AS 所属合同编号,
p.合同类型 AS 所属合同类型,
CASE
WHEN p.合同类型 = 1 THEN N'模块合同'
WHEN p.合同类型 = 2 THEN N'专机合同'
WHEN p.合同类型 = 3 THEN N'补货/仓库备货合同'
WHEN p.合同类型 = 5 THEN N'售后合同'
WHEN p.合同类型 = 6 THEN N'新模块合同'
WHEN p.合同类型 = 7 THEN N'新专机合同'
ELSE N'未定义'
END AS 所属合同类型名称,
CASE
WHEN o.订单类型 = 3 AND p.合同类型 <> 3 THEN N'补货挂销售合同'
WHEN o.订单类型 = 3 AND p.合同类型 = 3 THEN N'补货独立合同'
WHEN o.订单编号 = p.合同编号 THEN N'订单号同合同号'
ELSE N'订单关联销售合同'
END AS 关联类型,
CASE WHEN p.项目流水号 IS NULL THEN N'否' ELSE N'是' END AS 是否已关联合同,
CONVERT(varchar(19), o.下单日期, 120) AS 下单日期,
ISNULL(d.姓名, N'') AS 下单人,
ISNULL(pv.客户名称, N'') AS 客户名称,
ISNULL(pv.收货人员, N'') AS 收货人员,
ISNULL(pv.经手人, N'') AS 合同经手人,
CONVERT(varchar(10), p.签订日期, 120) AS 合同签订日期,
CONVERT(varchar(10), p.交货日期, 120) AS 合同交货日期,
CONVERT(varchar(10), o.审核期限, 120) AS 审核期限,
CONVERT(varchar(10), o.通用装配期限, 120) AS 通用装配期限,
CONVERT(varchar(10), o.采购期限, 120) AS 采购期限,
CONVERT(varchar(10), o.精工期限, 120) AS 精工期限,
CONVERT(varchar(10), o.专机装配期限, 120) AS 专机装配期限,
ISNULL(o.订单备注, N'') AS 订单备注,
ISNULL(p.合同备注, N'') AS 合同备注,
ISNULL(pv.状态, N'') AS 合同状态,
ISNULL(ov.订单状态, N'') AS 订单状态,
ISNULL(ov.下达部门, N'') AS 下达部门
FROM dbo.合同管理_订单信息_基础表 o
LEFT JOIN dbo.PDM_项目名称 p ON o.项目流水号 = p.项目流水号
LEFT JOIN dbo.PDM_项目名称_视图 pv ON o.项目流水号 = pv.项目流水号
LEFT JOIN dbo.PDM_订单信息_视图 ov ON o.订单流水号 = ov.订单流水号
LEFT JOIN dbo.人事档案管理_人员名单 d ON o.下单人 = d.人员编号
WHERE o.下单日期 >= @开始日期
AND o.下单日期 < @结束日期
ORDER BY o.下单日期 DESC, o.订单流水号 DESC;
"@
$adapter = New-Object System.Data.SqlClient.SqlDataAdapter $command
$table = New-Object System.Data.DataTable
[void]$adapter.Fill($table)
$rows = foreach ($row in $table.Rows) {
$object = [ordered]@{}
foreach ($column in $table.Columns) {
$value = $row[$column.ColumnName]
if ($value -is [System.DBNull]) {
$object[$column.ColumnName] = $null
} else {
$object[$column.ColumnName] = $value
}
}
[pscustomobject]$object
}
$jsonPath = Join-Path $outputDir 'order_contract_links_202609.json'
$rows | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath $jsonPath -Encoding UTF8
$summary = [ordered]@{
数据库 = 'ERPTOOL_JY'
开始日期 = '2026-09-01'
结束日期 = '2026-10-01'
导出时间 = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
记录数 = $table.Rows.Count
}
$summary | ConvertTo-Json -Depth 3 | Set-Content -LiteralPath (Join-Path $outputDir 'extract_summary.json') -Encoding UTF8
Write-Output "exported=$($table.Rows.Count)"
Write-Output "json=$jsonPath"
} finally {
$connection.Close()
}

View File

@@ -0,0 +1,7 @@
{
"数据库": "ERPTOOL_JY",
"开始日期": "2026-09-01",
"结束日期": "2026-10-01",
"导出时间": "2026-09-17 11:32:33",
"记录数": 276
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long