| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- @page "/app/product"
- @attribute [ReuseTabsPage(Title = "商品管理")]
- <Spin Spinning="Loading">
- <Table @ref="_Table"
- AutoHeight
- TItem="TProduct"
- @bind-PageSize="Ps"
- @bind-PageIndex="Pi"
- Total="Total"
- DataSource="DataSource"
- @bind-SelectedRows="SelectedRows"
- ScrollX="1300"
- OnChange="OnChange">
- <TitleTemplate>
- <Flex Justify="FlexJustify.Start" Gap="@("10")">
- <Input Width="300" Placeholder="输入商品名称" @bind-Value="@Q_Name" />
- <Input Width="300" Placeholder="输入商品编码" @bind-Value="@Q_Code" />
- <Button OnClick="Search">搜索</Button>
- <Button OnClick="ResetQuery">重置</Button>
- <Button Type="ButtonType.Primary" Color="Color.Green6" OnClick="() => StartEdit(default)">新增</Button>
- </Flex>
- </TitleTemplate>
- <ColumnDefinitions Context="row">
- <PropertyColumn Align="ColumnAlign.Center" Property="c=>c.Id" Width="100" Title="ID" />
- <PropertyColumn Align="ColumnAlign.Center" Property="c=>c.MainImage" Width="100" Title="主图">
- <Image Src="@row.MainImage" Width="50" Height="50" />
- </PropertyColumn>
- <PropertyColumn Align="ColumnAlign.Center" Property="c=>c.Name" Width="100" Title="商品名称" />
- <PropertyColumn Align="ColumnAlign.Center" Property="c=>c.Code" Width="100" Title="商品编码" />
- <PropertyColumn Align="ColumnAlign.Center" Width="100" Property="c=>c.Available" Title="是否上架">
- <Switch Checked="@row.Available" @bind-Value="@row.Available" CheckedChildren="上架" UnCheckedChildren="下架" OnChange="() => CheckedChanged(row)" />
- </PropertyColumn>
- <PropertyColumn Align="ColumnAlign.Center" Property="c=>c.TotalStock" Width="100" Title="总库存" />
- <PropertyColumn Align="ColumnAlign.Center" Property="c => c.CreateTime" Width="200" Title="创建时间">
- @{
- var formattedTime = row.CreateTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? "N/A";
- }
- @formattedTime
- </PropertyColumn>
- <ActionColumn Width="180" Title="操作" Fixed="ColumnFixPlacement.Right">
- <Button Type="ButtonType.Primary" Color="Color.Blue6" OnClick="() => StartEdit(row)">编辑</Button>
- </ActionColumn>
- </ColumnDefinitions>
- <PaginationTemplate>
- <Pagination Class="@(context.PaginationClass + " my-custom-pagination")"
- Total="context.Total"
- PageSize="context.PageSize"
- Current="context.PageIndex"
- ShowSizeChanger
- OnChange="context.HandlePageChange" />
- </PaginationTemplate>
- </Table>
- </Spin>
- <Modal Visible="previewVisible"
- Title="预览图"
- OnCancel="()=> previewVisible=false">
- <img style="width: 100%" src="@imgUrl" />
- </Modal>
- @inject ModalService ModalService;
- @inject ConfirmService ComfirmService;
- @inject IMessageService MessageService;
- @code {
- /// <summary>
- /// 富文本配置项
- /// 在这里注册获取key:https://www.tiny.cloud/
- /// </summary>
- public static Dictionary<string, object> TinyMCEConfig { get; set; } = new()
- {
- // 配置项
- { "language_url", "/lib/tinymce/langs/zh_CN.js" },
- { "language", "zh_CN" },
- { "min_width", 500 },
- //{ "max_width", 1000 },
- { "min_height", 500 },
- //{ "max_height", 1000 },
- { "plugins", "table image code link lists insertdatetime preview searchreplace wordcount" },
- { "toolbar", "undo redo | searchreplace removeformat | bold italic underline strikethrough subscript superscript | alignleft aligncenter alignright outdent indent blockquote | code codesample | fontsize fontfamily styles forecolor backcolor | hr bullist numlist | link image charmap preview anchor pagebreak insertdatetime table emoticons | fullscreen" },
- { "toolbar_mode", "wrap" },
- { "promotion", false },//关闭升级付费提示
- { "paste_data_images", true },//内存中的图片粘贴为base64文本格式
- { "image_uploadtab", true },
- { "images_file_types", "jpg,jpeg,png,gif" },
- { "images_upload_credentials", "false" },//同域名下基于Cookie鉴权
- { "images_upload_url", Global.UploadUrl },//图片上传地址
- };
- private void StartEdit(TProduct row)
- {
- tProduct = row ?? new();
- InitFormData(row);
- IForm form = default;
- modalRef = ModalService.CreateModal<bool>(new()
- {
- Width = "1300px",
- Title = tProduct.Id > 0 ? "编辑" : "新增",
- Content =
- @<Form @ref="form" Model="tProduct" OnFinish="()=> modalRef.OkAsync(true)" LabelColSpan="6" WrapperColSpan="18">
- <FormItem Label="名称" Required>
- <Input @bind-Value="@tProduct.Name" />
- </FormItem>
- @if (tProduct.Id == 0)
- {
- <FormItem Label="编码" ToolTip="不填写则自动生成">
- <Input @bind-Value="@tProduct.Code" />
- </FormItem>
- }
- else
- {
- <FormItem Label="编码">
- <Input @bind-Value="@tProduct.Code" ReadOnly />
- </FormItem>
- }
- <FormItem Label="介绍" Required>
- <Input @bind-Value="@tProduct.Description" />
- </FormItem>
- @if (tProduct.Id == 0)
- {
- <FormItem Label="是否上架">
- <Switch @bind-Value="@tProduct.Available" />
- </FormItem>
- }
- <FormItem Label="预览图" Required>
- <Upload Action="@Global.UploadUrl"
- Name="preview"
- ShowUploadList=true
- ShowPreviewIcon=true
- ShowRemoveIcon=true
- @bind-FileList="FileList"
- ShowButton="FileList?.Count < 8"
- ListType="UploadListType.PictureCard"
- BeforeUpload="BeforeUpload"
- OnPreview="(file)=> {
- previewVisible = true;
- imgUrl = file.Url;
- }"
- OnSingleCompleted="(file)=>{
- if (file.File.State == UploadState.Success)
- {
- var result = file.File.GetResponse<Result<string>>();
- file.File.Url = result.Data;
- modalRef.UpdateConfigAsync();//这里必须加上这一段,否则图片上传后无法正常显示,使用该方法触发modal重新渲染
- }
- }">
- <div>
- <Icon Type="@IconType.Outline.Plus" />
- <div className="ant-upload-text">上传</div>
- </div>
- </Upload>
- </FormItem>
- <FormItem Label="详细描述" Required>
- <TinyMCE.Blazor.Editor @bind-Value="tProduct.Content"
- ApiKey="@Global.TinyMCEApiKey"
- LicenseKey="gpl"
- Field="() => tProduct.Content"
- Conf="@TinyMCEConfig"
- ScriptSrc="lib/tinymce/tinymce.min.js" />
- </FormItem>
- <FormItem Label="规格" Required>
- @foreach (var TPropertyItem in TPropertyItems)
- {
- <InputGroup Style="margin-bottom: 8px;" Compact>
- <Select TItem="TProductProperty"
- @ref="@TPropertyItem.MainSelect"
- TItemValue="long?"
- DataSource="@TPropertyItem.MainProperties"
- @bind-Value="@TPropertyItem.MainSelectedValue"
- ValueName="@nameof(TProductProperty.Id)"
- LabelName="@nameof(TProductProperty.Name)"
- Placeholder="选择规格"
- @onclick="OnClick"
- OnSelectedItemChanged="@((args) => OnMainSelectedItemChanged(@TPropertyItem, args))"
- Style="width: 240px;">
- <DropdownRender Context="originNode">
- <div>
- @originNode
- <Divider Style="margin: 4px 0"></Divider>
- <div style="display: flex; flex-wrap: nowrap; padding: 8px">
- <Input Style="flex: auto" @bind-Value="@_name" />
- <Button OnClick="AddNewMainProperty" Icon="@IconType.Outline.Plus" />
- </div>
- </div>
- </DropdownRender>
- </Select>
- <Select Mode="SelectMode.Multiple"
- @ref="@TPropertyItem.ChildSelect"
- TItem="TProductProperty"
- TItemValue="long?"
- DataSource="@TPropertyItem.ChildProperties"
- @bind-Values="@TPropertyItem.ChildSelectedValues"
- ValueName="@nameof(TProductProperty.Id)"
- LabelName="@nameof(TProductProperty.Name)"
- Placeholder="选择属性"
- @onclick="OnClick"
- OnSelectedItemsChanged="OnChildSelectedItemsChanged">
- <DropdownRender Context="originNode">
- <div>
- @originNode
- <Divider Style="margin: 4px 0"></Divider>
- <div style="display: flex; flex-wrap: nowrap; padding: 8px">
- <Input Style="flex: auto" @bind-Value="@_name" />
- <Button OnClick="(args)=>AddNewChildProperty(TPropertyItem, args)" Icon="@IconType.Outline.Plus" />
- </div>
- </div>
- </DropdownRender>
- </Select>
- @if(TPropertyItem.Index>1)
- {
- <Button Style="width:50px;" OnClick="(args)=>DeleteProperty(TPropertyItem, args)" Icon="@IconType.Outline.Delete" />
- }
- </InputGroup>
- }
- </FormItem>
- <FormItem WrapperColOffset="6" WrapperColSpan="18">
- <Button OnClick="AddProperty" Style="width:100%;" Disabled="@IsDisabled" Icon="@IconType.Outline.Plus">添加规格</Button>
- </FormItem>
- <FormItem Label="Sku设置" >
- <Table @ref="SkuTable" DataSource="tProduct.Skus" TItem="TProductSku" Context="row" Size="TableSize.Small" HidePagination Bordered>
- <PropertyColumn Width="200px" Property="c=>c.PropertyName" Title="规格名称">
- <FormItem >
- <Input @bind-Value="@row.PropertyName" ReadOnly />
- </FormItem>
- </PropertyColumn>
- <PropertyColumn Width="50px" Property="c=>c.Image" Title="预览图">
- <FormItem>
- <Upload Action="@Global.UploadUrl"
- Name="skuimage"
- Class="skuimage-uploader"
- ListType="UploadListType.PictureCard"
- ShowUploadList="false"
- BeforeUpload="BeforeUpload"
- OnSingleCompleted="(file)=>{
- ImageLoading = file.File.State == UploadState.Uploading;
- if (file.File.State == UploadState.Success)
- {
- var result = file.File.GetResponse<Result<string>>();
- row.Image = result.Data;
- modalRef.UpdateConfigAsync();
- }
- }">
- @if (!string.IsNullOrWhiteSpace(@row.Image))
- {
- <img src="@GetImageUrl(row, row.Image)" alt="sku image" style="width: 100%" />
- }
- else
- {
- <div>
- <Icon Spin="ImageLoading" Type="@(ImageLoading ? IconType.Outline.Loading : IconType.Outline.Plus)" />
- <div className="ant-upload-text">上传图片</div>
- </div>
- }
- </Upload>
- </FormItem>
- </PropertyColumn>
- <PropertyColumn Width="200px" Property="c=>c.Code" Title="编码">
- <FormItem>
- <Input @bind-Value="@row.Code" />
- </FormItem>
- </PropertyColumn>
- <PropertyColumn Property="c=>c.Cost" Title="原价">
- <FormItem>
- <AntDesign.InputNumber @bind-Value="@row.Cost" Min="0"/>
- </FormItem>
- </PropertyColumn>
- <PropertyColumn Property="c=>c.Price" Title="现价">
- <FormItem>
- <AntDesign.InputNumber @bind-Value="@row.Price" Min="0" />
- </FormItem>
- </PropertyColumn>
- <PropertyColumn Property="c=>c.Stock" Title="库存">
- <FormItem>
- <AntDesign.InputNumber @bind-Value="@row.Stock" Min="0" />
- </FormItem>
- </PropertyColumn>
- </Table>
- </FormItem>
- </Form>
- ,
- OnOk = async (e) =>
- {
- if (!form.Validate())
- {
- return;
- }
- if (FileList?.Count == 0)
- {
- MessageService.Warning("必须上传预览图");
- return;
- }
- modalRef.SetConfirmLoading(true);
- var flag = InsertOrUpdate(tProduct);
- if (flag)
- {
- TPropertyItems.Clear();
- MessageService.Success("操作成功");
- await modalRef.CloseAsync();
- _Table.ReloadData(Pi, Ps);
- StateHasChanged();
- }
- else
- {
- MessageService.Error("操作失败");
- }
- modalRef.SetConfirmLoading(false);
- },
- OnCancel = async (e) =>
- {
- if (form.IsModified && (!await Comfirm("已修改内容,确定退出吗?")))
- {
- return;
- }
- await modalRef.CloseAsync();
- }
- });
- modalRef.UpdateConfigAsync();
- }
- private string GetImageUrl(TProductSku row, string imageUrl)
- {
- if (!string.IsNullOrEmpty(imageUrl))
- {
- return imageUrl;
- }
- else
- {
- var image = row.Image;
- return image;
- }
- }
- private async Task<bool> Comfirm(string message)
- {
- return await ComfirmService.Show(message, "提示", ConfirmButtons.YesNo, ConfirmIcon.Warning) == ConfirmResult.Yes;
- }
- }
|