XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

STHApplication

【MAUI】寄当家——安卓端交易管理系统

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json;
using JiDangJia.Core;

namespace JiDangJia.Views;

public sealed class PrintTemplatesPage : ContentPage
{
    private readonly BusinessService service;
    private readonly VerticalStackLayout body=Ui.Stack();
    public PrintTemplatesPage(BusinessService service){this.service=service;Title="打印模板";body.Padding=18;Content=new ScrollView{Content=body};}
    protected override void OnAppearing()
    {
        base.OnAppearing();Title="打印模板";body.Clear();body.Padding=18;
        body.Add(Ui.Text("可自行修改凭证,无需重新发布 APP。新增模板后选择凭证类型,勾选要打印的项目,再预览并设为默认。复杂排版也可以导入 HTML 模板。",13,Ui.Muted));
        body.Add(Ui.Button("+ 新增打印模板",()=>Navigation.PushAsync(new PrintTemplateEditorPage(service,new DbRow()))));
        foreach(var row in service.Db.Query("SELECT * FROM PrintTemplate ORDER BY type,isDefault DESC,updatedAt DESC"))body.Add(Ui.Tap(Ui.Card(Ui.Stack(Ui.Spread(Ui.Text(row.Text("name"),17,bold:true),Ui.Pill(row.Int("isDefault")==1?"默认":"备用")),Ui.Text((row.Text("type")=="PAWN"?"当票":"回收凭证")+" · "+row.Text("pageSize","A5"),12,Ui.Muted))),()=>Navigation.PushAsync(new PrintTemplateEditorPage(service,row))));
    }
}

public sealed class PrintTemplateEditorPage : ContentPage
{
    private sealed record VisualSettings(string Title,string Footer,List<string> Fields);
    private readonly BusinessService service;
    private readonly DbRow row;
    private readonly Entry name=new(){Placeholder="模板名称 *",MaxLength=80},heading=new(){Placeholder="凭证标题",MaxLength=100};
    private readonly Picker kind=new(){Title="凭证类型",ItemsSource=new List<string>{"当票","回收凭证"}},paper=new(){Title="纸张",ItemsSource=new List<string>{"A5","A4"}};
    private readonly Editor footer=new(){HeightRequest=110,Placeholder="签字栏、说明、交易约定等"},html=new(){HeightRequest=300,Placeholder="HTML 模板代码"};
    private readonly Switch primary=new(){OnColor=Ui.Bronze},advanced=new(){OnColor=Ui.Bronze},landscape=new(){OnColor=Ui.Bronze};
    private readonly Dictionary<string,CheckBox> fields=[];
    public PrintTemplateEditorPage(BusinessService service,DbRow row)
    {
        this.service=service;this.row=new(row);Title=row.Id.Length==0?"新增打印模板":"修改打印模板";
        VisualSettings? visual=null;try{if(row.Text("description").StartsWith("JDJ_VISUAL:"))visual=JsonSerializer.Deserialize<VisualSettings>(row.Text("description")[11..]);}catch(JsonException){}
        name.Text=row.Text("name");kind.SelectedIndex=row.Text("type")=="RECYCLE"?1:0;paper.SelectedIndex=row.Text("pageSize")=="A4"?1:0;landscape.IsToggled=row.Text("orientation")=="landscape";primary.IsToggled=row.Id.Length==0||row.Int("isDefault")==1;
        heading.Text=visual?.Title??(kind.SelectedIndex==0?"当票":"回收凭证");footer.Text=visual?.Footer??"客户签名:________________\n经办人:________________";html.Text=row.Text("content");advanced.IsToggled=visual is null&&row.Id.Length>0;
        var basic=Ui.Stack(Ui.Text("凭证标题",12,Ui.Muted),heading,Ui.Text("勾选凭证内容(按下列顺序排版)",12,Ui.Muted));
        foreach(var f in VoucherTemplates.Fields){var box=new CheckBox{Color=Ui.Bronze,IsChecked=visual?.Fields.Contains(f.Key)??true};fields[f.Key]=box;basic.Add(Ui.Row(box,Ui.Text(f.Value,14)));}basic.Add(Ui.Text("页尾 / 签字栏",12,Ui.Muted));basic.Add(footer);
        var advancedBody=Ui.Stack(Ui.Text("高级模板使用 HTML。可从文件导入;保留 {{shopName}}、{{ticketNo}}、{{customerName}}、{{itemName}}、{{amount}}、{{date}}、{{dueDate}}、{{remark}}、{{address}}、{{phone}},打印时会自动替换。",12,Ui.Muted),html,Ui.Button("导入 HTML 文件",Import,false));
        var basicCard=Ui.Card(basic);var advancedCard=Ui.Card(advancedBody);
        void Mode(){basicCard.IsVisible=!advanced.IsToggled;advancedCard.IsVisible=advanced.IsToggled;}Mode();advanced.Toggled+=(_,_)=>Mode();
        var body=Ui.Stack(Ui.Card(Ui.Stack(Ui.Text("模板名称",12,Ui.Muted),name,kind,Ui.Spread(Ui.Text("设为该凭证类型的默认模板"),primary),paper,Ui.Spread(Ui.Text("横向纸张"),landscape),Ui.Spread(Ui.Text("高级 HTML 模式"),advanced))),basicCard,advancedCard,Ui.Button("预览示例凭证",Preview,false),Ui.Button("保存打印模板",Save));body.Padding=18;Content=new ScrollView{Content=body};
    }
    private string Html()=>advanced.IsToggled?html.Text?.Trim()??"":VoucherTemplates.Basic(heading.Text??"",footer.Text??"",fields.Where(p=>p.Value.IsChecked).Select(p=>p.Key),paper.SelectedIndex==1?"A4":"A5",landscape.IsToggled);
    private async Task Import(){var file=await FilePicker.Default.PickAsync(new PickOptions{PickerTitle="选择 HTML 模板文件"});if(file is null)return;await using var stream=await file.OpenReadAsync();using var reader=new StreamReader(stream);var value=await reader.ReadToEndAsync();if(value.Length>200000)throw new ArgumentException("模板文件过大,最多 20 万字符");html.Text=value;}
    private Task Preview()
    {
        var example=new Dictionary<string,string>{["shopName"]=service.Shop.Text("name"),["ticketNo"]="示例202610190001",["customerName"]="示例客户",["itemName"]="示例物品",["amount"]="¥10,000.00",["date"]=Display.Day(DateTime.Today),["dueDate"]=Display.Day(DateTime.Today.AddDays(30)),["remark"]="此页为示例排版,不会保存业务数据。",["address"]=service.Shop.Text("address"),["phone"]=service.Shop.Text("phone")};
        return Navigation.PushAsync(new ContentPage{Title="模板预览(示例)",Content=new WebView{Source=new HtmlWebViewSource{Html=VoucherTemplates.Render(Html(),example)}}});
    }
    private async Task Save()
    {
        if(string.IsNullOrWhiteSpace(name.Text)||string.IsNullOrWhiteSpace(Html()))throw new ArgumentException("请填写模板名称与内容");
        var saved=new DbRow(row){["name"]=name.Text.Trim(),["type"]=kind.SelectedIndex==1?"RECYCLE":"PAWN",["pageSize"]=paper.SelectedIndex==1?"A4":"A5",["orientation"]=landscape.IsToggled?"landscape":"portrait",["content"]=Html(),["description"]=advanced.IsToggled?"":"JDJ_VISUAL:"+JsonSerializer.Serialize(new VisualSettings(heading.Text??"",footer.Text??"",fields.Where(p=>p.Value.IsChecked).Select(p=>p.Key).ToList())),["isDefault"]=primary.IsToggled?1:0};if(saved.Id.Length==0){saved["id"]=Database.Id("print");saved["createdAt"]=Database.Now;}saved["updatedAt"]=Database.Now;
        service.Db.Write(c=>{if(primary.IsToggled)Database.Execute(c,"UPDATE PrintTemplate SET isDefault=0 WHERE type=@p0",saved.Text("type"));Database.Upsert(c,"PrintTemplate",saved);return 0;});await Navigation.PopAsync();
    }
}