sunpengfei
2025-08-08 53ee0a68605433db362abae3ed1af03fd23a7832
pref:优化
4个文件已添加
2个文件已删除
2 文件已重命名
13个文件已修改
945 ■■■■ 已修改文件
FlexJobApi.Core/Enums/Common/EnumErrorCodeType.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Enums/Common/EnumSmsTemplateCode.cs 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Enums/Common/EnumSmsTemplateType.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/FlexJobApi.Core.xml 228 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/FlexJobApiCoreStartup.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Models/FlexJobServer/Tasks/Queries/GetTaskInfoQuery.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Models/FlexJobServer/Tasks/Queries/GetTaskInfosQuery.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Models/UserServer/Auths/Commands/PasswordLoginCommand.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Models/UserServer/Auths/Commands/SendLoginOrRegisterVerifyCodeCommand.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Models/UserServer/Auths/Commands/SmsLoginCommand.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Utils/AliyunUtils/AliyunOptions.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Utils/SmsUtils/AliyunSmsUtils.cs 130 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Utils/SmsUtils/CheckVerifyCodeModel.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Utils/SmsUtils/SendVerifyCodeModel.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Utils/SmsUtils/SmsUtils.cs 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.FlexJobServer.Application/Tasks/Queries/TaskInfoQueryHandler.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.UserServer.Application/Auths/Commands/LoginCommandHandler.cs 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.UserServer.Application/Auths/Commands/PasswordLoginCommandHandler.cs 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.UserServer.Application/Auths/Commands/VerifyCodeCommandHandler.cs 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.UserServer.Application/FlexJobApi.UserServer.Application.xml 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Web.Entry/appsettings.json 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FlexJobApi.Core/Enums/Common/EnumErrorCodeType.cs
@@ -36,9 +36,14 @@
        [ErrorCodeItemMetadata("该{0}不可修改")]
        s410 = 410,
        /// <summary>
        /// 系统异常,请联系管理员
        /// 未知异常
        /// </summary>
        [ErrorCodeItemMetadata("系统异常,请联系管理员")]
        s500 = 500,
        /// <summary>
        /// 系统异常
        /// </summary>
        [ErrorCodeItemMetadata("{0}")]
        s510 = 510
    }
}
FlexJobApi.Core/Enums/Common/EnumSmsTemplateCode.cs
New file
@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FlexJobApi.Core
{
    /// <summary>
    /// 短信模板编号
    /// </summary>
    public enum EnumSmsTemplateCode
    {
        /// <summary>
        /// 818平台短信验证码
        /// 验证码:${code},请于5分钟内填写,请勿泄露,若非本人操作请忽略。
        /// </summary>
        VerifyCode,
        /// <summary>
        /// 818平台登录/注册
        /// 验证码${code},用户您好,您正在进行平台登录/注册,验证码10分钟内有效。
        /// </summary>
        LoginOrRegister,
        /// <summary>
        /// 818账号开通(管理端)
        /// 尊敬的用户您好,人力无忧账号已开通,账号:${account},密码:${pwd},请登录网址 https://admin.81812333.com
        /// </summary>
        CreateOperationAccount,
        /// <summary>
        /// 818手机号码修改
        /// 验证码${code},您正在进行修改手机号码操作,请勿泄露,若非本人操作请忽略。
        /// </summary>
        UpdateUserPhoneNumber,
        /// <summary>
        /// 818手机号换绑
        /// 尊敬的用户您好,818平台${code}的账户绑定手机号成功修改为${account},你可以使用该手机号登录,登录网址 https://www.81812333.com
        /// </summary>
        UpdateUserPhoneNumberNotice,
        /// <summary>
        /// 818重置密码
        /// 验证码${code},您正在进行重置密码操作,请勿泄露,若非本人操作请忽略。
        /// </summary>
        ResetUserPhoneNumber,
        /// <summary>
        /// 818平台密码重置(通知)
        /// 您好,您的密码已重置,账号:${account},密码:${password},请妥善保存
        /// </summary>
        ResetPasswordNotice,
        /// <summary>
        /// 账号修改
        /// 尊敬的用户您好: 您的818平台账号成功修改为${account}您可以使用该账号进行登录,登录网址:https://www.81812333.com
        /// </summary>
        ChangeUserName,
        /// <summary>
        /// 818账号开通
        /// 尊敬的用户您好,您的账号:${account},初始密码:${password},请妥善保存,您可使用账号密码登录并修改密码,登录网址 https://www.81812333.com
        /// </summary>
        CreateAccountNotice,
        /// <summary>
        /// 手机号解绑
        /// 尊敬的用户您好:818平台${account}的账号与${number}已解绑,你可以登录网址:https://www.81812333.com重新绑定手机号。
        /// </summary>
        UnbindingUserPhoneNumber,
        /// <summary>
        /// 解绑邮箱
        /// 尊敬的用户您好:818平台${account}的账号与${mail}已解绑,你可以登录网址:https://www.81812333.com重新绑定邮箱。
        /// </summary>
        UnbindingUserEmail,
        /// <summary>
        /// 818实名认证
        /// 验证码${code},您正在进行实名认证操作,请勿泄露,若非本人操作请忽略。
        /// </summary>
        UserCertificationAudit,
        /// <summary>
        /// 申请数字证书
        /// 验证码${code},用户您好,您正在申请数字证书,验证码10分钟内有效。
        /// </summary>
        ApplyUserCertificate,
        /// <summary>
        /// 电子签
        /// ${unit_name}请您点击签约t.81812333.com/Inter/${code}
        /// </summary>
        UserElectronSign,
        /// <summary>
        /// 818钱包开通
        /// 验证码${code},用户您好,您正在进行平台钱包开通,该验证码5分钟内有效,请勿泄露于他人。
        /// </summary>
        BankWalletAccountOpen
    }
}
FlexJobApi.Core/Enums/Common/EnumSmsTemplateType.cs
File was deleted
FlexJobApi.Core/FlexJobApi.Core.xml
@@ -1771,7 +1771,12 @@
        </member>
        <member name="F:FlexJobApi.Core.EnumErrorCodeType.s500">
            <summary>
            系统异常,请联系管理员
            未知异常
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumErrorCodeType.s510">
            <summary>
            系统异常
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.Enums.Common.EnumFileStoreAccess">
@@ -1989,34 +1994,99 @@
            阿里云短信
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.EnumSmsTemplateType">
        <member name="T:FlexJobApi.Core.EnumSmsTemplateCode">
            <summary>
            短信模板类型
            短信模板编号
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateType.Login">
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.VerifyCode">
            <summary>
            登录
            818平台短信验证码
            验证码:${code},请于5分钟内填写,请勿泄露,若非本人操作请忽略。
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateType.Register">
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.LoginOrRegister">
            <summary>
            注册
            818平台登录/注册
            验证码${code},用户您好,您正在进行平台登录/注册,验证码10分钟内有效。
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateType.UpdatePassword">
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.CreateOperationAccount">
            <summary>
            修改密码
            818账号开通(管理端)
            尊敬的用户您好,人力无忧账号已开通,账号:${account},密码:${pwd},请登录网址 https://admin.81812333.com
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateType.BindPhoneNumber">
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.UpdateUserPhoneNumber">
            <summary>
            绑定手机号码
            818手机号码修改
            验证码${code},您正在进行修改手机号码操作,请勿泄露,若非本人操作请忽略。
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateType.UpdatePhoneNumber">
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.UpdateUserPhoneNumberNotice">
            <summary>
            修改手机号码
            818手机号换绑
            尊敬的用户您好,818平台${code}的账户绑定手机号成功修改为${account},你可以使用该手机号登录,登录网址 https://www.81812333.com
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.ResetUserPhoneNumber">
            <summary>
            818重置密码
            验证码${code},您正在进行重置密码操作,请勿泄露,若非本人操作请忽略。
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.ResetPasswordNotice">
            <summary>
            818平台密码重置(通知)
            您好,您的密码已重置,账号:${account},密码:${password},请妥善保存
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.ChangeUserName">
            <summary>
            账号修改
            尊敬的用户您好: 您的818平台账号成功修改为${account}您可以使用该账号进行登录,登录网址:https://www.81812333.com
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.CreateAccountNotice">
            <summary>
            818账号开通
            尊敬的用户您好,您的账号:${account},初始密码:${password},请妥善保存,您可使用账号密码登录并修改密码,登录网址 https://www.81812333.com
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.UnbindingUserPhoneNumber">
            <summary>
            手机号解绑
            尊敬的用户您好:818平台${account}的账号与${number}已解绑,你可以登录网址:https://www.81812333.com重新绑定手机号。
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.UnbindingUserEmail">
            <summary>
            解绑邮箱
            尊敬的用户您好:818平台${account}的账号与${mail}已解绑,你可以登录网址:https://www.81812333.com重新绑定邮箱。
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.UserCertificationAudit">
            <summary>
            818实名认证
            验证码${code},您正在进行实名认证操作,请勿泄露,若非本人操作请忽略。
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.ApplyUserCertificate">
            <summary>
            申请数字证书
            验证码${code},用户您好,您正在申请数字证书,验证码10分钟内有效。
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.UserElectronSign">
            <summary>
            电子签
            ${unit_name}请您点击签约t.81812333.com/Inter/${code}
            </summary>
        </member>
        <member name="F:FlexJobApi.Core.EnumSmsTemplateCode.BankWalletAccountOpen">
            <summary>
            818钱包开通
            验证码${code},用户您好,您正在进行平台钱包开通,该验证码5分钟内有效,请勿泄露于他人。
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.EnumBillingMethod">
@@ -3060,7 +3130,7 @@
            企业Id
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.GetTaskInfoQueryResult.EnterpriseName">
        <member name="P:FlexJobApi.Core.GetTaskInfoQueryResult.EnterpriseEnterpriseName">
            <summary>
            企业全称
            </summary>
@@ -3175,6 +3245,16 @@
            是否已收藏
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.GetTaskInfoQueryResult.Status">
            <summary>
            任务状态
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.GetTaskInfoQueryResult.ReleaseStatus">
            <summary>
            发布状态
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.GetTaskInfoQueryResultBenefit">
            <summary>
            查询任务详情-结果-福利
@@ -3185,9 +3265,14 @@
            福利编号
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.GetTaskInfoQueryResultBenefit.BenefitField2">
            <summary>
            福利图标
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.GetTaskInfoQueryResultBenefit.BenefitContent">
            <summary>
            福利
            福利名称
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.GetTaskInfoQueryResultCredentialLimit">
@@ -3213,6 +3298,11 @@
        <member name="P:FlexJobApi.Core.GetTaskInfosQuery.Keywords">
            <summary>
            关键字(任务名称)
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.GetTaskInfosQuery.EnterpriseId">
            <summary>
            企业Id
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.GetTaskInfosQuery.BeginTime">
@@ -3434,34 +3524,29 @@
            客户端类型
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.PasswordLoginCommandCallback">
        <member name="T:FlexJobApi.Core.LoginCommandCallback">
            <summary>
            密码登录结果
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.PasswordLoginCommandCallback.AccessToken">
        <member name="P:FlexJobApi.Core.LoginCommandCallback.AccessToken">
            <summary>
            用户访问令牌
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.PasswordLoginCommandCallback.RefreshToken">
        <member name="P:FlexJobApi.Core.LoginCommandCallback.RefreshToken">
            <summary>
            刷新令牌
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.SendVerifyCodeCommand">
        <member name="T:FlexJobApi.Core.SendLoginOrRegisterVerifyCodeCommand">
            <summary>
            发送验证码
            发送登录或注册短信
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.SendVerifyCodeCommand.PhoneNumber">
        <member name="P:FlexJobApi.Core.SendLoginOrRegisterVerifyCodeCommand.PhoneNumber">
            <summary>
            手机号码
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.SendVerifyCodeCommand.TemplateCode">
            <summary>
            短信模板编号
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.SmsLoginCommand">
@@ -3497,21 +3582,6 @@
        <member name="P:FlexJobApi.Core.WxmpLoginCommand.Code">
            <summary>
            用户登录凭证
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.WxmpRegisterCommand">
            <summary>
            微信小程序注册
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.WxmpRegisterCommand.PhoneNumber">
            <summary>
            手机号码
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.WxmpRegisterCommand.VerifyCode">
            <summary>
            验证码
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.GetAliyunOSSAcsQuery">
@@ -5119,6 +5189,31 @@
            阿里云短信配置
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.AliyunSMSOptions.Enable">
            <summary>
            是否启用
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.AliyunSMSOptions.Version">
            <summary>
            版本
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.AliyunSMSOptions.SignName">
            <summary>
            签名名称
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.AliyunSMSOptions.RegionId">
            <summary>
            区域Id
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.AliyunSMSOptions.TemplateCodes">
            <summary>
            模板代码
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.AliyunOSSUtils">
            <summary>
            阿里云OSS工具
@@ -6029,6 +6124,17 @@
            <param name="type"></param>
            <returns></returns>
        </member>
        <member name="M:FlexJobApi.Core.AliyunSmsUtils.SendAsync(System.String,FlexJobApi.Core.EnumSmsTemplateCode,System.String,System.Threading.CancellationToken)">
            <summary>
            发送短信
            </summary>
            <param name="phoneNumber">手机号码</param>
            <param name="templateCode">模板代码</param>
            <param name="templateParam">模板参数</param>
            <param name="cancellationToken">取消令牌</param>
            <returns></returns>
            <exception cref="T:Furion.FriendlyException.Oops"></exception>
        </member>
        <member name="M:FlexJobApi.Core.AliyunSmsUtils.PercentEncode(System.String)">
            <summary>
            排除敏感字符串
@@ -6044,6 +6150,46 @@
            <param name="key"></param>
            <returns></returns>
        </member>
        <member name="T:FlexJobApi.Core.CheckVerifyCodeModel">
            <summary>
            校验验证码
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.CheckVerifyCodeModel.TemplateCode">
            <summary>
            短信模板编号
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.CheckVerifyCodeModel.PhoneNumber">
            <summary>
            手机号码
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.CheckVerifyCodeModel.VerifyCode">
            <summary>
            验证码
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.SendVerifyCodeModel">
            <summary>
            发送验证码
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.SendVerifyCodeModel.PhoneNumber">
            <summary>
            手机号码
            </summary>
        </member>
        <member name="P:FlexJobApi.Core.SendVerifyCodeModel.TemplateCode">
            <summary>
            短信模板编号
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.SmsUtils">
            <summary>
            短信工具
            </summary>
        </member>
        <member name="T:FlexJobApi.Core.StringUtils">
            <summary>
            字符串工具
FlexJobApi.Core/FlexJobApiCoreStartup.cs
@@ -51,6 +51,8 @@
            services.AddHttpRemote();
            services.AddSingleton<ResourceHttpUtils>();
            services.AddSingleton<AliyunSmsUtils>();
            services.AddScoped<SmsUtils>();
            services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(App.Assemblies.ToArray()));
FlexJobApi.Core/Models/FlexJobServer/Tasks/Queries/GetTaskInfoQuery.cs
@@ -1,6 +1,7 @@
using FlexJobApi.Core.Models.Common;
using Mapster;
using MediatR;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
@@ -46,7 +47,8 @@
        /// <summary>
        /// 企业全称
        /// </summary>
        public string EnterpriseName { get; set; }
        [JsonProperty("EnterpriseName")]
        public string EnterpriseEnterpriseName { get; set; }
        /// <summary>
        /// 在招岗位数量
FlexJobApi.Core/Models/FlexJobServer/Tasks/Queries/GetTaskInfosQuery.cs
@@ -24,6 +24,11 @@
        public string Keywords { get; set; }
        /// <summary>
        /// 企业Id
        /// </summary>
        public Guid? EnterpriseId { get; set; }
        /// <summary>
        /// 发布时间-开始
        /// </summary>
        public DateTime? BeginTime { get; set; }
FlexJobApi.Core/Models/UserServer/Auths/Commands/PasswordLoginCommand.cs
@@ -13,7 +13,7 @@
    /// 密码登录
    /// </summary>
    [Resource([EnumResourceController.Auth], AllowAnonymous = true)]
    public class PasswordLoginCommand : IRequest<PasswordLoginCommandCallback>
    public class PasswordLoginCommand : IRequest<LoginCommandCallback>
    {
        /// <summary>
        /// 账号
@@ -41,7 +41,7 @@
    /// <summary>
    /// 密码登录结果
    /// </summary>
    public class PasswordLoginCommandCallback
    public class LoginCommandCallback
    {
        /// <summary>
        /// 用户访问令牌
FlexJobApi.Core/Models/UserServer/Auths/Commands/SendLoginOrRegisterVerifyCodeCommand.cs
New file
@@ -0,0 +1,24 @@
using Furion.DataValidation;
using MediatR;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FlexJobApi.Core
{
    /// <summary>
    /// 发送登录或注册短信
    /// </summary>
    [Resource([EnumResourceController.Auth], AllowAnonymous = true)]
    public class SendLoginOrRegisterVerifyCodeCommand : IRequest<Guid>
    {
        /// <summary>
        /// 手机号码
        /// </summary>
        [Required, DataValidation(ValidationTypes.PhoneNumber)]
        public string PhoneNumber { get; set; }
    }
}
FlexJobApi.Core/Models/UserServer/Auths/Commands/SmsLoginCommand.cs
@@ -1,4 +1,5 @@
using System;
using MediatR;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
@@ -11,18 +12,20 @@
    /// 短信登录
    /// </summary>
    [Resource([EnumResourceController.Auth], AllowAnonymous = true)]
    public class SmsLoginCommand
    public class SmsLoginCommand : IRequest<LoginCommandCallback>
    {
        /// <summary>
        /// 手机号码
        /// </summary>
        [Required]
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 验证码
        /// </summary>
        [Required]
        public string VerifyCode { get; set; }
        /// <summary>
        /// 用户类型
        /// </summary>
FlexJobApi.Core/Utils/AliyunUtils/AliyunOptions.cs
@@ -37,7 +37,34 @@
    /// 阿里云短信配置
    /// </summary>
    public class AliyunSMSOptions
    {
    {
        public string AccessKeyId { get; set; }
        public string AccessSecret { get; set; }
        /// <summary>
        /// 是否启用
        /// </summary>
        public bool Enable { get; set; }
        /// <summary>
        /// 版本
        /// </summary>
        public string Version { get; set; }
        /// <summary>
        /// 签名名称
        /// </summary>
        public string SignName { get; set; }
        /// <summary>
        /// 区域Id
        /// </summary>
        public string RegionId { get; set; }
        /// <summary>
        /// 模板代码
        /// </summary>
        public Dictionary<string, string> TemplateCodes { get; set; }
    }
}
FlexJobApi.Core/Utils/SmsUtils/AliyunSmsUtils.cs
@@ -17,16 +17,13 @@
    {
        private readonly IOptions<AliyunOptions> options;
        private readonly IHttpRemoteService httpRemoteService;
        private readonly IHttpContextAccessor httpContextAccessor;
        public AliyunSmsUtils(
            IOptions<AliyunOptions> options,
            IHttpRemoteService httpRemoteService,
            IHttpContextAccessor httpContextAccessor)
            IHttpRemoteService httpRemoteService)
        {
            this.options = options;
            this.httpRemoteService = httpRemoteService;
            this.httpContextAccessor = httpContextAccessor;
        }
        /// <summary>
@@ -38,75 +35,72 @@
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns></returns>
        /// <exception cref="Oops"></exception>
        //public async Task SendAsync(string phoneNumber, EnumSmsTemplateType templateCode, string templateParam, CancellationToken cancellationToken)
        //{
        //    if (options.Value.Sms?.Enable != true)
        //    {
        //        httpContextAccessor.AddAdditionalData("TemplateParam", templateParam);
        //        return;
        //    }
        //    if (options.Value.Sms != null
        //        && options.Value.Sms.Version.IsNotNull()
        //        && options.Value.Sms.RegionId.IsNotNull()
        //        && options.Value.Sms.SignName.IsNotNull()
        //        && options.Value.AccessKeyId.IsNotNull()
        //        && options.Value.AccessKeySecret.IsNotNull())
        //    {
        //        var _templateCode = options.Value.Sms.TemplateCodes[templateCode.ToString()];
        //        var _params = new Dictionary<string, string>
        //        {
        //            {"Action", "SendSms"},
        //            {"Version", options.Value.Sms.Version},
        //            {"RegionId", options.Value.Sms.RegionId},
        //            {"PhoneNumbers", phoneNumber},
        //            {"SignName", options.Value.Sms.SignName},
        //            {"TemplateCode",  _templateCode}
        //        };
        //        if (!string.IsNullOrWhiteSpace(templateParam))
        //        {
        //            _params.Add("TemplateParam", templateParam);
        //        }
        //        var timestamp = DateTime.Now.ToUniversalTime()
        //            .ToString("yyyy-MM-dd'T'HH:mm:ss'Z'", CultureInfo.CreateSpecificCulture("en-US"));
        public async Task SendAsync(string phoneNumber, EnumSmsTemplateCode templateCode, string templateParam, CancellationToken cancellationToken)
        {
            if (options.Value.SMS?.Enable != true)
            {
                return;
            }
            if (options.Value.SMS != null
                && options.Value.SMS.Version.IsNotNull()
                && options.Value.SMS.RegionId.IsNotNull()
                && options.Value.SMS.SignName.IsNotNull()
                && options.Value.SMS.AccessKeyId.IsNotNull()
                && options.Value.SMS.AccessSecret.IsNotNull())
            {
                var _templateCode = options.Value.SMS.TemplateCodes[templateCode.ToString()];
                var _params = new Dictionary<string, string>
                {
                    {"Action", "SendSms"},
                    {"Version", options.Value.SMS.Version},
                    {"RegionId", options.Value.SMS.RegionId},
                    {"PhoneNumbers", phoneNumber},
                    {"SignName", options.Value.SMS.SignName},
                    {"TemplateCode",  _templateCode}
                };
                if (!string.IsNullOrWhiteSpace(templateParam))
                {
                    _params.Add("TemplateParam", templateParam);
                }
                var timestamp = DateTime.Now.ToUniversalTime()
                    .ToString("yyyy-MM-dd'T'HH:mm:ss'Z'", CultureInfo.CreateSpecificCulture("en-US"));
        //        _params.Add("AccessKeyId", options.Value.AccessKeyId);
        //        _params.Add("Timestamp", timestamp);
        //        _params.Add("Format", "JSON");
        //        _params.Add("SignatureMethod", "HMAC-SHA1");
        //        _params.Add("SignatureVersion", "1.0");
        //        _params.Add("SignatureNonce", Guid.NewGuid().ToString());
                _params.Add("AccessKeyId", options.Value.SMS.AccessKeyId);
                _params.Add("Timestamp", timestamp);
                _params.Add("Format", "JSON");
                _params.Add("SignatureMethod", "HMAC-SHA1");
                _params.Add("SignatureVersion", "1.0");
                _params.Add("SignatureNonce", Guid.NewGuid().ToString());
        //        //排序
        //        var sortDic = new SortedDictionary<string, string>(_params, StringComparer.Ordinal);
                //排序
                var sortDic = new SortedDictionary<string, string>(_params, StringComparer.Ordinal);
        //        //生成Url参数
        //        var urlParams = "";
        //        foreach (var dic in sortDic)
        //        {
        //            urlParams += $"{PercentEncode(dic.Key)}={PercentEncode(dic.Value)}&";
        //        }
        //        urlParams = urlParams.TrimEnd('&');
                //生成Url参数
                var urlParams = "";
                foreach (var dic in sortDic)
                {
                    urlParams += $"{PercentEncode(dic.Key)}={PercentEncode(dic.Value)}&";
                }
                urlParams = urlParams.TrimEnd('&');
        //        //签名
        //        var stringToSign = $"GET&{PercentEncode("/")}&{PercentEncode(urlParams)}";
        //        string signature = PercentEncode(ToHmacsha1(stringToSign, options.Value.AccessKeySecret + "&"));
                //签名
                var stringToSign = $"GET&{PercentEncode("/")}&{PercentEncode(urlParams)}";
                string signature = PercentEncode(ToHmacsha1(stringToSign, options.Value.SMS.AccessSecret + "&"));
        //        var req = $"http://dysmsapi.aliyuncs.com/?Signature={signature}&{urlParams}"
        //            .SetMethod(HttpMethod.Get);
        //        var res = await http.SendAsync(req, cancellationToken);
        //        var callback = res.Callback?.JsonTo(new
        //        {
        //            Code = "",
        //            Message = "",
        //            RequestId = "",
        //            BizId = ""
        //        });
        //        if (callback == null || callback.Code != "OK")
        //        {
        //            throw new Oops(FriendlyCallbackCode.Error, "发送短信失败", $"发送短信异常:{callback?.Message}");
        //        }
        //    }
        //}
                var res = await httpRemoteService.GetAsStringAsync($"http://dysmsapi.aliyuncs.com/?Signature={signature}&{urlParams}");
                var callback = res.JsonTo(new
                {
                    Code = "",
                    Message = "",
                    RequestId = "",
                    BizId = ""
                });
                if (callback == null || callback.Code != "OK")
                {
                    throw Oops.Oh(EnumErrorCodeType.s510, $"发送短信失败:{callback?.Message},请联系管理员");
                }
            }
        }
        /// <summary>
        /// 排除敏感字符串
FlexJobApi.Core/Utils/SmsUtils/CheckVerifyCodeModel.cs
File was renamed from FlexJobApi.Core/Models/UserServer/Auths/Commands/WxmpRegisterCommand.cs
@@ -1,6 +1,6 @@
using System;
using MediatR;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -8,19 +8,23 @@
namespace FlexJobApi.Core
{
    /// <summary>
    /// 微信小程序注册
    /// 校验验证码
    /// </summary>
    public class WxmpRegisterCommand
    public class CheckVerifyCodeModel
    {
        /// <summary>
        /// 短信模板编号
        /// </summary>
        public EnumSmsTemplateCode TemplateCode { get; set; }
        /// <summary>
        /// 手机号码
        /// </summary>
        [Required]
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 验证码
        /// </summary>
        [Required]
        public string VerifyCode { get; set; }
    }
}
FlexJobApi.Core/Utils/SmsUtils/SendVerifyCodeModel.cs
File was renamed from FlexJobApi.Core/Models/UserServer/Auths/Commands/SendVerifyCodeCommand.cs
@@ -1,6 +1,8 @@
using MediatR;
using Furion.DataValidation;
using MediatR;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -10,16 +12,17 @@
    /// <summary>
    /// 发送验证码
    /// </summary>
    [Resource([EnumResourceController.Auth], AllowAnonymous = true)]
    public class SendVerifyCodeCommand : IRequest<Guid>
    public class SendVerifyCodeModel
    {
        /// <summary>
        /// 手机号码
        /// </summary>
        [Required, DataValidation(ValidationTypes.PhoneNumber)]
        public string PhoneNumber { get; set; }
        /// <summary>
        /// 短信模板编号
        /// </summary>
        public EnumSmsTemplateType TemplateCode { get; set; }
        public EnumSmsTemplateCode TemplateCode { get; set; }
    }
}
FlexJobApi.Core/Utils/SmsUtils/SmsUtils.cs
New file
@@ -0,0 +1,59 @@
using Azure.Core;
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using Mapster;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace FlexJobApi.Core
{
    /// <summary>
    /// 短信工具
    /// </summary>
    public class SmsUtils
    {
        private readonly IRepository<SmsLog> rep;
        private readonly AliyunSmsUtils aliyunSmsUtils;
        public SmsUtils(
            IRepository<SmsLog> rep,
            AliyunSmsUtils aliyunSmsUtils)
        {
            this.rep = rep;
            this.aliyunSmsUtils = aliyunSmsUtils;
        }
        public async Task<Guid> SendVerifyCode(SendVerifyCodeModel model, CancellationToken cancellationToken = default)
        {
            var code = new Random().Next(100000, 999999).ToString();
            var entity = new SmsLog();
            model.Adapt(entity);
            entity.Expiry = DateTime.Now.AddMinutes(10);
            entity.TemplateParam = new { code }.ToJson();
            await aliyunSmsUtils.SendAsync(model.PhoneNumber, model.TemplateCode, entity.TemplateParam, cancellationToken);
            await rep.InsertAsync(entity);
            return entity.Id;
        }
        public async Task CheckVerifyCode(CheckVerifyCodeModel model, CancellationToken cancellationToken = default)
        {
            var entity = await rep.AsQueryable().AsNoTracking()
                .Where(it =>
                    it.PhoneNumber == model.PhoneNumber
                    && it.TemplateCode == model.TemplateCode.ToString()
                    && it.TemplateParam == new { code = model.VerifyCode }.ToJson()
                    && it.Expiry > DateTimeOffset.Now
                    && !it.IsUsed)
                .FirstOrDefaultAsync(cancellationToken);
            if (entity == null) throw Oops.Oh(EnumErrorCodeType.s400, "验证码无效");
            entity.IsUsed = true;
            await rep.UpdateAsync(entity);
        }
    }
}
FlexJobApi.FlexJobServer.Application/Tasks/Queries/TaskInfoQueryHandler.cs
@@ -57,6 +57,10 @@
            {
                q = q.Where(it => it.Name.Contains(request.Keywords));
            }
            if (request.EnterpriseId.HasValue)
            {
                q = q.Where(it => it.EnterpriseId == request.EnterpriseId);
            }
            if (request.BeginTime.HasValue && request.EndTime.HasValue)
            {
                q = q.Where(it => request.BeginTime <= it.BeginTime && it.BeginTime <= request.EndTime);
FlexJobApi.UserServer.Application/Auths/Commands/LoginCommandHandler.cs
New file
@@ -0,0 +1,101 @@
using Azure.Core;
using FlexJobApi.Core;
using Furion.DatabaseAccessor;
using Furion.DataEncryption;
using Furion.FriendlyException;
using Mapster;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FlexJobApi.UserServer.Application
{
    /// <summary>
    /// 登录命令处理器
    /// </summary>
    public class LoginCommandHandler(
        IRepository<User> rep,
        SmsUtils smsUtils) :
        IRequestHandler<PasswordLoginCommand, LoginCommandCallback>,
        IRequestHandler<SmsLoginCommand, LoginCommandCallback>
    {
        private readonly IRepository<User> rep = rep;
        private readonly SmsUtils smsUtils = smsUtils;
        /// <summary>
        /// 密码登录
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<LoginCommandCallback> Handle(PasswordLoginCommand request, CancellationToken cancellationToken)
        {
            var user = await rep.AsQueryable().AsNoTracking()
                .Where(it => it.UserName == request.UserName && it.Type == request.Type)
                .FirstOrDefaultAsync(cancellationToken);
            if (user == null
                || !PBKDF2Encryption.Compare(request.Password, user.Password))
                throw Oops.Oh(EnumUserErrorCodeType.u1000);
            if (user.Status == EnumUserStatus.Disabled)
                throw Oops.Oh(EnumUserErrorCodeType.u1001);
            return GetCurrentLogier(user, request.ClientType);
        }
        /// <summary>
        /// 短信登录
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<LoginCommandCallback> Handle(SmsLoginCommand request, CancellationToken cancellationToken)
        {
            await smsUtils.CheckVerifyCode(new CheckVerifyCodeModel
            {
                PhoneNumber = request.PhoneNumber,
                VerifyCode = request.VerifyCode,
                TemplateCode = EnumSmsTemplateCode.LoginOrRegister
            });
            var user = await rep.AsQueryable().AsNoTracking()
                .Where(it => it.UserName == request.PhoneNumber && it.Type == request.Type)
                .FirstOrDefaultAsync(cancellationToken);
            if (user == null)
                throw Oops.Oh(EnumUserErrorCodeType.u1000);
            if (user.Status == EnumUserStatus.Disabled)
                throw Oops.Oh(EnumUserErrorCodeType.u1001);
            return GetCurrentLogier(user, request.ClientType);
        }
        /// <summary>
        /// 获取当前登录用户
        /// </summary>
        /// <param name="user"></param>
        /// <param name="clientType"></param>
        /// <returns></returns>
        private LoginCommandCallback GetCurrentLogier(User user, EnumClientType clientType)
        {
            var logier = new CurrentLogier
            {
                Id = user.Id,
                Avatar = user.Avatar,
                Name = user.Name,
                UserName = user.UserName,
                PhoneNumber = user.PhoneNumber,
                Level = user.Level,
                Type = user.Type,
                ClientType = clientType,
                EnterpriseId = user.EnterpriseId,
            };
            JwtUtils.GenerateToken(logier);
            return new LoginCommandCallback
            {
                AccessToken = logier.AccessToken,
                RefreshToken = logier.RefreshToken,
            };
        }
    }
}
FlexJobApi.UserServer.Application/Auths/Commands/PasswordLoginCommandHandler.cs
File was deleted
FlexJobApi.UserServer.Application/Auths/Commands/VerifyCodeCommandHandler.cs
@@ -1,4 +1,5 @@
using FlexJobApi.Core;
using Furion.DatabaseAccessor;
using Mapster;
using MediatR;
using System;
@@ -12,27 +13,26 @@
    /// <summary>
    /// 验证码命令处理器
    /// </summary>
    public class VerifyCodeCommandHandler
        : IRequestHandler<SendVerifyCodeCommand, Guid>
    public class VerifyCodeCommandHandler(
            SmsUtils smsUtils
        )
        : IRequestHandler<SendLoginOrRegisterVerifyCodeCommand, Guid>
    {
        private readonly SmsUtils smsUtils = smsUtils;
        /// <summary>
        /// 发送验证码
        /// 发送登录或注册短信
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task<Guid> Handle(SendVerifyCodeCommand request, CancellationToken cancellationToken)
        public Task<Guid> Handle(SendLoginOrRegisterVerifyCodeCommand request, CancellationToken cancellationToken)
        {
            throw new Exception();
            //var code = new Random().Next(100000, 999999).ToString();
            //var entity = new SmsLog();
            //request.Adapt(entity);
            //entity.Expiry = DateTime.Now.AddMinutes(30);
            //entity.TemplateParam = new { code }.ToJson();
            //await utils.SendAsync(request.PhoneNumber, request.TemplateCode, entity.TemplateParam, cancellationToken);
            //rep.Add(entity);
            //await rep.SaveChangesAsync(cancellationToken);
            //return new FriendlyEmptyCallback("验证码已发送,请查收");
            return smsUtils.SendVerifyCode(new SendVerifyCodeModel
            {
                PhoneNumber = request.PhoneNumber,
                TemplateCode = EnumSmsTemplateCode.LoginOrRegister
            });
        }
    }
}
FlexJobApi.UserServer.Application/FlexJobApi.UserServer.Application.xml
@@ -4,27 +4,53 @@
        <name>FlexJobApi.UserServer.Application</name>
    </assembly>
    <members>
        <member name="T:FlexJobApi.UserServer.Application.PasswordLoginCommandHandler">
        <member name="T:FlexJobApi.UserServer.Application.LoginCommandHandler">
            <summary>
            登录命令处理器
            </summary>
        </member>
        <member name="M:FlexJobApi.UserServer.Application.LoginCommandHandler.#ctor(Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.User},FlexJobApi.Core.SmsUtils)">
            <summary>
            登录命令处理器
            </summary>
        </member>
        <member name="M:FlexJobApi.UserServer.Application.LoginCommandHandler.Handle(FlexJobApi.Core.PasswordLoginCommand,System.Threading.CancellationToken)">
            <summary>
            密码登录
            </summary>
            <param name="request"></param>
            <param name="cancellationToken"></param>
            <returns></returns>
        </member>
        <member name="M:FlexJobApi.UserServer.Application.PasswordLoginCommandHandler.#ctor(Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.UserAuth},Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.User})">
        <member name="M:FlexJobApi.UserServer.Application.LoginCommandHandler.Handle(FlexJobApi.Core.SmsLoginCommand,System.Threading.CancellationToken)">
            <summary>
            密码登录
            短信登录
            </summary>
            <param name="request"></param>
            <param name="cancellationToken"></param>
            <returns></returns>
        </member>
        <member name="M:FlexJobApi.UserServer.Application.PasswordLoginCommandHandler.Handle(FlexJobApi.Core.PasswordLoginCommand,System.Threading.CancellationToken)">
            <inheritdoc/>
        <member name="M:FlexJobApi.UserServer.Application.LoginCommandHandler.GetCurrentLogier(FlexJobApi.Core.User,FlexJobApi.Core.EnumClientType)">
            <summary>
            获取当前登录用户
            </summary>
            <param name="user"></param>
            <param name="clientType"></param>
            <returns></returns>
        </member>
        <member name="T:FlexJobApi.UserServer.Application.VerifyCodeCommandHandler">
            <summary>
            验证码命令处理器
            </summary>
        </member>
        <member name="M:FlexJobApi.UserServer.Application.VerifyCodeCommandHandler.Handle(FlexJobApi.Core.SendVerifyCodeCommand,System.Threading.CancellationToken)">
        <member name="M:FlexJobApi.UserServer.Application.VerifyCodeCommandHandler.#ctor(FlexJobApi.Core.SmsUtils)">
            <summary>
            发送验证码
            验证码命令处理器
            </summary>
        </member>
        <member name="M:FlexJobApi.UserServer.Application.VerifyCodeCommandHandler.Handle(FlexJobApi.Core.SendLoginOrRegisterVerifyCodeCommand,System.Threading.CancellationToken)">
            <summary>
            发送登录或注册短信
            </summary>
            <param name="request"></param>
            <param name="cancellationToken"></param>
FlexJobApi.Web.Entry/appsettings.json
@@ -29,5 +29,50 @@
      "Policy": "{\"Version\":\"1\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"oss:PutObject\",\"Resource\":[\"acs:oss:*:*:waterdroptest2/*\",\"acs:oss:*:*:parkmanagement/*\",\"acs:oss:*:*:jurenlian/*\"]}]}",
      "DurationSeconds": 3600
    }
  },
  "SMS": {
    "Enable": false,
    "AccessKeyId": "LTAI5tMS7qz1duiyncCqxB8H",
    "AccessSecret": "TEHSXK6f6Njg0v0MSFkrjURofdjuKQ",
    "Version": "2017-05-25",
    "SignName": "818数字人力资产平台",
    "RegionId": "cn-hangzhou",
    "TemplateCodes": {
      //818平台短信验证码 验证码:${code},请于5分钟内填写,请勿泄露,若非本人操作请忽略。
      "VerifyCode": "SMS_471100021",
      //818平台登录/注册 验证码${code},用户您好,您正在进行平台登录/注册,验证码10分钟内有效。
      "LoginOrRegister": "SMS_472170005",
      //818账号开通(管理端)尊敬的用户您好,人力无忧账号已开通,账号:${account},密码:${pwd},请登录网址 https://admin.81812333.com
      "CreateOperationAccount": "SMS_471970028",
      //818手机号码修改 验证码${code},您正在进行修改手机号码操作,请勿泄露,若非本人操作请忽略。
      "UpdateUserPhoneNumber": "SMS_471100097",
      //818手机号换绑 尊敬的用户您好,818平台${code}的账户绑定手机号成功修改为${account},你可以使用该手机号登录,登录网址 https://www.81812333.com
      "UpdateUserPhoneNumberNotice": "SMS_471925037",
      //818重置密码 验证码${code},您正在进行重置密码操作,请勿泄露,若非本人操作请忽略。
      "ResetUserPhoneNumber": "SMS_471240080",
      //818平台密码重置(通知) 您好,您的密码已重置,账号:${account},密码:${password},请妥善保存
      "ResetPasswordNotice": "SMS_476790229",
      //账号修改 尊敬的用户您好: 您的818平台账号成功修改为${account}您可以使用该账号进行登录,登录网址:https://www.81812333.com
      "ChangeUserName": "SMS_475895109",
      //818账号开通 尊敬的用户您好,您的账号:${account},初始密码:${password},请妥善保存,您可使用账号密码登录并修改密码,登录网址 https://www.81812333.com
      "CreateAccountNotice": "SMS_471980029",
      //手机号解绑 尊敬的用户您好:818平台${account}的账号与${number}已解绑,你可以登录网址:https://www.81812333.com重新绑定手机号。
      "UnbindingUserPhoneNumber": "SMS_475840188",
      //解绑邮箱 尊敬的用户您好:818平台${account}的账号与${mail}已解绑,你可以登录网址:https://www.81812333.com重新绑定邮箱。
      "UnbindingUserEmail": "SMS_475875117",
      //818实名认证 验证码${code},您正在进行实名认证操作,请勿泄露,若非本人操作请忽略。
      "UserCertificationAudit": "SMS_471230080",
      //申请数字证书 验证码${code},用户您好,您正在申请数字证书,验证码10分钟内有效。
      "ApplyUserCertificate": "SMS_475345383",
      //电子签 ${unit_name}请您点击签约t.81812333.com/Inter/${code}
      "UserElectronSign": "SMS_476485061",
      //818钱包开通 验证码${code},用户您好,您正在进行平台钱包开通,该验证码5分钟内有效,请勿泄露于他人。
      "BankWalletAccountOpen": "SMS_473860301"
    }
  }
}