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

STHApplication

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

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

namespace JiDangJia.Views;

public sealed class ContentAdminPage : ContentPage
{
    private readonly VerticalStackLayout list=Ui.Stack();
    private readonly Entry community=new(){Placeholder="官方社群 / 服务页面 HTTPS 地址",MaxLength=2048};
    private AppContent? content;
    private static readonly JsonSerializerOptions json=new(JsonSerializerDefaults.Web);
    public ContentAdminPage()
    {
        if(!AuthClient.Current.IsAdmin)throw new InvalidOperationException("需要管理员权限");Title="首页广告管理";
        var body=Ui.Stack(Ui.Card(Ui.Stack(Ui.Section("全局内容"),Ui.Text("此处发布的首页广告会同步到记账端门店。普通账户只能查看。",13,Ui.Muted))),Ui.Button("+ 新增滚动广告",()=>Edit(null)),list,Ui.Button("刷新后台内容",Load,false));
        body.Padding=18;Content=new ScrollView{Content=body};
    }
    protected override async void OnAppearing(){base.OnAppearing();try{await Load();}catch(Exception ex){await DisplayAlertAsync("无法加载",ex.Message,"知道了");}}
    private async Task Load()
    {
        using var result=await AuthClient.Current.AdminRequest("/content");content=result.RootElement.Deserialize<AppContent>(json)??throw new InvalidOperationException("后台内容数据无效");Render();
    }
    private async Task Save(List<Advertisement> ads,string url)
    {
        if(content is null)throw new InvalidOperationException("请先刷新后台内容");
        using var result=await AuthClient.Current.AdminRequest("/content",new UpdateContentRequest(content.Revision,ads,url));
        content=result.RootElement.Deserialize<AppContent>(json)??throw new InvalidOperationException("后台内容数据无效");ContentClient.Remember(content);Render();
    }
    private void Render()
    {
        if(content is null)return;list.Clear();community.Text=content.CommunityUrl;
        list.Add(Ui.Text($"{content.Ads.Count} 个广告位 · 更新 {DateTime.Parse(content.UpdatedAt).ToLocalTime():MM-dd HH:mm}",12,Ui.Muted));
        foreach(var ad in content.Ads)
        {
            var item=Ui.Stack(Ui.Spread(Ui.Text(ad.Title,17,bold:true),Ui.Pill(ad.Enabled?"已启用":"已停用")),Ui.Text(ad.Subtitle,12,Ui.Muted));
            if(ad.Image.Length>0)item.Add(new Image{Source=MediaFiles.Source(ad.Image),HeightRequest=120,Aspect=Aspect.AspectFill});
            item.Add(Ui.Spread(Ui.Button("编辑广告",()=>Edit(ad),false),Ui.Button("删除",async()=>{if(await DisplayAlertAsync("删除全局广告","所有门店同步后将不再显示此广告。","删除","取消"))await Save(content.Ads.Where(a=>a.Id!=ad.Id).ToList(),content.CommunityUrl);},false)));list.Add(Ui.Card(item));
        }
        if(content.Ads.Count==0)list.Add(Ui.Card(Ui.Empty("暂无广告","新增并发布后,所有门店首页会显示广告")));
    }
    private Task Edit(Advertisement? ad)
    {
        if(content is null)throw new InvalidOperationException("请先刷新后台内容");
        if(ad is null && content.Ads.Count>=20)throw new ArgumentException("最多 20 个广告位");
        return Navigation.PushAsync(new AdvertisementEditor(ad,async updated=>
        {
            var ads=content.Ads.Where(a=>a.Id!=updated.Id).Append(updated).ToList();await Save(ads,content.CommunityUrl);
        }));
    }
}

public sealed class AdvertisementEditor : ContentPage
{
    public AdvertisementEditor(Advertisement? ad,Func<Advertisement,Task> publish)
    {
        if(!AuthClient.Current.IsAdmin)throw new InvalidOperationException("需要管理员权限");Title=ad is null?"新增全局广告":"编辑全局广告";
        var row=new DbRow{["title"]=ad?.Title??"",["subtitle"]=ad?.Subtitle??"",["adPhotos"]=JsonSerializer.Serialize(ad is {Image.Length:>0}?new[]{ad.Image}:Array.Empty<string>()),["link"]=ad?.Link??"",["enabled"]=ad is null || ad.Enabled?1:0,["sortOrder"]=ad?.SortOrder??0};
        var fields=new FieldSet(row,[new("title","广告标题",Required:true),new("subtitle","副标题"),new("adPhotos","广告图片(JPEG / PNG,最多 1 MB)",FieldKind.Photos),new("link","点击跳转 HTTPS 链接"),new("sortOrder","排序",FieldKind.Number,true),new("enabled","启用广告",FieldKind.Toggle)]);
        var id=ad?.Id??Guid.NewGuid().ToString("N");var body=Ui.Stack(Ui.Card(fields.View),Ui.Button("发布到所有门店",async()=>
        {
            var value=fields.Read();if(value.Money("sortOrder")%1!=0 || value.Money("sortOrder") is <0 or >9999)throw new ArgumentException("排序请填写 0 至 9999 的整数");
            var updated=new Advertisement(id,value.Text("title"),value.Text("subtitle"),MediaFiles.Parse(value.Text("adPhotos")).FirstOrDefault()??"",value.Text("link"),value.Int("enabled")==1,value.Int("sortOrder"));
            await publish(updated);await DisplayAlertAsync("已发布","各门店联网后会自动同步。","完成");await Navigation.PopAsync();
        }));body.Padding=18;Content=new ScrollView{Content=body};
    }
}