feat: add docfill mvp cli
This commit is contained in:
13
scripts/build.sh
Executable file
13
scripts/build.sh
Executable 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"
|
||||
137
scripts/smoke-fixtures/main.go
Normal file
137
scripts/smoke-fixtures/main.go
Normal 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
31
scripts/smoke.sh
Executable 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"
|
||||
Reference in New Issue
Block a user