feat: add docfill mvp cli

This commit is contained in:
赵义仑
2026-06-18 20:03:47 +08:00
commit ca444bd5d0
22 changed files with 2539 additions and 0 deletions

13
scripts/build.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
OUT_DIR="$ROOT/dist"
OUT="$OUT_DIR/docfill-darwin-arm64"
mkdir -p "$OUT_DIR"
cd "$ROOT"
go build -trimpath -o "$OUT" ./cmd/docfill
echo "$OUT"

View File

@@ -0,0 +1,137 @@
package main
import (
"archive/zip"
"database/sql"
"flag"
"fmt"
"os"
"path/filepath"
_ "modernc.org/sqlite"
"github.com/xuri/excelize/v2"
)
func main() {
base := flag.String("base", "", "examples base directory")
flag.Parse()
if *base == "" {
fmt.Fprintln(os.Stderr, "missing --base")
os.Exit(2)
}
if err := writeExcelToWord(filepath.Join(*base, "excel-to-word")); err != nil {
fmt.Fprintf(os.Stderr, "write excel-to-word fixtures: %v\n", err)
os.Exit(1)
}
if err := writeSQLiteToExcel(filepath.Join(*base, "sqlite-to-excel")); err != nil {
fmt.Fprintf(os.Stderr, "write sqlite-to-excel fixtures: %v\n", err)
os.Exit(1)
}
}
func writeExcelToWord(dir string) error {
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
if err := writeWorkbook(filepath.Join(dir, "data.xlsx"), "Daily", [][]string{
{"name", "date", "done", "plan"},
{"张三", "2026-06-18", "完成接口数据核对", "继续处理异常数据"},
{"李四", "2026-06-18", "完成日报提交", "补充系统截图"},
}); err != nil {
return err
}
return writeDocx(filepath.Join(dir, "template.docx"), `<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:body><w:p><w:r><w:t>员工:{{na</w:t></w:r><w:r><w:t>me}}</w:t></w:r></w:p><w:p><w:r><w:t>日期:{{date}}</w:t></w:r></w:p><w:p><w:r><w:t>完成:{{done}}</w:t></w:r></w:p><w:p><w:r><w:t>计划:{{plan}}</w:t></w:r></w:p></w:body></w:document>`)
}
func writeSQLiteToExcel(dir string) error {
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
if err := writeSQLite(filepath.Join(dir, "data.db")); err != nil {
return err
}
return writeWorkbook(filepath.Join(dir, "template.xlsx"), "Summary", [][]string{
{"部门", "{{department}}"},
{"日期", "{{report_date}}"},
{"总数", "{{total_count}}"},
{"异常数", "{{abnormal_count}}"},
})
}
func writeWorkbook(path, sheet string, rows [][]string) error {
f := excelize.NewFile()
defer f.Close()
defaultSheet := f.GetSheetName(0)
if defaultSheet != sheet {
if err := f.SetSheetName(defaultSheet, sheet); err != nil {
return err
}
}
for r, row := range rows {
for c, value := range row {
cell, err := excelize.CoordinatesToCellName(c+1, r+1)
if err != nil {
return err
}
if err := f.SetCellValue(sheet, cell, value); err != nil {
return err
}
}
}
return f.SaveAs(path)
}
func writeDocx(path, body string) error {
file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()
zw := zip.NewWriter(file)
if err := writeZipEntry(zw, "[Content_Types].xml", `<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"/>`); err != nil {
return err
}
if err := writeZipEntry(zw, "word/document.xml", body); err != nil {
return err
}
return zw.Close()
}
func writeZipEntry(zw *zip.Writer, name, body string) error {
w, err := zw.Create(name)
if err != nil {
return err
}
_, err = w.Write([]byte(body))
return err
}
func writeSQLite(path string) error {
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
return err
}
db, err := sql.Open("sqlite", path)
if err != nil {
return err
}
defer db.Close()
_, err = db.Exec(`
create table department_summary (
department text,
report_date text,
total_count integer,
abnormal_count integer
);
insert into department_summary values
('营销部', '2026-06-18', 128, 3),
('客服部', '2026-06-18', 76, 0),
('客服部', '2026-06-17', 68, 1);
`)
return err
}

31
scripts/smoke.sh Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
TMP="$(mktemp -d "${TMPDIR:-/tmp}/docfill-smoke.XXXXXX")"
cleanup() {
rm -rf "$TMP"
}
trap cleanup EXIT
cd "$ROOT"
go test -count=1 ./...
go build -o "$TMP/docfill" ./cmd/docfill
cp -R examples "$TMP/examples"
go run ./scripts/smoke-fixtures --base "$TMP/examples"
"$TMP/docfill" run -c "$TMP/examples/excel-to-word/task.json" --var date=2026-06-18
"$TMP/docfill" run -c "$TMP/examples/sqlite-to-excel/task.json" --var date=2026-06-18
test -f "$TMP/examples/excel-to-word/out/daily_2026-06-18_张三_1.docx"
test -f "$TMP/examples/excel-to-word/out/daily_2026-06-18_李四_2.docx"
xlsx_count="$(find "$TMP/examples/sqlite-to-excel/out" -type f -name '*.xlsx' | wc -l | tr -d ' ')"
if [[ "$xlsx_count" != "2" ]]; then
echo "expected 2 sqlite-to-excel outputs, got $xlsx_count" >&2
exit 1
fi
echo "smoke ok"