init 初始化项目

This commit is contained in:
zyxucp
2024-02-01 23:12:53 +08:00
parent fac705d632
commit 697c254b3f
246 changed files with 12436 additions and 0 deletions

63
.gitattributes vendored Normal file
View File

@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

339
.gitignore vendored Normal file
View File

@@ -0,0 +1,339 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.bin
*.Debug
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
*.dll
*.pdb
# MFractors (Xamarin productivity tool) working folder
.mfractor/
/.semantic-kernel/results/src/ISS.IPSA.AiAgent.Api/plugins/BasePlugin/YesNo
**/bin/
**/obj/
**/.vs/
/Xzy.KnowledgeBase/appsettings.Development.json
/Xzy.KnowledgeBase/XzyAgent.db

13
Dockerfile Normal file
View File

@@ -0,0 +1,13 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /service
EXPOSE 5000
WORKDIR /app
COPY ["Xzy.KnowledgeBase/bin/Release/net8.0/publish", "publish"]
WORKDIR /app/publish
FROM base AS final
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
ENTRYPOINT ["dotnet", "Xzy.KnowledgeBase.dll"]

View File

@@ -0,0 +1,57 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Common.DependencyInjection
{
/// <summary>
/// 容器扩展
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// 从程序集中加载类型并添加到容器中
/// </summary>
/// <param name="services">容器</param>
/// <param name="assemblies">程序集集合</param>
/// <returns></returns>
public static IServiceCollection AddServicesFromAssemblies(this IServiceCollection services, params string[] assemblies)
{
Type attributeType = typeof(ServiceDescriptionAttribute);
//var refAssembyNames = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
foreach (var item in assemblies)
{
Assembly assembly = Assembly.Load(item);
var types = assembly.GetTypes();
foreach (var classType in types)
{
if (!classType.IsAbstract && classType.IsClass && classType.IsDefined(attributeType, false))
{
ServiceDescriptionAttribute serviceAttribute = classType.GetCustomAttribute(attributeType) as ServiceDescriptionAttribute;
switch (serviceAttribute.Lifetime)
{
case ServiceLifetime.Scoped:
services.AddScoped(serviceAttribute.ServiceType, classType);
break;
case ServiceLifetime.Singleton:
services.AddSingleton(serviceAttribute.ServiceType, classType);
break;
case ServiceLifetime.Transient:
services.AddTransient(serviceAttribute.ServiceType, classType);
break;
}
}
}
}
return services;
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Common.DependencyInjection
{
public class ServiceDescriptionAttribute : Attribute
{
public ServiceDescriptionAttribute(Type serviceType, ServiceLifetime lifetime)
{
ServiceType = serviceType;
Lifetime = lifetime;
}
public Type ServiceType { get; set; }
public ServiceLifetime Lifetime { get; set; }
}
public enum ServiceLifetime
{
/// <summary>
/// 作用域
/// </summary>
Scoped,
/// <summary>
/// 单例
/// </summary>
Singleton,
/// <summary>
/// 瞬时
/// </summary>
Transient
}
}

View File

@@ -0,0 +1,18 @@
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Map
{
public class AutoMapProfile : Profile
{
public AutoMapProfile()
{
}
}
}

View File

@@ -0,0 +1,53 @@
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Map
{
public static class MapperExtend
{
/// <summary>
/// Entity集合转DTO集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static List<T> ToDTOList<T>(this object value)
{
if (value == null)
return new List<T>();
return Mapper.Map<List<T>>(value);
}
/// <summary>
/// Entity转DTO
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T ToDTO<T>(this object value)
{
if (value == null)
return default(T);
return Mapper.Map<T>(value);
}
/// <summary>
/// 给已有对象map,适合update场景如需过滤空值需要在AutoMapProfile 设置
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="self"></param>
/// <param name="result"></param>
/// <returns></returns>
public static T MapTo<T>(this object self, T result)
{
if (self == null)
return default(T);
return (T)Mapper.Map(self, result, self.GetType(), typeof(T));
}
}
}

View File

@@ -0,0 +1,35 @@
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Map
{
public static class MapperRegister
{
public static void AddMapper(this IServiceCollection services)
{
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMissingTypeMaps = true;
cfg.ValidateInlineMaps = false;
cfg.ShouldMapMethod = m => false;
cfg.AddProfile<AutoMapProfile>();
});
IMapper mapper = config.CreateMapper();
//启动实体映射
Mapper.Initialize(cfg =>
{
cfg.CreateMissingTypeMaps = true;
cfg.ValidateInlineMaps = false;
cfg.ShouldMapMethod = m => false;
cfg.AddProfile<AutoMapProfile>();
});
}
}
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Model
{
public class PageList<T>
{
//查询结果
public List<T> List { get; set; }
/// <summary>
/// 当前页从1开始
/// </summary>
public int PageIndex { get; set; }
/// <summary>
/// 每页数量
/// </summary>
public int PageSize { get; set; }
/// <summary>
/// 总数
/// </summary>
public int TotalCount { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Options
{
public class AIModelOption
{
public static string KmsChatModel { get; set; }
public static string KmsEmbeddingModel { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Options
{
public class ConnectionOption
{
/// <summary>
/// sqlite连接字符串
/// </summary>
public static string Sqlite { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Repositories
{
[SugarTable("Apps")]
public partial class Apps
{
[SugarColumn(IsPrimaryKey = true)]
public string Id { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 描述
/// </summary>
public string Describe { get; set; }
}
}

View File

@@ -0,0 +1,16 @@

using Xzy.KnowledgeBase.Domain.Repositories.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xzy.KnowledgeBase.Domain.Common.DependencyInjection;
namespace Xzy.KnowledgeBase.Domain.Repositories
{
[ServiceDescription(typeof(IApps_Repositories), ServiceLifetime.Scoped)]
public class Apps_Repositories : Repository<Apps>, IApps_Repositories
{
}
}

View File

@@ -0,0 +1,13 @@
using Xzy.KnowledgeBase.Domain.Repositories.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Repositories
{
public interface IApps_Repositories : IRepository<Apps>
{
}
}

View File

@@ -0,0 +1,13 @@
using Xzy.KnowledgeBase.Domain.Repositories.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Repositories
{
public interface IKmss_Repositories : IRepository<Kmss>
{
}
}

View File

@@ -0,0 +1,29 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Repositories
{
[SugarTable("Kms")]
public partial class Kmss
{
[SugarColumn(IsPrimaryKey = true)]
public string Id { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 会话模型
/// </summary>
public string ChatModel { get; set; }
/// <summary>
/// 向量模型
/// </summary>
public string EmbeddingModel { get; set; }
}
}

View File

@@ -0,0 +1,16 @@

using Xzy.KnowledgeBase.Domain.Repositories.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xzy.KnowledgeBase.Domain.Common.DependencyInjection;
namespace Xzy.KnowledgeBase.Domain.Repositories
{
[ServiceDescription(typeof(IKmss_Repositories), ServiceLifetime.Scoped)]
public class Kmss_Repositories : Repository<Kmss>, IKmss_Repositories
{
}
}

View File

@@ -0,0 +1,13 @@
using Xzy.KnowledgeBase.Domain.Repositories.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Repositories
{
public interface IKmsDetails_Repositories : IRepository<KmsDetails>
{
}
}

View File

@@ -0,0 +1,34 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Repositories
{
[SugarTable("KmsDetails")]
public partial class KmsDetails
{
[SugarColumn(IsPrimaryKey = true)]
public string Id { get; set; }
/// <summary>
/// 文件名称
/// </summary>
public string FileName { get; set; }
/// <summary>
/// 数据数量
/// </summary>
public int DataCount { get; set; }
/// <summary>
/// 状态
/// </summary>
public string Status { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
}
}

View File

@@ -0,0 +1,16 @@

using Xzy.KnowledgeBase.Domain.Repositories.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xzy.KnowledgeBase.Domain.Common.DependencyInjection;
namespace Xzy.KnowledgeBase.Domain.Repositories
{
[ServiceDescription(typeof(IKmsDetails_Repositories), ServiceLifetime.Scoped)]
public class KmsDetails_Repositories : Repository<KmsDetails>, IKmsDetails_Repositories
{
}
}

View File

@@ -0,0 +1,62 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Xzy.KnowledgeBase.Domain.Model;
namespace Xzy.KnowledgeBase.Domain.Repositories.Base
{
public interface IRepository<T>
{
SqlSugarScope GetDB();
List<T> GetList();
Task<List<T>> GetListAsync();
List<T> GetList(Expression<Func<T, bool>> whereExpression);
Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression);
int Count(Expression<Func<T, bool>> whereExpression);
Task<int> CountAsync(Expression<Func<T, bool>> whereExpression);
PageList<T> GetPageList(Expression<Func<T, bool>> whereExpression, PageModel page);
PageList<P> GetPageList<P>(Expression<Func<T, bool>> whereExpression, PageModel page);
Task<PageList<T>> GetPageListAsync(Expression<Func<T, bool>> whereExpression, PageModel page);
Task<PageList<P>> GetPageListAsync<P>(Expression<Func<T, bool>> whereExpression, PageModel page);
PageList<T> GetPageList(Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc);
Task<PageList<T>> GetPageListAsync(Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc);
PageList<P> GetPageList<P>(Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc);
Task<PageList<P>> GetPageListAsync<P>(Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc);
PageList<T> GetPageList(List<IConditionalModel> conditionalList, PageModel page);
Task<PageList<T>> GetPageListAsync(List<IConditionalModel> conditionalList, PageModel page);
PageList<T> GetPageList(List<IConditionalModel> conditionalList, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc);
Task<PageList<T>> GetPageListAsync(List<IConditionalModel> conditionalList, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc);
T GetById(dynamic id);
Task<T> GetByIdAsync(dynamic id);
T GetSingle(Expression<Func<T, bool>> whereExpression);
Task<T> GetSingleAsync(Expression<Func<T, bool>> whereExpression);
T GetFirst(Expression<Func<T, bool>> whereExpression);
Task<T> GetFirstAsync(Expression<Func<T, bool>> whereExpression);
bool Insert(T obj);
Task<bool> InsertAsync(T obj);
bool InsertRange(List<T> objs);
Task<bool> InsertRangeAsync(List<T> objs);
int InsertReturnIdentity(T obj);
Task<int> InsertReturnIdentityAsync(T obj);
long InsertReturnBigIdentity(T obj);
Task<long> InsertReturnBigIdentityAsync(T obj);
bool DeleteByIds(dynamic[] ids);
Task<bool> DeleteByIdsAsync(dynamic[] ids);
bool Delete(dynamic id);
Task<bool> DeleteAsync(dynamic id);
bool Delete(T obj);
Task<bool> DeleteAsync(T obj);
bool Delete(Expression<Func<T, bool>> whereExpression);
Task<bool> DeleteAsync(Expression<Func<T, bool>> whereExpression);
bool Update(T obj);
Task<bool> UpdateAsync(T obj);
bool UpdateRange(List<T> objs);
Task<bool> UpdateRangeAsync(List<T> objs);
bool IsAny(Expression<Func<T, bool>> whereExpression);
Task<bool> IsAnyAsync(Expression<Func<T, bool>> whereExpression);
}
}

View File

@@ -0,0 +1,521 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Xzy.KnowledgeBase.Domain.Map;
using Xzy.KnowledgeBase.Domain.Model;
namespace Xzy.KnowledgeBase.Domain.Repositories.Base
{
public class Repository<T> : SimpleClient<T> where T : class, new()
{
public Repository(ISqlSugarClient context = null) : base(context)//注意这里要有默认值等于null
{
if (context == null)
{
}
//Sqlite.DbMaintenance.CreateDatabase();
//Sqlite.CodeFirst.InitTables(typeof(CodeFirstTable1));
}
//注意如果使用Client不能写成静态的Scope并发更高
public static SqlSugarScope Sqlite = SqlSugarHelper.Sqlite;
public SimpleClient<T> CurrentDb
{ get { return new SimpleClient<T>(Sqlite); } }//用来处理T表的常用操作
#region
public virtual SqlSugarScope GetDB()
{
return Sqlite;
}
/// <summary>
/// 获取所有list
/// </summary>
/// <returns></returns>
public virtual List<T> GetList()
{
return CurrentDb.GetList();
}
/// <summary>
/// 获取所有list-异步
/// </summary>
/// <returns></returns>
public virtual async Task<List<T>> GetListAsync()
{
return await CurrentDb.GetListAsync();
}
/// <summary>
/// 根据lambda查询
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual List<T> GetList(Expression<Func<T, bool>> whereExpression)
{
return CurrentDb.GetList(whereExpression);
}
/// <summary>
/// 根据lambda查询-异步
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual async Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression)
{
return await CurrentDb.GetListAsync(whereExpression);
}
/// <summary>
/// 根据lambda表达式获取数量
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual int Count(Expression<Func<T, bool>> whereExpression)
{
return CurrentDb.Count(whereExpression);
}
/// <summary>
/// 根据lambda表达式获取数量-异步
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual async Task<int> CountAsync(Expression<Func<T, bool>> whereExpression)
{
return await CurrentDb.CountAsync(whereExpression);
}
/// <summary>
/// 获取分页
/// </summary>
/// <param name="whereExpression"></param>
/// <param name="page"></param>
/// <returns></returns>
public virtual PageList<T> GetPageList(Expression<Func<T, bool>> whereExpression, PageModel page)
{
PageList<T> list = new PageList<T>();
list.List = CurrentDb.GetPageList(whereExpression, page);
list.PageIndex = page.PageIndex;
list.PageSize = page.PageSize;
list.TotalCount = page.TotalCount;
return list;
}
public virtual PageList<P> GetPageList<P>(Expression<Func<T, bool>> whereExpression, PageModel page)
{
var result = CurrentDb.GetPageList(whereExpression, page);
var pageData = new PageList<P>
{
TotalCount = page.TotalCount,
PageIndex = page.PageIndex,
PageSize = page.PageSize,
List = result.ToDTOList<P>()
};
return pageData;
}
/// <summary>
/// 获取分页-异步
/// </summary>
/// <param name="whereExpression"></param>
/// <param name="page"></param>
/// <returns></returns>
public virtual async Task<PageList<T>> GetPageListAsync(Expression<Func<T, bool>> whereExpression, PageModel page)
{
PageList<T> list = new PageList<T>();
list.List = await CurrentDb.GetPageListAsync(whereExpression, page);
list.PageIndex = page.PageIndex;
list.PageSize = page.PageSize;
list.TotalCount = page.TotalCount;
return list;
}
public virtual async Task<PageList<P>> GetPageListAsync<P>(Expression<Func<T, bool>> whereExpression, PageModel page)
{
var result = await CurrentDb.GetPageListAsync(whereExpression, page);
var pageData = new PageList<P>
{
TotalCount = page.TotalCount,
PageIndex = page.PageIndex,
PageSize = page.PageSize,
List = result.ToDTOList<P>()
};
return pageData;
}
public virtual PageList<T> GetPageList(Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
{
PageList<T> list = new PageList<T>();
list.List = CurrentDb.GetPageList(whereExpression, page, orderByExpression, orderByType);
list.PageIndex = page.PageIndex;
list.PageSize = page.PageSize;
list.TotalCount = page.TotalCount;
return list;
}
public virtual async Task<PageList<T>> GetPageListAsync(Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
{
PageList<T> list = new PageList<T>();
list.List = await CurrentDb.GetPageListAsync(whereExpression, page, orderByExpression, orderByType);
list.PageIndex = page.PageIndex;
list.PageSize = page.PageSize;
list.TotalCount = page.TotalCount;
return list;
}
public virtual PageList<P> GetPageList<P>(Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
{
var result = CurrentDb.GetPageList(whereExpression, page, orderByExpression, orderByType);
var pageData = new PageList<P>
{
TotalCount = page.TotalCount,
PageIndex = page.PageIndex,
PageSize = page.PageSize,
List = result.ToDTOList<P>()
};
return pageData;
}
public virtual async Task<PageList<P>> GetPageListAsync<P>(Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
{
var result = await CurrentDb.GetPageListAsync(whereExpression, page, orderByExpression, orderByType);
var pageData = new PageList<P>
{
TotalCount = page.TotalCount,
PageIndex = page.PageIndex,
PageSize = page.PageSize,
List = result.ToDTOList<P>()
};
return pageData;
}
public virtual PageList<T> GetPageList(List<IConditionalModel> conditionalList, PageModel page)
{
PageList<T> list = new PageList<T>();
list.List = CurrentDb.GetPageList(conditionalList, page);
list.PageIndex = page.PageIndex;
list.PageSize = page.PageSize;
list.TotalCount = page.TotalCount;
return list;
}
public virtual async Task<PageList<T>> GetPageListAsync(List<IConditionalModel> conditionalList, PageModel page)
{
PageList<T> list = new PageList<T>();
list.List = await CurrentDb.GetPageListAsync(conditionalList, page);
list.PageIndex = page.PageIndex;
list.PageSize = page.PageSize;
list.TotalCount = page.TotalCount;
return list;
}
public virtual PageList<T> GetPageList(List<IConditionalModel> conditionalList, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
{
PageList<T> list = new PageList<T>();
list.List = CurrentDb.GetPageList(conditionalList, page, orderByExpression, orderByType);
list.PageIndex = page.PageIndex;
list.PageSize = page.PageSize;
list.TotalCount = page.TotalCount;
return list;
}
public virtual async Task<PageList<T>> GetPageListAsync(List<IConditionalModel> conditionalList, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
{
PageList<T> list = new PageList<T>();
list.List = await CurrentDb.GetPageListAsync(conditionalList, page, orderByExpression, orderByType);
list.PageIndex = page.PageIndex;
list.PageSize = page.PageSize;
list.TotalCount = page.TotalCount;
return list;
}
/// <summary>
/// 根据id获取实体
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual T GetById(dynamic id)
{
return CurrentDb.GetById(id);
}
/// <summary>
/// 根据id获取实体-异步
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual async Task<T> GetByIdAsync(dynamic id)
{
return await CurrentDb.GetByIdAsync(id);
}
/// <summary>
/// 根据lambda获取单个对象 注意需要确保唯一如果获取到2个会报错这种场景需要使用GetFirst
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual T GetSingle(Expression<Func<T, bool>> whereExpression)
{
return CurrentDb.GetSingle(whereExpression); //Db.Queryable<T>().First(whereExpression);
}
/// <summary>
/// 根据lambda获取单个对象-异步 注意需要确保唯一如果获取到2个会报错这种场景需要使用GetFirst
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual async Task<T> GetSingleAsync(Expression<Func<T, bool>> whereExpression)
{
return await CurrentDb.GetSingleAsync(whereExpression); //await Db.Queryable<T>().FirstAsync(whereExpression);
}
/// <summary>
/// 根据lambda获取单个对象
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual T GetFirst(Expression<Func<T, bool>> whereExpression)
{
return GetDB().Queryable<T>().First(whereExpression);
}
/// <summary>
/// 根据lambda获取单个对象 --异步
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual async Task<T> GetFirstAsync(Expression<Func<T, bool>> whereExpression)
{
return await GetDB().Queryable<T>().FirstAsync(whereExpression);
}
/// <summary>
/// 实体插入
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual bool Insert(T obj)
{
return CurrentDb.Insert(obj);
}
/// <summary>
/// 实体插入-异步
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual async Task<bool> InsertAsync(T obj)
{
return await CurrentDb.InsertAsync(obj);
}
/// <summary>
/// 批量插入
/// </summary>
/// <param name="objs"></param>
/// <returns></returns>
public virtual bool InsertRange(List<T> objs)
{
return CurrentDb.InsertRange(objs);
}
/// <summary>
/// 批量插入-异步
/// </summary>
/// <param name="objs"></param>
/// <returns></returns>
public virtual async Task<bool> InsertRangeAsync(List<T> objs)
{
return await CurrentDb.InsertRangeAsync(objs);
}
/// <summary>
/// 插入返回自增列
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual int InsertReturnIdentity(T obj)
{
return CurrentDb.InsertReturnIdentity(obj);
}
/// <summary>
/// 插入返回自增列-异步
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual async Task<int> InsertReturnIdentityAsync(T obj)
{
return await CurrentDb.InsertReturnIdentityAsync(obj);
}
/// <summary>
/// 插入返回longid
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual long InsertReturnBigIdentity(T obj)
{
return CurrentDb.InsertReturnBigIdentity(obj);
}
/// <summary>
/// 插入返回longid-异步
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual async Task<long> InsertReturnBigIdentityAsync(T obj)
{
return await CurrentDb.InsertReturnBigIdentityAsync(obj);
}
/// <summary>
/// 批量删除
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
public virtual bool DeleteByIds(dynamic[] ids)
{
return CurrentDb.DeleteByIds(ids);
}
/// <summary>
/// 批量删除-异步
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
public virtual async Task<bool> DeleteByIdsAsync(dynamic[] ids)
{
return await CurrentDb.DeleteByIdsAsync(ids);
}
/// <summary>
/// 根据主键删除
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual bool Delete(dynamic id)
{
return CurrentDb.DeleteById(id);
}
/// <summary>
/// 根据主键删除-异步
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual async Task<bool> DeleteAsync(dynamic id)
{
return await CurrentDb.DeleteByIdAsync(id);
}
/// <summary>
/// 根据实体删除
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual bool Delete(T obj)
{
return CurrentDb.Delete(obj);
}
/// <summary>
/// 根据实体删除-异步
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual async Task<bool> DeleteAsync(T obj)
{
return await CurrentDb.DeleteAsync(obj);
}
/// <summary>
/// 根据表达式删除
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual bool Delete(Expression<Func<T, bool>> whereExpression)
{
return CurrentDb.Delete(whereExpression);
}
/// <summary>
/// 根据表达式删除-异步
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual async Task<bool> DeleteAsync(Expression<Func<T, bool>> whereExpression)
{
return await CurrentDb.DeleteAsync(whereExpression);
}
/// <summary>
/// 更新
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual bool Update(T obj)
{
return CurrentDb.Update(obj);
}
/// <summary>
/// 更新-异步
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public virtual async Task<bool> UpdateAsync(T obj)
{
return await CurrentDb.UpdateAsync(obj);
}
/// <summary>
/// 批量更新
/// </summary>
/// <param name="objs"></param>
/// <returns></returns>
public virtual bool UpdateRange(List<T> objs)
{
return CurrentDb.UpdateRange(objs);
}
/// <summary>
/// 批量更新-异步
/// </summary>
/// <param name="objs"></param>
/// <returns></returns>
public virtual async Task<bool> UpdateRangeAsync(List<T> objs)
{
return await CurrentDb.UpdateRangeAsync(objs);
}
/// <summary>
/// 是否包含元素
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual bool IsAny(Expression<Func<T, bool>> whereExpression)
{
return CurrentDb.IsAny(whereExpression);
}
/// <summary>
/// 是否包含元素-异步
/// </summary>
/// <param name="whereExpression"></param>
/// <returns></returns>
public virtual async Task<bool> IsAnyAsync(Expression<Func<T, bool>> whereExpression)
{
return await CurrentDb.IsAnyAsync(whereExpression);
}
#endregion
}
}

View File

@@ -0,0 +1,36 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xzy.KnowledgeBase.Domain.Options;
using Xzy.KnowledgeBase.Domain.Utils;
namespace Xzy.KnowledgeBase.Domain.Repositories.Base
{
public class SqlSugarHelper
{
/// <summary>
/// sqlserver连接
/// </summary>
public static SqlSugarScope Sqlite = new SqlSugarScope(new ConnectionConfig()
{
ConnectionString = ConnectionOption.Sqlite,
DbType = DbType.Sqlite,
InitKeyType = InitKeyType.Attribute,//从特性读取主键和自增列信息
IsAutoCloseConnection = true
}, Db =>
{
Db.Aop.OnLogExecuting = (sql, pars) =>
{
if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT").ConvertToString() == "Development")
{
Console.WriteLine(sql + "\r\n" +
Sqlite.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
Console.WriteLine();
}
};
});
}
}

View File

@@ -0,0 +1,241 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Utils
{
public static class ConvertUtils
{
/// <summary>
/// 判断是否为空为空返回true
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static bool IsNull(this object data)
{
//如果为null
if (data == null)
{
return true;
}
//如果为""
if (data.GetType() == typeof(String))
{
if (string.IsNullOrEmpty(data.ToString().Trim()))
{
return true;
}
}
return false;
}
/// <summary>
/// 判断是否为空为空返回true
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static bool IsNotNull(this object data)
{
//如果为null
if (data == null)
{
return false;
}
//如果为""
if (data.GetType() == typeof(String))
{
if (string.IsNullOrEmpty(data.ToString().Trim()))
{
return false;
}
}
return true;
}
/// <summary>
/// 判断是否为空为空返回true
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static bool IsNull(string data)
{
//如果为null
if (data == null)
{
return true;
}
//如果为""
if (data.GetType() == typeof(String))
{
if (string.IsNullOrEmpty(data.ToString().Trim()))
{
return true;
}
}
return false;
}
/// <summary>
/// 将obj类型转换为string
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string ConvertToString(this object s)
{
if (s == null)
{
return "";
}
else
{
return Convert.ToString(s);
}
}
/// <summary>
/// object 转int32
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static Int32 ConvertToInt32(this object s)
{
int i = 0;
if (s == null)
{
return 0;
}
else
{
int.TryParse(s.ToString(), out i);
}
return i;
}
/// <summary>
/// object 转int32
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static Int64 ConvertToInt64(this object s)
{
long i = 0;
if (s == null)
{
return 0;
}
else
{
long.TryParse(s.ToString(), out i);
}
return i;
}
/// <summary>
/// 将字符串转double
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static double ConvertToDouble(this object s)
{
double i = 0;
if (s == null)
{
return 0;
}
else
{
double.TryParse(s.ToString(), out i);
}
return i;
}
/// <summary>
/// 转换为datetime类型
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static DateTime ConvertToDateTime(this string s)
{
DateTime dt = new DateTime();
if (s == null || s == "")
{
return DateTime.Now;
}
DateTime.TryParse(s, out dt);
return dt;
}
/// <summary>
/// 转换为datetime类型的格式字符串
/// </summary>
/// <param name="s">要转换的对象</param>
/// <param name="y">格式化字符串</param>
/// <returns></returns>
public static string ConvertToDateTime(this string s, string y)
{
DateTime dt = new DateTime();
DateTime.TryParse(s, out dt);
return dt.ToString(y);
}
/// <summary>
/// 将字符串转换成decimal
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static decimal ConvertToDecimal(this object s)
{
decimal d = 0;
if (s == null || s == "")
{
return 0;
}
Decimal.TryParse(s.ToString(), out d);
return d;
}
/// <summary>
/// decimal保留2位小数
/// </summary>
public static decimal DecimalFraction(this decimal num)
{
return Convert.ToDecimal(num.ToString("f2"));
}
/// <summary>
/// 替换html种的特殊字符
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string ReplaceHtml(this string s)
{
return s.Replace("&lt;", "<").Replace("&gt;", ">").Replace("&amp;", "&").Replace("&quot;", "\"");
}
/// <summary>
/// 流转byte
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public static byte[] StreamToByte(this Stream stream)
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
// 设置当前流的位置为流的开始
stream.Seek(0, SeekOrigin.Begin);
return bytes;
}
public static string JsonToMarkDown(this string s)
{
return $"{Environment.NewLine}```json{Environment.NewLine}{s}{Environment.NewLine}```{Environment.NewLine}";
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Xzy.KnowledgeBase.Domain.Utils
{
public class DateTimeConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DateTime.TryParse(reader.GetString(), out var dateTime) ? dateTime : default(DateTime);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
}
}
public class DateTimeNullableConvert : JsonConverter<DateTime?>
{
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DateTime.TryParse(reader.GetString(), out var dateTime) ? dateTime : default(DateTime?);
}
public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options)
{
writer.WriteStringValue(value?.ToString("yyyy-MM-dd HH:mm:ss"));
}
}
}

View File

@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<DocumentationFile>Xzy.KnowledgeBase.Domain.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="8.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.137" />
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
<PackageReference Include="Microsoft.SemanticKernel" Version="1.2.0" />
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.2.0" />
<PackageReference Include="Microsoft.KernelMemory.Core" Version="0.26.240121.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="Domain\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,473 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Xzy.KnowledgeBase.Domain</name>
</assembly>
<members>
<member name="T:Xzy.KnowledgeBase.Domain.Common.DependencyInjection.ServiceCollectionExtensions">
<summary>
容器扩展
</summary>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Common.DependencyInjection.ServiceCollectionExtensions.AddServicesFromAssemblies(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.String[])">
<summary>
从程序集中加载类型并添加到容器中
</summary>
<param name="services">容器</param>
<param name="assemblies">程序集集合</param>
<returns></returns>
</member>
<member name="F:Xzy.KnowledgeBase.Domain.Common.DependencyInjection.ServiceLifetime.Scoped">
<summary>
作用域
</summary>
</member>
<member name="F:Xzy.KnowledgeBase.Domain.Common.DependencyInjection.ServiceLifetime.Singleton">
<summary>
单例
</summary>
</member>
<member name="F:Xzy.KnowledgeBase.Domain.Common.DependencyInjection.ServiceLifetime.Transient">
<summary>
瞬时
</summary>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Map.MapperExtend.ToDTOList``1(System.Object)">
<summary>
Entity集合转DTO集合
</summary>
<typeparam name="T"></typeparam>
<param name="value"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Map.MapperExtend.ToDTO``1(System.Object)">
<summary>
Entity转DTO
</summary>
<typeparam name="T"></typeparam>
<param name="value"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Map.MapperExtend.MapTo``1(System.Object,``0)">
<summary>
给已有对象map,适合update场景如需过滤空值需要在AutoMapProfile 设置
</summary>
<typeparam name="T"></typeparam>
<param name="self"></param>
<param name="result"></param>
<returns></returns>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Model.PageList`1.PageIndex">
<summary>
当前页从1开始
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Model.PageList`1.PageSize">
<summary>
每页数量
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Model.PageList`1.TotalCount">
<summary>
总数
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Options.ConnectionOption.Sqlite">
<summary>
sqlite连接字符串
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Repositories.Apps.Name">
<summary>
名称
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Repositories.Apps.Describe">
<summary>
描述
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Repositories.KmsDetails.FileName">
<summary>
文件名称
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Repositories.KmsDetails.DataCount">
<summary>
数据数量
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Repositories.KmsDetails.Status">
<summary>
状态
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Repositories.KmsDetails.CreateTime">
<summary>
创建时间
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Repositories.Kmss.Name">
<summary>
名称
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Repositories.Kmss.ChatModel">
<summary>
会话模型
</summary>
</member>
<member name="P:Xzy.KnowledgeBase.Domain.Repositories.Kmss.EmbeddingModel">
<summary>
向量模型
</summary>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetList">
<summary>
获取所有list
</summary>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetListAsync">
<summary>
获取所有list-异步
</summary>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetList(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据lambda查询
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetListAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据lambda查询-异步
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.Count(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据lambda表达式获取数量
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.CountAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据lambda表达式获取数量-异步
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetPageList(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}},SqlSugar.PageModel)">
<summary>
获取分页
</summary>
<param name="whereExpression"></param>
<param name="page"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetPageListAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}},SqlSugar.PageModel)">
<summary>
获取分页-异步
</summary>
<param name="whereExpression"></param>
<param name="page"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetById(System.Object)">
<summary>
根据id获取实体
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetByIdAsync(System.Object)">
<summary>
根据id获取实体-异步
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetSingle(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据lambda获取单个对象 注意需要确保唯一如果获取到2个会报错这种场景需要使用GetFirst
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetSingleAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据lambda获取单个对象-异步 注意需要确保唯一如果获取到2个会报错这种场景需要使用GetFirst
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetFirst(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据lambda获取单个对象
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.GetFirstAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据lambda获取单个对象 --异步
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.Insert(`0)">
<summary>
实体插入
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.InsertAsync(`0)">
<summary>
实体插入-异步
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.InsertRange(System.Collections.Generic.List{`0})">
<summary>
批量插入
</summary>
<param name="objs"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.InsertRangeAsync(System.Collections.Generic.List{`0})">
<summary>
批量插入-异步
</summary>
<param name="objs"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.InsertReturnIdentity(`0)">
<summary>
插入返回自增列
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.InsertReturnIdentityAsync(`0)">
<summary>
插入返回自增列-异步
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.InsertReturnBigIdentity(`0)">
<summary>
插入返回longid
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.InsertReturnBigIdentityAsync(`0)">
<summary>
插入返回longid-异步
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.DeleteByIds(System.Object[])">
<summary>
批量删除
</summary>
<param name="ids"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.DeleteByIdsAsync(System.Object[])">
<summary>
批量删除-异步
</summary>
<param name="ids"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.Delete(System.Object)">
<summary>
根据主键删除
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.DeleteAsync(System.Object)">
<summary>
根据主键删除-异步
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.Delete(`0)">
<summary>
根据实体删除
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.DeleteAsync(`0)">
<summary>
根据实体删除-异步
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.Delete(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据表达式删除
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.DeleteAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据表达式删除-异步
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.Update(`0)">
<summary>
更新
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.UpdateAsync(`0)">
<summary>
更新-异步
</summary>
<param name="obj"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.UpdateRange(System.Collections.Generic.List{`0})">
<summary>
批量更新
</summary>
<param name="objs"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.UpdateRangeAsync(System.Collections.Generic.List{`0})">
<summary>
批量更新-异步
</summary>
<param name="objs"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.IsAny(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
是否包含元素
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Repositories.Base.Repository`1.IsAnyAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
是否包含元素-异步
</summary>
<param name="whereExpression"></param>
<returns></returns>
</member>
<member name="F:Xzy.KnowledgeBase.Domain.Repositories.Base.SqlSugarHelper.Sqlite">
<summary>
sqlserver连接
</summary>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.IsNull(System.Object)">
<summary>
判断是否为空为空返回true
</summary>
<param name="data"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.IsNotNull(System.Object)">
<summary>
判断是否为空为空返回true
</summary>
<param name="data"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.IsNull(System.String)">
<summary>
判断是否为空为空返回true
</summary>
<param name="data"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.ConvertToString(System.Object)">
<summary>
将obj类型转换为string
</summary>
<param name="s"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.ConvertToInt32(System.Object)">
<summary>
object 转int32
</summary>
<param name="s"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.ConvertToInt64(System.Object)">
<summary>
object 转int32
</summary>
<param name="s"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.ConvertToDouble(System.Object)">
<summary>
将字符串转double
</summary>
<param name="s"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.ConvertToDateTime(System.String)">
<summary>
转换为datetime类型
</summary>
<param name="s"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.ConvertToDateTime(System.String,System.String)">
<summary>
转换为datetime类型的格式字符串
</summary>
<param name="s">要转换的对象</param>
<param name="y">格式化字符串</param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.ConvertToDecimal(System.Object)">
<summary>
将字符串转换成decimal
</summary>
<param name="s"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.DecimalFraction(System.Decimal)">
<summary>
decimal保留2位小数
</summary>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.ReplaceHtml(System.String)">
<summary>
替换html种的特殊字符
</summary>
<param name="s"></param>
<returns></returns>
</member>
<member name="M:Xzy.KnowledgeBase.Domain.Utils.ConvertUtils.StreamToByte(System.IO.Stream)">
<summary>
流转byte
</summary>
<param name="stream"></param>
<returns></returns>
</member>
</members>
</doc>

36
Xzy.KnowledgeBase.sln Normal file
View File

@@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xzy.KnowledgeBase", "Xzy.KnowledgeBase\Xzy.KnowledgeBase.csproj", "{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xzy.KnowledgeBase.Domain", "Xzy.KnowledgeBase.Domain\Xzy.KnowledgeBase.Domain.csproj", "{64F17C9A-97C2-46FA-9345-86C5289288AD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docker", "Docker", "{9F2E193A-5F9D-4C82-B591-CB133EEB59F0}"
ProjectSection(SolutionItems) = preProject
Dockerfile = Dockerfile
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9AA5A735-8FB1-4CC5-AB3E-D02B3A3B6682}.Release|Any CPU.Build.0 = Release|Any CPU
{64F17C9A-97C2-46FA-9345-86C5289288AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{64F17C9A-97C2-46FA-9345-86C5289288AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64F17C9A-97C2-46FA-9345-86C5289288AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{64F17C9A-97C2-46FA-9345-86C5289288AD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2076B7C9-2E5B-4580-9712-03F0D56BC1AF}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,13 @@
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<CascadingValue Value="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(BasicLayout)" />
</CascadingValue>
</Found>
<NotFound>
<LayoutView Layout="@typeof(BasicLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
<AntContainer />

View File

@@ -0,0 +1,52 @@
@namespace Xzy.KnowledgeBase.Components
@inherits AntDomComponentBase
<Space Class="@ClassMapper.Class" Size="@("24")">
<SpaceItem>
<HeaderSearch Class="action search"
Placeholder="Site Search"
DefaultValue="umi ui"
Options="DefaultOptions" />
</SpaceItem>
<SpaceItem>
<AntDesign.Tooltip Title="@("Help")" Placement="@Placement.Bottom">
<Unbound>
<span @ref="@context.Current" class="action">
<Icon Type="question-circle" Theme="outline" />
</span>
</Unbound>
</AntDesign.Tooltip>
</SpaceItem>
<SpaceItem>
<NoticeIcon ClearText="Empty"
ViewMoreText="see more"
Count="_count"
OnClear="HandleClear"
OnViewMore="HandleViewMore">
<NoticeList TabKey="notification"
Title="Notifications"
EmptyText="You have viewed all notifications"
ShowViewMore
Data="_notifications" />
<NoticeList TabKey="message"
Title="Messages"
EmptyText="You have read all messages"
ShowViewMore
Data="_messages" />
<NoticeList TabKey="event"
Title="Upcoming"
EmptyText="You have completed all to do"
ShowViewMore
Data="_events" />
</NoticeIcon>
</SpaceItem>
<SpaceItem>
<AvatarDropdown Name="@_currentUser.Name"
Avatar="@_currentUser.Avatar"
MenuItems="@AvatarMenuItems"
OnItemSelected="HandleSelectUser" />
</SpaceItem>
<SpaceItem>
<SelectLang OnItemSelected="HandleSelectLang" />
</SpaceItem>
</Space>

View File

@@ -0,0 +1,114 @@
using AntDesign;
using AntDesign.ProLayout;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xzy.KnowledgeBase.Models;
using Xzy.KnowledgeBase.Services;
namespace Xzy.KnowledgeBase.Components
{
public partial class RightContent
{
private CurrentUser _currentUser = new CurrentUser();
private NoticeIconData[] _notifications = { };
private NoticeIconData[] _messages = { };
private NoticeIconData[] _events = { };
private int _count = 0;
private List<AutoCompleteDataItem<string>> DefaultOptions { get; set; } = new List<AutoCompleteDataItem<string>>
{
new AutoCompleteDataItem<string>
{
Label = "umi ui",
Value = "umi ui"
},
new AutoCompleteDataItem<string>
{
Label = "Pro Table",
Value = "Pro Table"
},
new AutoCompleteDataItem<string>
{
Label = "Pro Layout",
Value = "Pro Layout"
}
};
public AvatarMenuItem[] AvatarMenuItems { get; set; } = new AvatarMenuItem[]
{
new() { Key = "center", IconType = "user", Option = "个人中心"},
new() { Key = "setting", IconType = "setting", Option = "个人设置"},
new() { IsDivider = true },
new() { Key = "logout", IconType = "logout", Option = "退出登录"}
};
[Inject] protected NavigationManager NavigationManager { get; set; }
[Inject] protected IUserService UserService { get; set; }
[Inject] protected IProjectService ProjectService { get; set; }
[Inject] protected MessageService MessageService { get; set; }
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
SetClassMap();
_currentUser = await UserService.GetCurrentUserAsync();
var notices = await ProjectService.GetNoticesAsync();
_notifications = notices.Where(x => x.Type == "notification").Cast<NoticeIconData>().ToArray();
_messages = notices.Where(x => x.Type == "message").Cast<NoticeIconData>().ToArray();
_events = notices.Where(x => x.Type == "event").Cast<NoticeIconData>().ToArray();
_count = notices.Length;
}
protected void SetClassMap()
{
ClassMapper
.Clear()
.Add("right");
}
public void HandleSelectUser(MenuItem item)
{
switch (item.Key)
{
case "center":
NavigationManager.NavigateTo("/account/center");
break;
case "setting":
NavigationManager.NavigateTo("/account/settings");
break;
case "logout":
NavigationManager.NavigateTo("/user/login");
break;
}
}
public void HandleSelectLang(MenuItem item)
{
}
public async Task HandleClear(string key)
{
switch (key)
{
case "notification":
_notifications = new NoticeIconData[] { };
break;
case "message":
_messages = new NoticeIconData[] { };
break;
case "event":
_events = new NoticeIconData[] { };
break;
}
await MessageService.Success($"清空了{key}");
}
public async Task HandleViewMore(string key)
{
await MessageService.Info("Click on view more");
}
}
}

View File

@@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Xzy.KnowledgeBase.Domain.Repositories;
namespace Xzy.KnowledgeBase.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class InitController : ControllerBase
{
private readonly IApps_Repositories _repository;
public InitController(IApps_Repositories repository)
{
_repository = repository;
}
/// <summary>
/// 初始化DB 和表
/// </summary>
/// <returns></returns>
[HttpPost]
public IActionResult InitTable()
{
_repository.GetDB().DbMaintenance.CreateDatabase();
_repository.GetDB().CodeFirst.InitTables(typeof(Apps));
_repository.GetDB().CodeFirst.InitTables(typeof(Kmss));
_repository.GetDB().CodeFirst.InitTables(typeof(KmsDetails));
return Ok();
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
namespace Xzy.KnowledgeBase
{
public static class DateTimeExtension
{
private const int Second = 1;
private const int Minute = 60 * Second;
private const int Hour = 60 * Minute;
private const int Day = 24 * Hour;
private const int Month = 30 * Day;
// todo: Need to be localized
public static string ToFriendlyDisplay(this DateTime dateTime)
{
var ts = DateTime.Now - dateTime;
var delta = ts.TotalSeconds;
if (delta < 0)
{
return "not yet";
}
if (delta < 1 * Minute)
{
return ts.Seconds == 1 ? "1 second ago" : ts.Seconds + " seconds ago";
}
if (delta < 2 * Minute)
{
return "1 minute ago";
}
if (delta < 45 * Minute)
{
return ts.Minutes + "minute";
}
if (delta < 90 * Minute)
{
return "1 hour ago";
}
if (delta < 24 * Hour)
{
return ts.Hours + " hours ago";
}
if (delta < 48 * Hour)
{
return "yesterday";
}
if (delta < 30 * Day)
{
return ts.Days + " days ago";
}
if (delta < 12 * Month)
{
var months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
return months <= 1 ? "A month ago" : months + " months ago";
}
else
{
var years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
return years <= 1 ? "a year ago" : years + " years ago";
}
}
}
}

View File

@@ -0,0 +1,56 @@
@namespace Xzy.KnowledgeBase
@inherits LayoutComponentBase
<AntDesign.ProLayout.BasicLayout
Logo="@("https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg")"
MenuData="_menuData">
<RightContentRender>
<Xzy.KnowledgeBase.Components.RightContent />
</RightContentRender>
<ChildContent>
@Body
</ChildContent>
<FooterRender>
<FooterView Copyright="2021 Ant Design Blazor" Links="Links"></FooterView>
</FooterRender>
</AntDesign.ProLayout.BasicLayout>
<SettingDrawer />
@code
{
private MenuDataItem[] _menuData = { };
[Inject] public HttpClient HttpClient { get; set; }
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
_menuData = await HttpClient.GetFromJsonAsync<MenuDataItem[]>("data/menu.json");
}
public LinkItem[] Links { get; set; } =
{
new LinkItem
{
Key = "Ant Design Blazor",
Title = "Ant Design Blazor",
Href = "https://antblazor.com",
BlankTarget = true,
},
new LinkItem
{
Key = "github",
Title = (RenderFragment)(@<Icon Type="github" />),
Href = "https://github.com/ant-design-blazor/ant-design-pro-blazor",
BlankTarget = true,
},
new LinkItem
{
Key = "Blazor",
Title = "Blazor",
Href = "https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor?WT.mc_id=DT-MVP-5003987",
BlankTarget = true,
}
};
}

View File

@@ -0,0 +1,50 @@
@namespace Xzy.KnowledgeBase
@using OneOf
@inherits LayoutComponentBase
<div class="container__b__0">
<div class="lang">
<!--todo: selectLang-->
</div>
<div class="content">
<div class="top">
<div class="header">
<a>
<img alt="logo" class="logo" src="assets/logo.svg" />
<span class="title">Ant Design</span>
</a>
</div>
<div class="desc">Ant Design Blazor</div>
</div>
@Body
</div>
<FooterView Copyright="2021 Ant Design Blazor" Links="Links"></FooterView>
</div>
@code
{
public LinkItem[] Links { get; set; } =
{
new LinkItem
{
Key = "Ant Design Blazor",
Title = "Ant Design Blazor",
Href = "https://antblazor.com",
BlankTarget = true,
},
new LinkItem
{
Key = "github",
Title = (RenderFragment)(@<Icon Type="github" />),
Href = "https://github.com/ant-design-blazor/ant-design-pro-blazor",
BlankTarget = true,
},
new LinkItem
{
Key = "Blazor",
Title = "Blazor",
Href = "https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor?WT.mc_id=DT-MVP-5003987",
BlankTarget = true,
}
};
}

View File

@@ -0,0 +1,64 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.container__b__0 {
display: flex;
flex-direction: column;
height: 100vh;
overflow: auto;
background: #f0f2f5;
}
.container__b__0 .lang {
width: 100%;
height: 40px;
line-height: 44px;
text-align: right;
}
.container__b__0 .lang :global(.ant-dropdown-trigger) {
margin-right: 24px;
}
.container__b__0 .content {
flex: 1;
padding: 32px 0;
}
.container__b__0 .top {
text-align: center;
}
.container__b__0 .header {
height: 44px;
line-height: 44px;
}
.container__b__0 .header a {
text-decoration: none;
}
.container__b__0 .logo {
height: 44px;
margin-right: 16px;
vertical-align: top;
}
.container__b__0 .title {
position: relative;
top: 2px;
color: rgba(0, 0, 0, 0.85);
font-weight: 600;
font-size: 33px;
font-family: Avenir, 'Helvetica Neue', Arial, Helvetica, sans-serif;
}
.container__b__0 .desc {
margin-top: 12px;
margin-bottom: 40px;
color: rgba(0, 0, 0, 0.45);
font-size: 14px;
}
@media (min-width: 768px) {
.container__b__0 {
background-image: url('https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg');
background-repeat: no-repeat;
background-position: center 110px;
background-size: 100%;
}
.container__b__0 .content {
padding: 32px 0 24px;
}
}

View File

@@ -0,0 +1,14 @@
using System;
namespace Xzy.KnowledgeBase.Models
{
public class ActivitiesType
{
public string Id { get; set; }
public DateTime UpdatedAt { get; set; }
public ActivityUser User { get; set; }
public ActivityGroup Group { get; set; }
public ActivityProject Project { get; set; }
public string Template { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace Xzy.KnowledgeBase.Models
{
public class ActivityGroup
{
public string Name { get; set; }
public string Link { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace Xzy.KnowledgeBase.Models
{
public class ActivityProject
{
public string Name { get; set; }
public string Link { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace Xzy.KnowledgeBase.Models
{
public class ActivityUser
{
public string Name { get; set; }
public string Avatar { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
namespace Xzy.KnowledgeBase.Models
{
public class AdvancedOperation
{
public string Key { get; set; }
public string Type { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public string UpdatedAt { get; set; }
public string Memo { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
namespace Xzy.KnowledgeBase.Models
{
public class AdvancedProfileData
{
public AdvancedOperation[] AdvancedOperation1 { get; set; }
public AdvancedOperation[] AdvancedOperation2 { get; set; }
public AdvancedOperation[] AdvancedOperation3 { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
namespace Xzy.KnowledgeBase.Models
{
public class BasicGood
{
public string Id { get; set; }
public string Name { get; set; }
public string Barcode { get; set; }
public string Price { get; set; }
public string Num { get; set; }
public string Amount { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace Xzy.KnowledgeBase.Models
{
public class BasicProfileDataType
{
public BasicGood[] BasicGoods { get; set; }
public BasicProgress[] BasicProgress { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
namespace Xzy.KnowledgeBase.Models
{
public class BasicProgress
{
public string Key { get; set; }
public string Time { get; set; }
public string Rate { get; set; }
public string Status { get; set; }
public string Operator { get; set; }
public string Cost { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
namespace Xzy.KnowledgeBase.Models
{
public class ChartData
{
public ChartDataItem[] VisitData { get; set; }
public ChartDataItem[] VisitData2 { get; set; }
public ChartDataItem[] SalesData { get; set; }
public SearchDataItem[] SearchData { get; set; }
public OfflineDataItem[] OfflineData { get; set; }
public OfflineChartDataItem[] OfflineChartData { get; set; }
public ChartDataItem[] SalesTypeData { get; set; }
public ChartDataItem[] SalesTypeDataOnline { get; set; }
public ChartDataItem[] SalesTypeDataOffline { get; set; }
public RadarDataItem[] RadarData { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace Xzy.KnowledgeBase.Models
{
public class ChartDataItem
{
public string X { get; set; }
public int Y { get; set; }
}
}

View File

@@ -0,0 +1,40 @@
namespace Xzy.KnowledgeBase.Models
{
public class TagType
{
public string Key { get; set; }
public string Label { get; set; }
}
public class GeographicType
{
public TagType Province { get; set; }
public TagType City { get; set; }
}
public class CurrentUser
{
public string Name { get; set; }
public string Avatar { get; set; }
public string Userid { get; set; }
public NoticeType[] Notice { get; set; } = { };
public string Email { get; set; }
public string Signature { get; set; }
public string Title { get; set; }
public string Group { get; set; }
public TagType[] Tags { get; set; } = { };
public int NotifyCount { get; set; }
public int UnreadCount { get; set; }
public string Country { get; set; }
public GeographicType Geographic { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
public class UserLiteItem
{
public string Avater { get; set; }
public string Title { get; set; }
public string Description { get; set; }
}
}

View File

@@ -0,0 +1,48 @@
using System;
namespace Xzy.KnowledgeBase.Models
{
public class StepFormModel
{
public string ReceiverAccountType { get; set; } = "ant-design@alipay.com";
public string ReceiverAccount { get; set; } = "test@example.com";
public string ReceiverName { get; set; } = "Alex";
public string PayAccount { get; set; }
public string Password { get; set; } = "500";
public string Amount { get; set; } = "12345678";
}
public class AdvancedFormModel
{
public string Name { get; set; }
public string Url { get; set; }
public string Owner { get; set; }
public string Approver { get; set; }
public DateTime?[] DateRange { get; set; }
public string Type { get; set; }
public string Name2 { get; set; }
public string Url2 { get; set; }
public string Owner2 { get; set; }
public string Approver2 { get; set; }
public DateTime? DateRange2 { get; set; }
public string Type2 { get; set; }
}
public class BasicFormModel
{
public string Title { get; set; }
public string Client { get; set; }
public string Invites { get; set; }
public int Disclosure { get; set; }
public int Weight { get; set; }
public string Standard { get; set; }
public string Goal { get; set; }
public DateTime?[] DateRange { get; set; }
}
public class Owner
{
public string Id { get; set; }
public string Name { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
namespace Xzy.KnowledgeBase.Models
{
public class ListFormModel
{
public string Owner { get; set; } = "wzj";
public string ActiveUser { get; set; }
public string Satisfaction { get; set; }
}
public class BasicListFormModel
{
public string Status { get; set; } = "all";
public string SearchKeyword { get; set; }
}
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Text.Json.Serialization;
using Xzy.KnowledgeBase.Utils;
namespace Xzy.KnowledgeBase.Models
{
public class Member
{
public string Avatar { get; set; }
public string Name { get; set; }
public string Id { get; set; }
}
public class ListItemDataType
{
public string Id { get; set; }
public string Owner { get; set; }
public string Title { get; set; }
public string Avatar { get; set; }
public string Cover { get; set; }
public string Status { get; set; }
public int Percent { get; set; }
public string Logo { get; set; }
public string Href { get; set; }
public string Body { get; set; }
public string SubDescription { get; set; }
public string Description { get; set; }
public int ActiveUser { get; set; }
public int NewUser { get; set; }
public int Star { get; set; }
public int Like { get; set; }
public int Message { get; set; }
public string Content { get; set; }
public Member[] Members { get; set; }
[JsonConverter(typeof(LongToDateTimeConverter))]
public DateTime UpdatedAt { get; set; }
[JsonConverter(typeof(LongToDateTimeConverter))]
public DateTime CreatedAt { get; set; }
}
}

View File

@@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
namespace Xzy.KnowledgeBase.Models
{
public class LoginParamsType
{
[Required] public string UserName { get; set; }
[Required] public string Password { get; set; }
public string Mobile { get; set; }
public string Captcha { get; set; }
public string LoginType { get; set; }
public bool AutoLogin { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
using AntDesign.ProLayout;
namespace Xzy.KnowledgeBase.Models
{
public class NoticeItem : NoticeIconData
{
public string Id { get; set; }
public string Type { get; set; }
public string Status { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
namespace Xzy.KnowledgeBase.Models
{
public class NoticeType
{
public string Id { get; set; }
public string Title { get; set; }
public string Logo { get; set; }
public string Description { get; set; }
public string UpdatedAt { get; set; }
public string Member { get; set; }
public string Href { get; set; }
public string MemberLink { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
namespace Xzy.KnowledgeBase.Models
{
public class OfflineChartDataItem
{
public long X { get; set; }
public int Y1 { get; set; }
public int Y2 { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace Xzy.KnowledgeBase.Models
{
public class OfflineDataItem
{
public string Name { get; set; }
public float Cvr { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
namespace Xzy.KnowledgeBase.Models
{
public class RadarDataItem
{
public string Name { get; set; }
public string Label { get; set; }
public int Value { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
namespace Xzy.KnowledgeBase.Models
{
public class SearchDataItem
{
public int Index { get; set; }
public string Keywod { get; set; }
public int Count { get; set; }
public int Range { get; set; }
public int Status { get; set; }
}
}

View File

@@ -0,0 +1,59 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Center
<AntList TItem="ListItemDataType"
Class="filterCardList"
Grid="_listGridType"
DataSource="List">
<ListItem NoFlex>
<Card Bordered
Hoverable
BodyStyle="padding-bottom: 20px;"
Actions="Actions">
<CardMeta>
<AvatarTemplate>
<Avatar Size="small" Src="@context.Avatar" />
</AvatarTemplate>
<TitleTemplate>@context.Title</TitleTemplate>
</CardMeta>
<div class="cardItemContent">
<div class="cardInfo">
<div>
<p>Active User</p>
<p>@FormatWan(context.ActiveUser)</p>
</div>
<div>
<p>New Users</p>
<p>@context.NewUser.ToString("0,0")</p>
</div>
</div>
</div>
</Card>
</ListItem>
</AntList>
@code
{
private static readonly RenderFragment Download =@<AntDesign.Tooltip Title="@("下载")">
<Icon Type="download" Theme="outline" />
</AntDesign.Tooltip>;
private static readonly IList<RenderFragment> Actions = new List<RenderFragment>
{
Download,
@<AntDesign.Tooltip Title="@("Edit")"><Icon Type="edit" Theme="outline" /></AntDesign.Tooltip>,
@<AntDesign.Tooltip Title="@("Share")"><Icon Type="share-alt" Theme="outline" /></AntDesign.Tooltip>,
@<Dropdown><Icon Type="ellipsis" Theme="outline" /></Dropdown>
};
private static RenderFragment FormatWan(int val) {
if (val > 10000) {
val = (int) Math.Floor((double) val / 10000);
}
return @<span>
@val
<span style="position: relative; top: -2px; font-size: 14px; font-style: normal; margin-left: 2px;">万</span>
</span>;
}
}

View File

@@ -0,0 +1,18 @@
using AntDesign;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Xzy.KnowledgeBase.Models;
namespace Xzy.KnowledgeBase.Pages.Account.Center
{
public partial class Applications
{
private readonly ListGridType _listGridType = new ListGridType
{
Gutter = 24,
Column = 4
};
[Parameter] public IList<ListItemDataType> List { get; set; }
}
}

View File

@@ -0,0 +1,49 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.filterCardList {
margin-bottom: -24px;
}
.filterCardList :global .ant-card-meta-content {
margin-top: 0;
}
.filterCardList :global .ant-card-meta-avatar {
font-size: 0;
}
.filterCardList :global .ant-list .ant-list-item-content-single {
max-width: 100%;
}
.filterCardList .cardInfo {
margin-top: 16px;
margin-left: 40px;
zoom: 1;
}
.filterCardList .cardInfo::before,
.filterCardList .cardInfo::after {
display: table;
content: ' ';
}
.filterCardList .cardInfo::after {
clear: both;
height: 0;
font-size: 0;
visibility: hidden;
}
.filterCardList .cardInfo > div {
position: relative;
float: left;
width: 50%;
text-align: left;
}
.filterCardList .cardInfo > div p {
margin: 0;
font-size: 24px;
line-height: 32px;
}
.filterCardList .cardInfo > div p:first-child {
margin-bottom: 4px;
color: rgba(0, 0, 0, 0.45);
font-size: 12px;
line-height: 20px;
}

View File

@@ -0,0 +1,16 @@
@using Xzy.KnowledgeBase.Models
@namespace Xzy.KnowledgeBase.Pages.Account.Center
<div class="listContent">
<div class="description">@Data.Content</div>
<div class="extra">
<Avatar Src="@Data.Avatar" Size="small" />
<a href="@Data.Href">@Data.Owner</a> Posted on <a href="@Data.Href">@Data.Href</a>
<em>@Data.UpdatedAt.ToString("yyyy-MM-dd HH:mm:ss")</em>
</div>
</div>
@code
{
[Parameter] public ListItemDataType Data { get; set; }
}

View File

@@ -0,0 +1,33 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.listContent .description {
max-width: 720px;
line-height: 22px;
}
.listContent .extra {
margin-top: 16px;
color: rgba(0, 0, 0, 0.45);
line-height: 22px;
}
.listContent .extra > :global(.ant-avatar) {
position: relative;
top: 1px;
width: 20px;
height: 20px;
margin-right: 8px;
vertical-align: top;
}
.listContent .extra > em {
margin-left: 16px;
color: rgba(0, 0, 0, 0.25);
font-style: normal;
}
@media screen and (max-width: 480px) {
.listContent .extra > em {
display: block;
margin-top: 8px;
margin-left: 0;
}
}

View File

@@ -0,0 +1,16 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Center
<AntList
TItem="ListItemDataType"
Size="large"
Class="articleList"
DataSource="List">
<ListItem NoFlex>
<ListItemMeta Description="">
<TitleTemplate>
<a href="https://ng.ant.design">@context.Title</a>
</TitleTemplate>
</ListItemMeta>
<ArticleListContent Data="@context" />
</ListItem>
</AntList>

View File

@@ -0,0 +1,11 @@
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Xzy.KnowledgeBase.Models;
namespace Xzy.KnowledgeBase.Pages.Account.Center
{
public partial class Articles
{
[Parameter] public IList<ListItemDataType> List { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.articleList :global .ant-list-item:first-child {
padding-top: 0;
}
a.listItemMetaTitle {
color: rgba(0, 0, 0, 0.85);
}

View File

@@ -0,0 +1,7 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Center
<div class="avatarList">
<ul>
@ChildContent
</ul>
</div>

View File

@@ -0,0 +1,9 @@
using Microsoft.AspNetCore.Components;
namespace Xzy.KnowledgeBase.Pages.Account.Center
{
public partial class AvatarList
{
[Parameter] public RenderFragment ChildContent { get; set; }
}
}

View File

@@ -0,0 +1,43 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.avatarList {
display: inline-block;
}
.avatarList ul {
display: inline-block;
margin-left: 8px;
font-size: 0;
}
.avatarItem {
display: inline-block;
width: 32px;
height: 32px;
margin-left: -8px;
font-size: 14px;
}
.avatarItem :global .ant-avatar {
border: 1px solid #d9d9d9;
}
.avatarItemLarge {
width: 40px;
height: 40px;
}
.avatarItemSmall {
width: 24px;
height: 24px;
}
.avatarItemMini {
width: 20px;
height: 20px;
}
.avatarItemMini :global .ant-avatar {
width: 20px;
height: 20px;
line-height: 20px;
}
.avatarItemMini :global .ant-avatar .ant-avatar-string {
font-size: 12px;
line-height: 18px;
}

View File

@@ -0,0 +1,17 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Center
@inherits AntDomComponentBase
<li class="@ClassMapper.Class" @onclick="OnClick">
@if (string.IsNullOrEmpty(Tips))
{
<AntDesign.Tooltip Title="@Tips">
<Unbound>
<Avatar Src="@Src" Size="@Size" Style="cursor: pointer;" RefBack="@context"/>
</Unbound>
</AntDesign.Tooltip>
}
else
{
<Avatar Src="@Src" Size="@Size" />
}
</li>

View File

@@ -0,0 +1,28 @@
using Microsoft.AspNetCore.Components;
namespace Xzy.KnowledgeBase.Pages.Account.Center
{
public partial class AvatarListItem
{
[Parameter] public string Size { get; set; }
[Parameter] public string Tips { get; set; }
[Parameter] public string Src { get; set; }
[Parameter] public EventCallback OnClick { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
SetClassMap();
}
protected void SetClassMap()
{
ClassMapper
.Clear()
.Add("avatarItem")
.If("avatarItemLarge", () => Size == "large")
.If("avatarItemSmall", () => Size == "small")
.If("avatarItemMini", () => Size == "mini");
}
}
}

View File

@@ -0,0 +1,35 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Center
<AntList
TItem="ListItemDataType"
Class="coverCardList"
Grid="_listGridType"
DataSource="List">
<ListItem NoFlex>
<Card Class="card" Hoverable Bordered>
<Cover>
<img alt="@context.Title" src="@context.Cover"/>
</Cover>
<ChildContent>
<CardMeta>
<DescriptionTemplate>@context.SubDescription</DescriptionTemplate>
<TitleTemplate><a>@context.Title</a></TitleTemplate>
</CardMeta>
<div class="cardItemContent">
<span>@context.UpdatedAt.ToFriendlyDisplay()</span>
<div class="avatarList">
<AvatarList>
@foreach (var member in context.Members)
{
<AvatarListItem
Size="small"
Src="@member.Avatar"
Tips="@member.Name"/>
}
</AvatarList>
</div>
</div>
</ChildContent>
</Card>
</ListItem>
</AntList>

View File

@@ -0,0 +1,19 @@
using AntDesign;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Xzy.KnowledgeBase.Models;
namespace Xzy.KnowledgeBase.Pages.Account.Center
{
public partial class Projects
{
private readonly ListGridType _listGridType = new ListGridType
{
Gutter = 24,
Column = 4
};
[Parameter]
public IList<ListItemDataType> List { get; set; }
}
}

View File

@@ -0,0 +1,41 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.coverCardList .card .ant-card-meta-title {
margin-bottom: 4px;
}
.coverCardList .card .ant-card-meta-title > a {
display: inline-block;
max-width: 100%;
color: rgba(0, 0, 0, 0.85);
}
.coverCardList .card .ant-card-meta-description {
height: 44px;
overflow: hidden;
line-height: 22px;
}
.coverCardList .card:hover .ant-card-meta-title > a {
color: #1890ff;
}
.coverCardList .cardItemContent {
display: flex;
height: 20px;
margin-top: 16px;
margin-bottom: -4px;
line-height: 20px;
}
.coverCardList .cardItemContent > span {
flex: 1;
color: rgba(0, 0, 0, 0.45);
font-size: 12px;
}
.coverCardList .cardItemContent .avatarList {
flex: 0 1 auto;
}
.coverCardList .cardList {
margin-top: 24px;
}
.coverCardList .ant-list .ant-list-item-content-single {
max-width: 100%;
}

View File

@@ -0,0 +1,88 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Center
@page "/account/center"
<GridContent>
<Row Gutter="24">
<AntDesign.Col Lg="7" Md="24">
<Card Style="margin-bottom: 24px;">
<div class="avatarHolder">
<img alt="" src="@_currentUser.Avatar" />
<div className="name">@_currentUser.Name</div>
<div>@_currentUser.Signature</div>
</div>
<div class="detail">
<p>
<Icon Type="contacts" Theme="outline" Style="margin-right:8px;" />
@_currentUser.Title
</p>
<p>
<Icon Type="cluster" Theme="outline" Style="margin-right:8px;" />
@_currentUser.Group
</p>
<p>
<Icon Type="home" Theme="outline" Style="margin-right:8px;" />
<!--todo: add userinfo-->
@_currentUser.Geographic.Province.Label
@_currentUser.Geographic.City.Label
</p>
</div>
<Divider Dashed />
<div class="tags">
<div class="tagsTitle">Tags</div>
@foreach (var tag in _currentUser.Tags) {
<Tag>@tag.Label</Tag>
}
@if (_inputVisible) {
<AntDesign.Input Type="text"
Size="small"
Style="width: 78px"
@bind-Value="InputValue"
OnBlur="HandleInputConfirm" />
}
else {
<Tag OnClick="ShowInput" Style="border-style: dashed">
<Icon Type="plus" Theme="outline" />
</Tag>
}
</div>
<Divider Dashed Style="margin-top: 16px;" />
<div class="team">
<div class="teamTitle">Team</div>
<!--todo: add notice-->
</div>
</Card>
</AntDesign.Col>
<AntDesign.Col Lg="17" Md="24">
<Card Class="tabsCard">
<CardTabs>
<Tabs DefaultActiveKey="1">
<TabPane Key="1">
<TabTemplate>Articles (@_fakeList.Count)</TabTemplate>
<ChildContent>
<Articles List="_fakeList" />
</ChildContent>
</TabPane>
<TabPane Key="2">
<TabTemplate>Applications (@_fakeList.Count)</TabTemplate>
<ChildContent>
<Applications List="_fakeList" />
</ChildContent>
</TabPane>
<TabPane Key="3">
<TabTemplate>Projects (@_fakeList.Count)</TabTemplate>
<ChildContent>
<Projects List="_fakeList" />
</ChildContent>
</TabPane>
</Tabs>
</CardTabs>
</Card>
</AntDesign.Col>
</Row>
</GridContent>

View File

@@ -0,0 +1,40 @@
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xzy.KnowledgeBase.Models;
using Xzy.KnowledgeBase.Services;
namespace Xzy.KnowledgeBase.Pages.Account.Center
{
public partial class Index
{
private CurrentUser _currentUser = new CurrentUser
{
Geographic = new GeographicType { City = new TagType(), Province = new TagType() }
};
private IList<ListItemDataType> _fakeList = new List<ListItemDataType>();
private bool _inputVisible;
public string InputValue { get; set; }
[Inject] public IProjectService ProjectService { get; set; }
[Inject] public IUserService UserService { get; set; }
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
_currentUser = await UserService.GetCurrentUserAsync();
_fakeList = await ProjectService.GetFakeListAsync();
}
protected void ShowInput()
{
_inputVisible = true;
}
protected void HandleInputConfirm()
{
_inputVisible = false;
}
}
}

View File

@@ -0,0 +1,63 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.avatarHolder {
margin-bottom: 24px;
text-align: center;
}
.avatarHolder > img {
width: 104px;
height: 104px;
margin-bottom: 20px;
}
.avatarHolder .name {
margin-bottom: 4px;
color: rgba(0, 0, 0, 0.85);
font-weight: 500;
font-size: 20px;
line-height: 28px;
}
.detail p {
position: relative;
margin-bottom: 8px;
padding-left: 26px;
}
.detail p:last-child {
margin-bottom: 0;
}
.detail i {
position: absolute;
top: 4px;
left: 0;
width: 14px;
height: 14px;
}
.tagsTitle,
.teamTitle {
margin-bottom: 12px;
color: rgba(0, 0, 0, 0.85);
font-weight: 500;
}
.tags .ant-tag {
margin-bottom: 8px;
}
.team .ant-avatar {
margin-right: 12px;
}
.team a {
display: block;
margin-bottom: 24px;
overflow: hidden;
color: rgba(0, 0, 0, 0.85);
white-space: nowrap;
text-overflow: ellipsis;
word-break: break-all;
transition: color 0.3s;
}
.team a:hover {
color: #1890ff;
}
.tabsCard .ant-card-head {
padding: 0 16px;
}

View File

@@ -0,0 +1,60 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Settings
<div class="baseView">
<div class="left" style="min-width: 310px;">
<Form
Layout="vertical"
OnFinish="HandleFinish"
Model="@_currentUser">
<FormItem Label="Email">
<AntDesign.Input @bind-Value="@context.Email" />
</FormItem>
<FormItem Label="Nickname">
<AntDesign.Input @bind-Value="@context.Name" />
</FormItem>
<FormItem Label="Personal profile">
<AntDesign.TextArea @bind-Value="@context.Signature" />
</FormItem>
<FormItem Label="Country/Region">
<Select
TItem="string"
TItemValue="string"
Style="max-width: 220px;"
@bind-Value="@context.Country">
<SelectOptions>
<SelectOption TItem="string" TItemValue="string" Value="@("China")" Label="中国"/>
</SelectOptions>
</Select>
</FormItem>
<FormItem Label="Province or city">
<GeographicView />
</FormItem>
<FormItem Label="Street Address">
<AntDesign.Input @bind-Value="@context.Address" />
</FormItem>
<FormItem Label="Phone Number">
<PhoneView />
</FormItem>
<FormItem>
<Button HtmlType="submit" Type="primary">
Update Information
</Button>
</FormItem>
</Form>
</div>
<div class="right__b__1">
<div class="avatar_title">
Avatar
</div>
<div class="avatar">
<img src="@_currentUser.Avatar" alt="avatar" />
</div>
<Upload ShowUploadList="false">
<div class="button_view">
<Button Icon="upload">
Change avatar
</Button>
</div>
</Upload>
</div>
</div>

View File

@@ -0,0 +1,24 @@
using Microsoft.AspNetCore.Components;
using System.Threading.Tasks;
using Xzy.KnowledgeBase.Models;
using Xzy.KnowledgeBase.Services;
namespace Xzy.KnowledgeBase.Pages.Account.Settings
{
public partial class BaseView
{
private CurrentUser _currentUser = new CurrentUser();
[Inject] protected IUserService UserService { get; set; }
private void HandleFinish()
{
}
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
_currentUser = await UserService.GetCurrentUserAsync();
}
}
}

View File

@@ -0,0 +1,54 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.baseView {
display: flex;
padding-top: 12px;
}
.baseView :global .ant-legacy-form-item .ant-legacy-form-item-control-wrapper {
width: 100%;
}
.baseView .left {
min-width: 224px;
max-width: 448px;
}
.baseView .right__b__1 {
flex: 1;
padding-left: 104px;
}
.baseView .right__b__1 .avatar_title {
height: 22px;
margin-bottom: 8px;
color: rgba(0, 0, 0, 0.85);
font-size: 14px;
line-height: 22px;
}
.baseView .right__b__1 .avatar {
width: 144px;
height: 144px;
margin-bottom: 12px;
overflow: hidden;
}
.baseView .right__b__1 .avatar img {
width: 100%;
}
.baseView .right__b__1 .button_view {
width: 144px;
text-align: center;
}
@media screen and (max-width: 1200px) {
.baseView {
flex-direction: column-reverse;
}
.baseView .right__b__1 {
display: flex;
flex-direction: column;
align-items: center;
max-width: 448px;
padding: 20px;
}
.baseView .right__b__1 .avatar_title {
display: none;
}
}

View File

@@ -0,0 +1,21 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Settings
<AntList
TItem="UserLiteItem"
ItemLayout="ListItemLayout.Horizontal"
DataSource="_data">
<ListItem Actions="_actions">
<ListItemMeta Title="@context.Title" Description="@context.Description">
<AvatarTemplate>
<Icon Type="@context.Avater" Theme="outline" Class="@context.Avater" />
</AvatarTemplate>
</ListItemMeta>
</ListItem>
</AntList>
@code
{
private static RenderFragment _modify = @<a key="bind">Bind</a>;
private readonly RenderFragment[] _actions = {_modify};
}

View File

@@ -0,0 +1,29 @@
using Xzy.KnowledgeBase.Models;
namespace Xzy.KnowledgeBase.Pages.Account.Settings
{
public partial class BindingView
{
private readonly UserLiteItem[] _data =
{
new UserLiteItem
{
Avater = "taobao",
Title = "Binding Taobao",
Description = "Currently unbound Taobao account"
},
new UserLiteItem
{
Avater = "alipay",
Title = "Binding Alipay",
Description = "Currently unbound Alipay account"
},
new UserLiteItem
{
Avater = "dingding",
Title = "Binding DingTalk",
Description = "Currently unbound DingTalk account"
}
};
}
}

View File

@@ -0,0 +1,5 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Settings
<h1>
GeographicView
</h1>

View File

@@ -0,0 +1,18 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.row .item {
width: 50%;
max-width: 220px;
}
.row .item:first-child {
width: calc(50% - 8px);
margin-right: 8px;
}
@media screen and (max-width: 576px) {
.item:first-child {
margin: 0;
margin-bottom: 8px;
}
}

View File

@@ -0,0 +1,18 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Settings
<AntList
TItem="UserLiteItem"
ItemLayout="ListItemLayout.Horizontal"
DataSource="_data">
<ListItem Actions="_actions">
<ListItemMeta Avatar="" Description="@context.Description">
<TitleTemplate>@context.Title</TitleTemplate>
</ListItemMeta>
</ListItem>
</AntList>
@code
{
private static RenderFragment _switch = @<Switch CheckedChildren="@("Open")" UnCheckedChildren="@("Close")" Checked="true"/>;
private readonly RenderFragment[] _actions = {_switch};
}

View File

@@ -0,0 +1,26 @@
using Xzy.KnowledgeBase.Models;
namespace Xzy.KnowledgeBase.Pages.Account.Settings
{
public partial class NotificationView
{
private readonly UserLiteItem[] _data =
{
new UserLiteItem
{
Title = "Account Password",
Description = "Messages from other users will be notified in the form of a station letter"
},
new UserLiteItem
{
Title = "System Messages",
Description = "System messages will be notified in the form of a station letter"
},
new UserLiteItem
{
Title = "To-do Notification",
Description = "The to-do list will be notified in the form of a letter from the station"
}
};
}
}

View File

@@ -0,0 +1,5 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Settings
<h1>
PhoneView
</h1>

View File

@@ -0,0 +1,13 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.area_code {
width: 30%;
max-width: 128px;
margin-right: 8px;
}
.phone_number {
width: calc(70% - 8px);
max-width: 312px;
}

View File

@@ -0,0 +1,18 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Settings
<AntList
TItem="UserLiteItem"
ItemLayout="ListItemLayout.Horizontal"
DataSource="_data">
<ListItem Actions="_actions">
<ListItemMeta Avatar="" Description="@context.Description">
<TitleTemplate>@context.Title</TitleTemplate>
</ListItemMeta>
</ListItem>
</AntList>
@code
{
private static RenderFragment _modify = @<a key="modify">Modify</a>;
private readonly RenderFragment[] _actions = {_modify};
}

View File

@@ -0,0 +1,37 @@
using Xzy.KnowledgeBase.Models;
namespace Xzy.KnowledgeBase.Pages.Account.Settings
{
public partial class SecurityView
{
private readonly UserLiteItem[] _data =
{
new UserLiteItem
{
Title = "Account Password",
Description = "Current password strength: : Strong"
},
new UserLiteItem
{
Title = "Security Phone",
Description = "Bound phone: : 138****8293"
},
new UserLiteItem
{
Title = "Security Question",
Description =
"The security question is not set, and the security policy can effectively protect the account security"
},
new UserLiteItem
{
Title = "Backup Email",
Description = "Bound Email: : ant***sign.com"
},
new UserLiteItem
{
Title = "MFA Device",
Description = "Unbound MFA device, after binding, can be confirmed twice"
}
};
}
}

View File

@@ -0,0 +1,36 @@
@namespace Xzy.KnowledgeBase.Pages.Account.Settings
@page "/account/settings"
<GridContent>
<div class="main__b__2">
<div class="leftMenu">
<Menu
Mode="MenuMode.Inline"
SelectedKeys="new []{_selectKey}"
OnMenuItemClicked="SelectKey">
@foreach (var item in _menuMap)
{
<MenuItem Key="@item.Key">@item.Value</MenuItem>
}
</Menu>
</div>
<div class="right__b__0">
<div class="title">@_menuMap[_selectKey]</div>
@switch (_selectKey)
{
case "base":
<BaseView />
break;
case "security":
<SecurityView />
break;
case "binding":
<BindingView />
break;
case "notification":
<NotificationView />
break;
}
</div>
</div>
</GridContent>

View File

@@ -0,0 +1,23 @@
using AntDesign;
using System.Collections.Generic;
namespace Xzy.KnowledgeBase.Pages.Account.Settings
{
public partial class Index
{
private readonly Dictionary<string, string> _menuMap = new Dictionary<string, string>
{
{"base", "Basic Settings"},
{"security", "Security Settings"},
{"binding", "Account Binding"},
{"notification", "New Message Notification"},
};
private string _selectKey = "base";
private void SelectKey(MenuItem item)
{
_selectKey = item.Key;
}
}
}

View File

@@ -0,0 +1,87 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.main__b__2 {
display: flex;
width: 100%;
height: 100%;
padding-top: 16px;
padding-bottom: 16px;
overflow: auto;
background-color: #fff;
}
.main__b__2 .leftMenu {
width: 224px;
border-right: 1px solid #f0f0f0;
}
.main__b__2 .leftMenu :global .ant-menu-inline {
border: none;
}
.main__b__2 .leftMenu :global .ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
font-weight: bold;
}
.main__b__2 .right__b__0 {
flex: 1;
padding-top: 8px;
padding-right: 40px;
padding-bottom: 8px;
padding-left: 40px;
}
.main__b__2 .right__b__0 .title {
margin-bottom: 12px;
color: rgba(0, 0, 0, 0.85);
font-weight: 500;
font-size: 20px;
line-height: 28px;
}
.main__b__2 .ant-list-split .ant-list-item:last-child {
border-bottom: 1px solid #f0f0f0;
}
.main__b__2 .ant-list-item {
padding-top: 14px;
padding-bottom: 14px;
}
.ant-list-item-meta .taobao {
display: block;
color: #ff4000;
font-size: 48px;
line-height: 48px;
border-radius: 2px;
}
.ant-list-item-meta .dingding {
margin: 2px;
padding: 6px;
color: #fff;
font-size: 32px;
line-height: 32px;
background-color: #2eabff;
border-radius: 2px;
}
.ant-list-item-meta .alipay {
color: #2eabff;
font-size: 48px;
line-height: 48px;
border-radius: 2px;
}
font.strong {
color: #52c41a;
}
font.medium {
color: #faad14;
}
font.weak {
color: #ff4d4f;
}
@media screen and (max-width: 768px) {
.main__b__2 {
flex-direction: column;
}
.main__b__2 .leftMenu {
width: 100%;
border: none;
}
.main__b__2 .right__b__0 {
padding: 40px;
}
}

View File

@@ -0,0 +1 @@
@namespace Xzy.KnowledgeBase.Pages.Dashboard.Analysis.Bar

View File

@@ -0,0 +1,26 @@
@namespace Xzy.KnowledgeBase.Pages.Dashboard.Analysis
@inherits AntDomComponentBase
<Card>
<div class="chartCard">
<div class="chartTop">
<div class="avatar">@Avatar</div>
<div class="metaWrap">
<div class="meta">
<span>@Title</span>
<span class="action"><Icon Type="info-circle" /></span>
</div>
<div class="total">
<span>@Total</span>
</div>
</div>
</div>
<div class="content" style="height: @(string.IsNullOrEmpty(ContentHeight) ? "auto" : ContentHeight+"px")">
<div class="@(string.IsNullOrEmpty(ContentHeight) ? "" : "contentFixed")">@ChildContent</div>
</div>
<div class="footer">
@Footer
</div>
</div>
</Card>

View File

@@ -0,0 +1,28 @@
using Microsoft.AspNetCore.Components;
namespace Xzy.KnowledgeBase.Pages.Dashboard.Analysis
{
public partial class ChartCard
{
[Parameter]
public string Avatar { get; set; }
[Parameter]
public string Title { get; set; }
[Parameter]
public RenderFragment Action { get; set; }
[Parameter]
public string Total { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public RenderFragment Footer { get; set; }
[Parameter]
public string ContentHeight { get; set; }
}
}

View File

@@ -0,0 +1,77 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.chartCard {
position: relative;
}
.chartCard .chartTop {
position: relative;
width: 100%;
overflow: hidden;
}
.chartCard .chartTopMargin {
margin-bottom: 12px;
}
.chartCard .chartTopHasMargin {
margin-bottom: 20px;
}
.chartCard .metaWrap {
float: left;
}
.chartCard .avatar {
position: relative;
top: 4px;
float: left;
margin-right: 20px;
}
.chartCard .avatar img {
border-radius: 100%;
}
.chartCard .meta {
height: 22px;
color: rgba(0, 0, 0, 0.45);
font-size: 14px;
line-height: 22px;
}
.chartCard .action {
position: absolute;
top: 4px;
right: 0;
line-height: 1;
cursor: pointer;
}
.chartCard .total {
height: 38px;
margin-top: 4px;
margin-bottom: 0;
overflow: hidden;
color: rgba(0, 0, 0, 0.85);
font-size: 30px;
line-height: 38px;
white-space: nowrap;
text-overflow: ellipsis;
word-break: break-all;
}
.chartCard .content {
position: relative;
width: 100%;
margin-bottom: 12px;
}
.chartCard .contentFixed {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
.chartCard .footer {
margin-top: 8px;
padding-top: 9px;
border-top: 1px solid #f0f0f0;
}
.chartCard .footer > * {
position: relative;
}
.chartCard .footerMargin {
margin-top: 20px;
}

View File

@@ -0,0 +1,7 @@
@namespace Xzy.KnowledgeBase.Pages.Dashboard.Analysis
@inherits AntDomComponentBase
<div class="field">
<span class="label">@Label</span>
<span class="number">@Value</span>
</div>

View File

@@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Components;
namespace Xzy.KnowledgeBase.Pages.Dashboard.Analysis
{
public partial class Field
{
[Parameter]
public string Label { get; set; }
[Parameter]
public string Value { get; set; }
}
}

View File

@@ -0,0 +1,19 @@
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
.field {
margin: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.field .label,
.field .number {
font-size: 14px;
line-height: 22px;
}
.field .number {
margin-left: 8px;
color: rgba(0, 0, 0, 0.85);
}

Some files were not shown because too many files have changed in this diff Show More