Przeglądaj źródła

1、修复获取部门没有根据用户权限获取
2、新增公告栏发布、获取、删除功能

MY 4 tygodni temu
rodzic
commit
c02b0e3b72

+ 4 - 4
JLHHJSvr/BLL/UserHelper.cs

@@ -211,7 +211,7 @@ namespace JLHHJSvr.BLL
         public static List<int> getPowerDept(SqlCommand cmd, int empid)
         {
             List<int> rslt = new List<int>();
-            var powerstr = "-1";
+            var powerstr = "0";
             string userid;
 
             cmd.CommandText = @"SELECT deptstr,userid FROM u_user_jlhprice WHERE Empid=@empid";
@@ -226,17 +226,17 @@ namespace JLHHJSvr.BLL
                     userid = reader["userid"].ToString().Trim();
                     if (userid.ToLower() == "super")
                     {
-                        powerstr = "0";
+                        powerstr = "-1";
                     }
                 }
             }
 
-            if (string.IsNullOrEmpty(powerstr) || powerstr.Equals("-1"))
+            if (string.IsNullOrEmpty(powerstr) || powerstr.Equals("0"))
             {
                 return rslt;
             }
             cmd.CommandText = "select deptid from u_dept";
-            if (powerstr != "0")
+            if (powerstr != "-1")
             {
                 cmd.CommandText += string.Format(" WHERE deptid IN ({0})", powerstr.Trim(','));
             }

+ 22 - 0
JLHHJSvr/Com/DeleteSysPostMessage.cs

@@ -0,0 +1,22 @@
+using JLHHJSvr.Com.Model;
+using LJLib.Net.SPI.Com;
+
+namespace JLHHJSvr.Com
+{
+    public sealed class DeleteSysPostMessageRequest : ILJRequest<DeleteSysPostMessageResponse>
+    {
+        public override string GetApiName()
+        {
+            return "DeleteSysPostMessage";
+        }
+        public string token { get; set; }
+        /// <summary>
+        /// 公告栏信息
+        /// </summary>
+        public int postid { get; set; }
+    }
+
+    public sealed class DeleteSysPostMessageResponse : LJResponse
+    {
+    }
+}

+ 28 - 0
JLHHJSvr/Com/Model/u_sys_post.cs

@@ -0,0 +1,28 @@
+using LJLib.DAL.SQL;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace JLHHJSvr.Com.Model
+{
+    [PK(new[] { "postid" })]
+    public sealed class u_sys_post
+    {
+        public int scid { get; set; }
+        public int? postid { get; set; }
+        public int deptid { get; set; }
+        public int empid { get; set; }
+        public DateTime? sdate { get; set; }
+        public DateTime? edate { get; set; }
+        public string dscrp { get; set; }
+        public string opemp { get; set; }
+        public DateTime? opdate { get; set; }
+        public byte? level { get; set; }
+        /// <summary>
+        /// 0 - 公告栏 1 - 员工提醒
+        /// </summary>
+        public byte? type { get; set; }
+    }
+}

+ 22 - 0
JLHHJSvr/Com/SaveSysPost.cs

@@ -0,0 +1,22 @@
+using JLHHJSvr.Com.Model;
+using LJLib.Net.SPI.Com;
+
+namespace JLHHJSvr.Com
+{
+    public sealed class SaveSysPostRequest : ILJRequest<SaveSysPostResponse>
+    {
+        public override string GetApiName()
+        {
+            return "SaveSysPost";
+        }
+        public string token { get; set; }
+        /// <summary>
+        /// 公告栏信息
+        /// </summary>
+        public u_sys_post postMessage { get; set; }
+    }
+
+    public sealed class SaveSysPostResponse : LJResponse
+    {
+    }
+}

+ 35 - 0
JLHHJSvr/DataStore/web_sys_post_list.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<select>
+  <selectstr>
+	SELECT u_sys_post.postid
+		,u_sys_post.scid
+		,u_sys_post.deptid
+		,u_sys_post.empid
+		,u_sys_post.sdate
+		,u_sys_post.edate
+		,u_sys_post.dscrp
+		,u_sys_post.opemp
+		,u_sys_post.opdate
+		,u_sys_post.level
+		,u_sys_post.type
+		,CASE WHEN u_sys_post.empid = -1 THEN '全部用户' ELSE u_user_jlhprice.username END AS username
+	FROM u_sys_post
+	LEFT OUTER JOIN u_user_jlhprice ON u_sys_post.empid = u_user_jlhprice.empid
+  </selectstr>
+  <where>
+	<when notnull="@type">
+		u_sys_post.type = @type
+	</when>
+	<when notnull="@empid">
+		u_sys_post.empid = -1 OR @empid = 0 OR u_sys_post.empid = @empid
+	</when>
+	<when>
+		getdate() >= u_sys_post.sdate AND getdate() <= u_sys_post.edate
+	</when>
+  </where>
+  <orderstr>
+	opdate DESC
+  </orderstr>
+  <displayfields>
+  </displayfields>
+</select>

+ 181 - 0
JLHHJSvr/Excutor/AdminTestFunctionExcutor.cs

@@ -0,0 +1,181 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using DirectService.Tools;
+using JLHHJSvr.BLL;
+using JLHHJSvr.Com;
+using JLHHJSvr.Com.Model;
+using JLHHJSvr.DBA.DBModle;
+using JLHHJSvr.Helper;
+using JLHHJSvr.LJException;
+using LJLib.DAL.SQL;
+using LJLib.Net.SPI.Server;
+using LJLib.SQLEX;
+using LJLib.TextLog;
+using LJLib.Tools.Encry;
+using Newtonsoft.Json.Linq;
+
+namespace JLHHJSvr.Excutor
+{
+    internal sealed class AdminTestFunctionExcutor : ExcutorBase<AdminTestFunctionRequest, AdminTestFunctionResponse>
+    {
+        string path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log"), "filterlog.log");
+        string path2 = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log"), "filterlog_result2.log");
+        protected override void ExcuteInternal(AdminTestFunctionRequest request, object state2, AdminTestFunctionResponse rslt)
+        {
+            //FilterLogs("8:00", "16:00");
+
+
+            psw_bczh3 pswhelper = new psw_bczh3();
+            var psw = pswhelper.GetEntrypt(request.requestStr, 1, "123457851239866");
+            rslt.resultStr = psw;
+
+            //new RequestLogger();
+
+            //string path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log"), "filterlog.log");
+            //string path2 = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log"), "filterlog_result.log");
+            //#region
+            //try
+            //{
+            //    var filteredLogs = new List<string>();
+            //    int matchCount = 0;
+            //    var currentBlock = new StringBuilder(1024);
+            //    bool isTargetRequest = false;
+            //    bool hasTargetMattressId = false;
+
+            //    foreach (string line in File.ReadLines(path))
+            //    {
+            //        if (line.StartsWith("===================================================================="))
+            //        {
+            //            // 检查当前块是否匹配
+            //            if (isTargetRequest && hasTargetMattressId)
+            //            {
+            //                filteredLogs.Add(currentBlock.ToString());
+            //                matchCount++;
+            //            }
+
+            //            // 重置状态,开始新块
+            //            currentBlock.Clear();
+            //            isTargetRequest = false;
+            //            hasTargetMattressId = false;
+            //        }
+
+            //        currentBlock.AppendLine(line);
+
+            //        // 快速检测关键信息
+            //        if (line.Contains("SaveMattressInterfaceRequest请求报文:"))
+            //        {
+            //            isTargetRequest = true;
+            //        }
+
+            //        if (isTargetRequest && line.Contains("\"mattressid\":21665686"))
+            //        {
+            //            hasTargetMattressId = true;
+            //        }
+            //    }
+
+            //    // 检查最后一个块
+            //    if (isTargetRequest && hasTargetMattressId)
+            //    {
+            //        filteredLogs.Add(currentBlock.ToString());
+            //        matchCount++;
+            //    }
+
+            //    File.WriteAllText(path2, string.Join("\n\n", filteredLogs));
+            //    Console.WriteLine($"筛选完成!共找到 {matchCount} 条符合条件的日志");
+            //}
+            //catch (Exception ex)
+            //{
+            //    Console.WriteLine($"错误: {ex.Message}");
+            //}
+            //#endregion
+        }
+
+
+        private void FilterLogs(string startTimeInput, string endTimeInput)
+        {
+            try
+            {
+                TimeSpan startTime = TimeSpan.Parse(startTimeInput);
+                TimeSpan endTime = TimeSpan.Parse(endTimeInput);
+
+                var filteredLogs = new List<string>();
+                int matchCount = 0;
+                var currentBlock = new StringBuilder(1024);
+                bool isTargetRequest = false;
+                bool hasTargetMattressId = false;
+                DateTime? currentTime = null;
+
+                foreach (string line in File.ReadLines(path))
+                {
+                    if (line.StartsWith("===================================================================="))
+                    {
+                        // 检查当前块是否在指定时间范围内且包含目标mattressid
+                        if (currentTime.HasValue && IsInTimeRange(currentTime.Value, startTime, endTime) &&
+                            isTargetRequest && hasTargetMattressId)
+                        {
+                            filteredLogs.Add(currentBlock.ToString());
+                            matchCount++;
+                        }
+
+                        // 重置状态
+                        currentBlock.Clear();
+                        isTargetRequest = false;
+                        hasTargetMattressId = false;
+                        currentTime = null;
+                    }
+
+                    currentBlock.AppendLine(line);
+
+                    // 解析时间
+                    if (line.StartsWith("时间:") && currentTime == null)
+                    {
+                        string timeStr = line.Substring(3).Trim();
+                        if (DateTime.TryParse(timeStr, out DateTime parsedTime))
+                        {
+                            currentTime = parsedTime;
+                        }
+                    }
+
+                    // 检测关键信息
+                    if (line.Contains("RefreshMattressInterfaceQdRequest请求报文:") || line.Contains("SaveMattressInterfaceRequest请求报文:"))
+                    {
+                        isTargetRequest = true;
+                    }
+
+                    if (line.Contains("\"mattressid\":21669844"))
+                    {
+                        hasTargetMattressId = true;
+                    }
+                }
+
+                // 处理最后一个块
+                if (currentTime.HasValue && IsInTimeRange(currentTime.Value, startTime, endTime) &&
+                    isTargetRequest && hasTargetMattressId)
+                {
+                    filteredLogs.Add(currentBlock.ToString());
+                    matchCount++;
+                }
+
+                File.WriteAllText(path2, string.Join("\n\n", filteredLogs));
+                Console.WriteLine($"筛选完成!共找到 {matchCount} 条 {startTime}-{endTime} 时间段的日志");
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"错误: {ex.Message}");
+            }
+        }
+        private static bool IsInTimeRange(DateTime time, TimeSpan start, TimeSpan end)
+        {
+            TimeSpan currentTime = time.TimeOfDay;
+            return currentTime >= start && currentTime <= end;
+        }
+    }
+}

+ 46 - 0
JLHHJSvr/Excutor/DeleteSysPostMessageExcutor.cs

@@ -0,0 +1,46 @@
+using System;
+using DirectService.Tools;
+using JLHHJSvr.BLL;
+using JLHHJSvr.Com;
+using JLHHJSvr.Helper;
+using LJLib.DAL.SQL;
+using LJLib.Net.SPI.Server;
+using LJLib.SQLEX;
+
+namespace JLHHJSvr.Excutor
+{
+    internal sealed class DeleteSysPostMessageExcutor : ExcutorBase<DeleteSysPostMessageRequest, DeleteSysPostMessageResponse>
+    {
+        protected override void ExcuteInternal(DeleteSysPostMessageRequest request, object state, DeleteSysPostMessageResponse rslt)
+        {
+            var tokendata = BllHelper.GetToken(request.token);
+            if (tokendata == null)
+            {
+                rslt.ErrMsg = "会话已经中断,请重新登录";
+                return;
+            }
+
+            using (var con = GlobalVar.ConnectionString.NewSqlConnection())
+            using (var cmd = con.CreateCommand())
+            {
+                con.Open();
+
+                var baseHelper = HelperBase.GetHelper<BasicInfoHelper>(cmd, new HelperBase.Context() { tokendata = tokendata });
+
+                using (cmd.Transaction = con.BeginTransaction())
+                {
+                    try
+                    {
+                        baseHelper.DeleteSysPostMessage(request.postid);
+                        cmd.Transaction.Commit();
+                    }
+                    catch (Exception e)
+                    {
+                        rslt.ErrMsg = e.Message;
+                        cmd.Transaction?.Rollback();
+                    }
+                }
+            }
+        }
+    }
+}

+ 14 - 0
JLHHJSvr/Excutor/GetDeptExcutor.cs

@@ -3,10 +3,12 @@ using System.Collections.Generic;
 using System.Data.SqlClient;
 using System.Linq;
 using System.Text;
+using DirectService.Tools;
 using JLHHJSvr.BLL;
 using JLHHJSvr.Com;
 using JLHHJSvr.Com.Model;
 using JLHHJSvr.DBA.DBModle;
+using JLHHJSvr.LJException;
 using LJLib.DAL.SQL;
 using LJLib.Net.SPI.Server;
 using LJLib.SQLEX;
@@ -29,6 +31,18 @@ namespace JLHHJSvr.Excutor
                 con.Open();
 
                 rslt.list = new List<u_dept>();
+
+                var whereList = new List<string>();
+
+                var powerDeptList = UserHelper.getPowerDept(cmd, tokendata.empid);
+                if(powerDeptList != null && powerDeptList.Count > 0)
+                {
+                    whereList.Add($"u_dept.deptid IN {ListEx.getString(powerDeptList)}");
+                } else
+                {
+                    throw new LJCommonException("该用户没有相关权限部门,请检查!");
+                }
+
                 DbSqlHelper.Select(cmd, "u_dept", null, null, null, 0, 0, rslt.list, null,
                     "deptid, deptname, profitrate, pricelistid, springtypeid, flag");
             }

+ 59 - 0
JLHHJSvr/Excutor/SaveSysPostExcutor.cs

@@ -0,0 +1,59 @@
+using System;
+using DirectService.Tools;
+using JLHHJSvr.BLL;
+using JLHHJSvr.Com;
+using JLHHJSvr.Helper;
+using LJLib.DAL.SQL;
+using LJLib.Net.SPI.Server;
+using LJLib.SQLEX;
+
+namespace JLHHJSvr.Excutor
+{
+    internal sealed class SaveSysPostExcutor : ExcutorBase<SaveSysPostRequest, SaveSysPostResponse>
+    {
+        protected override void ExcuteInternal(SaveSysPostRequest request, object state, SaveSysPostResponse rslt)
+        {
+            var tokendata = BllHelper.GetToken(request.token);
+            if (tokendata == null)
+            {
+                rslt.ErrMsg = "会话已经中断,请重新登录";
+                return;
+            }
+
+            if (request.postMessage == null)
+            {
+                rslt.ErrMsg = "未提交公告栏信息";
+                return;
+            }
+
+            if (string.IsNullOrEmpty(request.postMessage.dscrp))
+            {
+                rslt.ErrMsg = "公告内容不能为空,请检查!";
+                return;
+            }
+
+            using (var con = GlobalVar.ConnectionString.NewSqlConnection())
+            using (var cmd = con.CreateCommand())
+            {
+                con.Open();
+
+                var baseHelper = HelperBase.GetHelper<BasicInfoHelper>(cmd, new HelperBase.Context() { tokendata = tokendata });
+                var _message = ObjectHelper.DeepCopy(request.postMessage);
+
+                using (cmd.Transaction = con.BeginTransaction())
+                {
+                    try
+                    {
+                        baseHelper.SaveSysPostMessage(_message);
+                        cmd.Transaction.Commit();
+                    }
+                    catch (Exception e)
+                    {
+                        rslt.ErrMsg = e.Message;
+                        cmd.Transaction?.Rollback();
+                    }
+                }
+            }
+        }
+    }
+}

+ 5 - 0
JLHHJSvr/GlobalVar/GlobalVar.cs

@@ -266,6 +266,11 @@ namespace JLHHJSvr
                 excutorManager.AddMap("GetErpMtrlPriceList", typeof(GetErpMtrlPriceListRequest), new GetErpMtrlPriceListExcutor()); // 获取ERP物料资料定义
                 excutorManager.AddMap("GetChangeSoftBedMxList", typeof(GetChangeSoftBedMxListRequest), new GetChangeSoftBedMxListExcutor()); // 获取软床报价换料后明细
                 excutorManager.AddMap("SaveMattressSubSpecs", typeof(SaveMattressSubSpecsRequest), new SaveMattressSubSpecsExcutor()); // 获取软床报价换料后明细
+                excutorManager.AddMap("SaveSysPost", typeof(SaveSysPostRequest), new SaveSysPostExcutor()); // 发布公告
+                excutorManager.AddMap("DeleteSysPostMessage", typeof(DeleteSysPostMessageRequest), new DeleteSysPostMessageExcutor()); // 删除公告
+
+                /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+                //excutorManager.AddMap("AdminTestFunction", typeof(AdminTestFunctionRequest), new AdminTestFunctionExcutor());
             }
             catch (Exception ex)
             {

+ 41 - 0
JLHHJSvr/Helper/BasicInfoHelper.cs

@@ -2,6 +2,7 @@
 using JLHHJSvr.BLL;
 using JLHHJSvr.Com.Model;
 using JLHHJSvr.LJException;
+using JLHHJSvr.Tools;
 using LJLib.DAL.SQL;
 using NPOI.SS.Formula;
 using NPOI.SS.Formula.Functions;
@@ -168,5 +169,45 @@ namespace JLHHJSvr.Helper
 
             return mtrldefList;
         }
+
+        public void SaveSysPostMessage(u_sys_post message)
+        {
+            if (message == null)
+            {
+                throw new LJCommonException("未提交公告栏信息!");
+            }
+
+            if (string.IsNullOrEmpty(message.dscrp))
+            {
+                throw new LJCommonException($"公告内容不能为空,请检查!");
+            }
+
+            if(message.type == 1 && message.empid == 0)
+            {
+                throw new LJCommonException("不允许向超级管理员发布提醒!");
+            }
+
+            AutoInit.AutoInitS(message);
+            //
+            message.sdate = message.sdate.Value.Date;
+            message.edate = message.edate.Value.Date.AddDays(1).AddSeconds(-1);
+            // 新建
+            message.postid = BllHelper.GetID(cmd, "u_sys_post");
+            message.opdate = context.opdate;
+            message.opemp = context.tokendata.username;
+
+            DbSqlHelper.Insert(cmd, "u_sys_post", null, message, "postid,scid,deptid,empid,sdate,edate,dscrp,opemp,opdate,level,type");
+        }
+
+        public void DeleteSysPostMessage(int postid)
+        {
+            if (postid == 0)
+            {
+                throw new LJCommonException("删除公告id有误,请检查!");
+            }
+
+            var message = new u_sys_post() { postid = postid };
+            DbSqlHelper.Delete(cmd, message);
+        }
     }
 }

+ 5 - 0
JLHHJSvr/JLHHJSvr.csproj

@@ -107,6 +107,7 @@
     <Compile Include="Com\DeleteMattressExtraType.cs" />
     <Compile Include="Com\DeleteMattressExtra.cs" />
     <Compile Include="Com\DeleteSoftBedQuote.cs" />
+    <Compile Include="Com\DeleteSysPostMessage.cs" />
     <Compile Include="Com\GetBedNetInterfaceList.cs" />
     <Compile Include="Com\GetChangeSoftBedMxList.cs" />
     <Compile Include="Com\GetComputeMattressById.cs" />
@@ -142,6 +143,7 @@
     <Compile Include="Com\Model\u_softbed.cs" />
     <Compile Include="Com\Model\u_softbed_formula.cs" />
     <Compile Include="Com\Model\u_softbed_mx.cs" />
+    <Compile Include="Com\Model\u_sys_post.cs" />
     <Compile Include="Com\PingToken.cs" />
     <Compile Include="Com\ReCalculateERPCost.cs" />
     <Compile Include="Com\RefreshBedNetInterface.cs" />
@@ -154,6 +156,7 @@
     <Compile Include="Com\SaveMattressSubSpecs.cs" />
     <Compile Include="Com\SaveSoftBedFormula.cs" />
     <Compile Include="Com\SaveSoftBedQuote.cs" />
+    <Compile Include="Com\SaveSysPost.cs" />
     <Compile Include="Com\UnLockUser.cs" />
     <Compile Include="Com\UpdateL1Basicinfo.cs" />
     <Compile Include="Com\UpdateMtrlPrice.cs" />
@@ -343,6 +346,7 @@
     <Compile Include="Excutor\DeleteMattressExtraTypeExcutor.cs" />
     <Compile Include="Excutor\DeleteMattressExtraExcutor.cs" />
     <Compile Include="Excutor\DeleteSoftBedQuoteExcutor.cs" />
+    <Compile Include="Excutor\DeleteSysPostMessageExcutor.cs" />
     <Compile Include="Excutor\FormulaCheckExcutor.cs" />
     <Compile Include="Excutor\GetBedNetInterfaceListExcutor.cs" />
     <Compile Include="Excutor\GetChangeSoftBedMxListExcutor.cs" />
@@ -368,6 +372,7 @@
     <Compile Include="Excutor\SaveMattressSubSpecsExcutor.cs" />
     <Compile Include="Excutor\SaveSoftBedFormulaExcutor.cs" />
     <Compile Include="Excutor\SaveSoftBedQuoteExcutor.cs" />
+    <Compile Include="Excutor\SaveSysPostExcutor.cs" />
     <Compile Include="Excutor\UnLockUserExcutor.cs" />
     <Compile Include="Excutor\UpdateL1BasicinfoExcutor.cs" />
     <Compile Include="Excutor\UpdateMtrlPriceExcutor.cs" />

+ 6 - 0
JLHWEB/src/api/interface/index.ts

@@ -1230,6 +1230,12 @@ export namespace Basicinfo {
   export interface ReqSaveErpMtrlPrice {
     mtrldefList: any[];
   }
+  export interface ReqSaveSysPost {
+    postMessage: any;
+  }
+  export interface ReqDeleteSysPost {
+    postid: number;
+  }
 }
 
 export namespace SalePrice {

+ 8 - 0
JLHWEB/src/api/modules/basicinfo.ts

@@ -27,6 +27,14 @@ export const getDept = () => {
   return http.post<SalePrice.ResPriceList>(PORT1 + `/GetDept`, {});
 };
 
+export const saveSysPost = (params: Basicinfo.ReqSaveSysPost) => {
+  return http.post(PORT1 + `/SaveSysPost`, params);
+};
+
+export const deleteSysPost = (params: Basicinfo.ReqDeleteSysPost) => {
+  return http.post(PORT1 + `/DeleteSysPostMessage`, params);
+};
+
 /**
  * @name 获取 床网类别定义列表
  */

+ 55 - 15
JLHWEB/src/views/home/components/SysPost/index.vue

@@ -8,7 +8,7 @@
             <i class="iconfont iconRefresh_light"></i>
           </template>
         </el-button>
-        <el-button class="default-btn" text round @click="toSendSysPost">
+        <el-button v-if="isSuper" class="default-btn" text round @click="toSendSysPost">
           <template #icon>
             <i class="iconfont iconPlus_light"></i>
           </template>
@@ -38,23 +38,35 @@
                     </span>
                   </div>
                   <div class="tag-list mt-2">
-                    <span class="text-f-c text-secondary-text">
-                      {{ formatToDate(item.opdate, "YYYY-MM-DD HH:mm") }}
-                    </span>
+                    <i
+                      class="iconfont icontrash-01 delete-icon text-secondary-text"
+                      v-if="isSuper"
+                      @click="onDeletePost(item.postid)"
+                    />
                   </div>
                 </div>
                 <div class="flx">
-                  <span class="text-body-m text-primary-text break-word">
+                  <span class="text-body-m text-primary-text break-word" :class="`post-message-${levelTypeMap.get(item.level)}`">
                     {{ item.dscrp }}
                   </span>
                 </div>
-                <div class="flx-end">
-                  <span class="text-secondary-text">
-                    <i class="iconfont iconSend_light" />
-                  </span>
-                  <span class="text-f-c text-secondary-text">
-                    {{ item.departmentname }}
-                  </span>
+                <div class="flx-justify-between">
+                  <div class="flx-start">
+                    <span class="text-f-c text-secondary-text">
+                      {{ formatToDate(item.opdate, "YYYY-MM-DD HH:mm") }}
+                    </span>
+                    <!-- <el-tag :type="levelTypeMap.get(item.level)" effect="Light" size="small">
+                      {{ levelMap.get(item.level) }}
+                    </el-tag> -->
+                  </div>
+                  <div class="flx-end flx-align-center">
+                    <span class="text-secondary-text">
+                      <!-- <i class="iconfont iconSend_light" /> -->
+                    </span>
+                    <span class="text-f-c text-secondary-text">
+                      <!-- {{ item.deptname }} -->
+                    </span>
+                  </div>
                 </div>
               </div>
             </header>
@@ -73,14 +85,16 @@ import { useDesign } from "@/hooks/useDesign";
 import { useI18n } from "vue-i18n";
 import { numberFormat } from "@/utils/index";
 import { formatToDate } from "@/utils/dateUtil";
+import { useGlobalStore } from "@/stores/modules/global";
+import { useUserStore } from "@/stores/modules/user";
 
 const { prefixCls } = useDesign("home_widget-mySysPost");
 const { t } = useI18n();
 const MySysPost = ref();
 const loading = ref();
-const emit = defineEmits(["getSysPostList", "sendSysPost"]);
+const emit = defineEmits(["getSysPostList", "sendSysPost", "deleteSysPost"]);
 const dataList = inject("sysPostList", ref<any>([]));
-
+const isSuper = useGlobalStore().isSuper || useUserStore().userInfo.usermode === 0;
 // 刷新
 const toRefresh = async () => {
   loading.value = true;
@@ -93,12 +107,28 @@ const toRefresh = async () => {
   });
 };
 
+const levelMap = new Map([
+  [0, "低"],
+  [1, "中"],
+  [2, "高"]
+]);
+
+const levelTypeMap = new Map([
+  [0, "info"],
+  [1, "warning"],
+  [2, "danger"]
+]);
+
 const refresh = async (callback?: any) => {
   emit("getSysPostList", () => callback && callback());
 };
 
 const toSendSysPost = async () => {
-  emit("sendSysPost");
+  emit("sendSysPost", 0);
+};
+
+const onDeletePost = (postid: number) => {
+  emit("deleteSysPost", postid, 0);
 };
 
 /**
@@ -147,4 +177,14 @@ onUnmounted(() => {
 
 <style lang="scss" scoped>
 @import "./index.scss";
+
+.post-message-info {
+  color: #666666;
+}
+.post-message-warning {
+  color: #ff8c00;
+}
+.post-message-danger {
+  color: #ff0000;
+}
 </style>

+ 53 - 17
JLHWEB/src/views/home/components/UserPost/index.vue

@@ -8,7 +8,7 @@
             <i class="iconfont iconRefresh_light"></i>
           </template>
         </el-button>
-        <el-button class="default-btn" text round @click="toSendSysPost">
+        <el-button v-if="isSuper" class="default-btn" text round @click="toSendSysPost">
           <template #icon>
             <i class="iconfont iconPlus_light"></i>
           </template>
@@ -26,7 +26,7 @@
         </el-skeleton>
       </div>
       <div v-else>
-        <div v-if="!dataList.length" class="empty text-disable">暂无数据</div>
+        <div v-if="!dataList.length" class="empty text-disable">暂没有公告</div>
         <div v-else :class="`${prefixCls}__grid`">
           <section :class="`${prefixCls}__post-item`" v-for="(item, index) in dataList" :key="index">
             <header class="flx-start">
@@ -38,23 +38,35 @@
                     </span>
                   </div>
                   <div class="tag-list mt-2">
-                    <span class="text-f-c text-secondary-text">
-                      {{ formatToDate(item.opdate, "YYYY-MM-DD HH:mm") }}
-                    </span>
+                    <i
+                      class="iconfont icontrash-01 delete-icon text-secondary-text"
+                      v-if="isSuper"
+                      @click="onDeletePost(item.postid)"
+                    />
                   </div>
                 </div>
                 <div class="flx">
-                  <span class="text-body-m text-primary-text break-word">
+                  <span class="text-body-m text-primary-text break-word" :class="`post-message-${levelTypeMap.get(item.level)}`">
                     {{ item.dscrp }}
                   </span>
                 </div>
-                <div class="flx-end">
-                  <span class="text-secondary-text">
-                    <i class="iconfont iconSend_light" />
-                  </span>
-                  <span class="text-f-c text-secondary-text">
-                    {{ item.departmentname }}
-                  </span>
+                <div class="flx-justify-between">
+                  <div class="flx-start">
+                    <span class="text-f-c text-secondary-text">
+                      {{ formatToDate(item.opdate, "YYYY-MM-DD HH:mm") }}
+                    </span>
+                    <!-- <el-tag :type="levelTypeMap.get(item.level)" effect="Light" size="small">
+                      {{ levelMap.get(item.level) }}
+                    </el-tag> -->
+                  </div>
+                  <div class="flx-end flx-align-center">
+                    <span class="text-secondary-text">
+                      <i class="iconfont iconSend_light" />
+                    </span>
+                    <span class="text-f-c text-secondary-text">
+                      {{ item.username }}
+                    </span>
+                  </div>
                 </div>
               </div>
             </header>
@@ -73,13 +85,22 @@ import { useDesign } from "@/hooks/useDesign";
 import { useI18n } from "vue-i18n";
 import { numberFormat } from "@/utils/index";
 import { formatToDate } from "@/utils/dateUtil";
+import { useGlobalStore } from "@/stores/modules/global";
+import { useUserStore } from "@/stores/modules/user";
 
 const { prefixCls } = useDesign("home_widget-mySysPost");
 const { t } = useI18n();
 const MySysPost = ref();
 const loading = ref();
-const emit = defineEmits(["getSysPostList", "sendSysPost"]);
-const dataList = inject("sysPostList", ref<any>([]));
+const emit = defineEmits(["getSysPostUserList", "sendSysPost", "deleteSysPost"]);
+const dataList = inject("sysPostUserList", ref<any>([]));
+const isSuper = useGlobalStore().isSuper || useUserStore().userInfo.usermode === 0;
+
+const levelTypeMap = new Map([
+  [0, "info"],
+  [1, "warning"],
+  [2, "danger"]
+]);
 
 // 刷新
 const toRefresh = async () => {
@@ -94,11 +115,16 @@ const toRefresh = async () => {
 };
 
 const refresh = async (callback?: any) => {
-  emit("getSysPostList", () => callback && callback());
+  emit("getSysPostUserList", () => callback && callback());
+  // dataList.value = [];
 };
 
 const toSendSysPost = async () => {
-  emit("sendSysPost");
+  emit("sendSysPost", 1);
+};
+
+const onDeletePost = (postid: number) => {
+  emit("deleteSysPost", postid, 1);
 };
 
 /**
@@ -147,4 +173,14 @@ onUnmounted(() => {
 
 <style lang="scss" scoped>
 @import "./index.scss";
+
+.post-message-info {
+  color: #666666;
+}
+.post-message-warning {
+  color: #ff8c00;
+}
+.post-message-danger {
+  color: #ff0000;
+}
 </style>

+ 68 - 7
JLHWEB/src/views/home/index.vue

@@ -60,6 +60,7 @@
       <!-- <DragBall ref="DragBallRef" @setting="OpenSettingHomeWidget" /> -->
     </el-container>
   </div>
+  <SysPostEditorDialog ref="SysPostEditorRef" @confirm="onSysPostConfirm" />
 </template>
 
 <script setup lang="ts" name="home">
@@ -77,7 +78,7 @@ import {
   watch,
   inject
 } from "vue";
-import { ElMessage } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import { streamlineFunc } from "@/utils";
 import { useLayoutLocalStore } from "@/stores/modules/layoutLocal";
 import { useLayoutStore } from "@/stores/modules/layout";
@@ -95,6 +96,8 @@ import { CommonDynamicSelect } from "@/api/modules/common";
 import { useUserStore } from "@/stores/modules/user";
 import type { Menu } from "@/typings/global";
 import { useAuthStore } from "@/stores/modules/auth";
+import SysPostEditorDialog from "@/views/system/syspost-editor/index.vue";
+import { saveSysPost, deleteSysPost } from "@/api/modules/basicinfo";
 
 const authStore = useAuthStore();
 
@@ -136,6 +139,7 @@ const layoutStore = useLayoutStore();
 const globalStore = useGlobalStore();
 const dwLayout = ref<any>({});
 const LayoutSettingRef = ref();
+const SysPostEditorRef = ref();
 // const dialogOutwareRef = ref();
 const DragBallRef = ref();
 const iframeRefs: any = {};
@@ -158,6 +162,9 @@ const rightLayoutSpan = ref(6);
 const sysPostList = ref<any>([]);
 provide("sysPostList", sysPostList);
 
+const sysPostUserList = ref<any>([]);
+provide("sysPostUserList", sysPostUserList);
+
 const initComponetList = ["QuickEnter", "SysPost", "UserPost"];
 /**
  * @description 功能展示布局,默认设置
@@ -423,29 +430,83 @@ const comEvent = {
    * @param callback 回调函数
    */
   async getSysPostList(callback?: any) {
-    // let data = await getSysPostData();
-    // sysPostList.value = data.datatable ?? [];
+    let data = await getSysPostData();
+    sysPostList.value = data.datatable ?? [];
     callback && callback();
   },
   /**
    * @description 发送公告栏
    */
-  async sendSysPost() {
-    alert("功能维护中,敬请期待!");
+  async sendSysPost(type) {
+    // alert("功能维护中,敬请期待!");
+    SysPostEditorRef.value.show(type);
+  },
+  /**
+   * @description 获取公告栏信息
+   * @param callback 回调函数
+   */
+  async getSysPostUserList(callback?: any) {
+    let data = await getSysPostUserData();
+    sysPostUserList.value = data.datatable ?? [];
+    callback && callback();
+  },
+  /**
+   * @description 删除公告栏提醒
+   * @param callback 回调函数
+   */
+  async deleteSysPost(postid: number, type: number) {
+    ElMessageBox.confirm(`是否删除公告?`, "温馨提示", {
+      confirmButtonText: "确定",
+      cancelButtonText: "取消",
+      draggable: true
+    }).then(async () => {
+      await deleteSysPost({ postid });
+      ElMessage({
+        type: "success",
+        message: `删除公告成功!`
+      });
+      if (type === 1) {
+        comEvent.getSysPostUserList();
+      } else {
+        comEvent.getSysPostList();
+      }
+    });
   }
 };
 
 const getSysPostData = () => {
   let newParams = {
-    dsname: "L1WEB_GetSysPostList",
+    dsname: "web_sys_post_list",
+    queryParams: {
+      scid: userInfo.scid,
+      type: 0
+    }
+  };
+  return CommonDynamicSelect(newParams);
+};
+
+const getSysPostUserData = () => {
+  let newParams = {
+    dsname: "web_sys_post_list",
     queryParams: {
       scid: userInfo.scid,
-      deptid: userInfo.deptid
+      empid: userInfo.empid,
+      type: 1
     }
   };
   return CommonDynamicSelect(newParams);
 };
 
+const onSysPostConfirm = async (type: number, postMessage: any) => {
+  await saveSysPost({ postMessage });
+
+  if (type === 1) {
+    comEvent.getSysPostUserList();
+  } else {
+    comEvent.getSysPostList();
+  }
+};
+
 /**
  * @description 点击设置按钮
  */

+ 111 - 0
JLHWEB/src/views/system/syspost-editor/editor.vue

@@ -0,0 +1,111 @@
+<template>
+  <div class="editor-container">
+    <el-form :model="editorForm" label-position="top" require-asterisk-position="right" inline size="default">
+      <el-col :span="24" v-if="type === 1">
+        <!-- <el-form-item label="部门选择" required>
+          <el-select v-model="editorForm.deptid" placeholder="请选择部门" filterable>
+            <el-option v-for="(col, index) in deptEnum" :key="index" :label="col.label" :value="col.value"></el-option>
+          </el-select>
+        </el-form-item> -->
+        <el-form-item label="用户选择" required>
+          <el-select v-model="editorForm.empid" placeholder="请选择用户" filterable>
+            <el-option v-for="(col, index) in empEnum" :key="index" :label="col.label" :value="col.value"></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="公告内容" required>
+          <el-input v-model="editorForm.dscrp" type="textarea" :rows="5" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="开始时间" required>
+          <el-date-picker v-model="editorForm.sdate" type="date" placeholder="Pick a date" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="结束时间" required>
+          <el-date-picker v-model="editorForm.edate" type="date" placeholder="Pick a date" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="优先级" required>
+          <el-radio-group v-model="editorForm.level">
+            <el-radio :value="0">低</el-radio>
+            <el-radio :value="1">中</el-radio>
+            <el-radio :value="2">高</el-radio>
+          </el-radio-group>
+        </el-form-item>
+      </el-col>
+    </el-form>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive, onMounted } from "vue";
+import { getDept, getUserList } from "@/api/modules/basicinfo";
+import { useUserStore } from "@/stores/modules/user";
+
+const props = defineProps({
+  type: {
+    type: Number,
+    default: 1
+  } // 0 - 公告栏 1 - 用户提醒
+});
+
+const editorForm = reactive({
+  scid: 0,
+  deptid: 0,
+  empid: 0,
+  type: 0,
+  dscrp: "",
+  sdate: new Date(),
+  edate: new Date(),
+  level: 1 // 0(低)、1(中)、2(高)
+});
+
+const deptEnum = ref([]);
+const empEnum = ref([{ label: "全部用户", value: -1 }]);
+onMounted(async () => {
+  if (props.type === 0) {
+    const result = await getDept();
+    deptEnum.value = result.list.map(t => {
+      return { label: t.deptname, value: t.deptid };
+    });
+    deptEnum.value.unshift({ label: "全部部门", value: -1 });
+
+    editorForm.deptid = -1;
+  }
+  if (props.type === 1) {
+    const result = await getUserList();
+    empEnum.value = result.userList
+      .filter(t => t.empid != 0 && t.empid != useUserStore().userInfo.empid)
+      .map(t => {
+        return { label: t.username, value: t.empid };
+      });
+    empEnum.value.unshift({ label: "全部用户", value: -1 });
+
+    editorForm.empid = -1;
+  }
+
+  editorForm.type = props.type;
+});
+
+defineExpose({ editorForm });
+</script>
+
+<style scoped lang="scss">
+.editor-container {
+  height: 100%;
+  // width: 100%;
+  // min-height: 510px;
+  --editor-border: #dcdfe6;
+  --panel-bg: #f8f9fa;
+  padding: 0 1.2rem;
+  overflow-x: hidden;
+
+  &::-webkit-scrollbar {
+    display: none; /* 隐藏滚动条但保留滚动功能 */
+  }
+}
+</style>

+ 152 - 0
JLHWEB/src/views/system/syspost-editor/index.vue

@@ -0,0 +1,152 @@
+<template>
+  <LjDialog
+    ref="LjSelectorRef"
+    class="is-selector lj-selector"
+    v-bind="{
+      ...drawerDefineProp
+    }"
+    :modal="false"
+    :style="{ height: '75%' }"
+  >
+    <template #header>
+      <div class="flx-1">
+        <span class="text-h5-b">{{ props.title }}</span>
+      </div>
+    </template>
+    <div class="flx-col h-full">
+      <LjHeaderMenu :update="dialogVisible" :data="initParams" :action="btnGroup" />
+      <LjFoldLayoutDouble v-bind="showLayout" class="flx-1 overflow-hidden">
+        <template #secondMain>
+          <div class="flx h-full">
+            <div class="flx-col w-full">
+              <Editor :type="editorType" ref="editorRef" />
+            </div>
+          </div>
+        </template>
+      </LjFoldLayoutDouble>
+    </div>
+  </LjDialog>
+</template>
+<script setup lang="ts">
+import { ref, computed, onMounted, onBeforeUnmount, nextTick, watch } from "vue";
+import LjDialog from "@/components/LjDialog/index.vue";
+import LjFoldLayoutDouble from "@/components/LjFoldLayoutDouble/index.vue";
+import Editor from "./editor.vue";
+import { useAuthButtons } from "@/hooks/useAuthButtons";
+import { useI18n } from "vue-i18n";
+
+const { t } = useI18n();
+const { buttonDefault } = useAuthButtons(t);
+
+const props = defineProps({
+  title: {
+    type: String,
+    default: "编辑公告"
+  }
+});
+
+const emit = defineEmits(["confirm"]);
+const LjSelectorRef = ref();
+const dialogVisible = ref(false);
+const editorRef = ref();
+const editorType = ref(0);
+/*
+ * @description 抽屉默认属性
+ */
+const drawerDefineProp = {
+  draggable: true,
+  overflow: true,
+  width: "40%",
+  modalClass: "lj-file-dialog"
+};
+const showLayout = ref<any>(false);
+const initParams = ref<any>();
+const btnGroup = ref<any>([
+  buttonDefault({
+    label: "确认",
+    clickFunc: item => {
+      handleConfirm();
+    }
+  }),
+  buttonDefault({
+    label: "取消",
+    clickFunc: item => {
+      hide();
+    }
+  })
+]);
+
+const handleConfirm = async () => {
+  emit("confirm", editorType.value, editorRef.value.editorForm);
+  hide();
+};
+
+/**
+ * @description 展示组件
+ * @param params 入参
+ * @param activeName 多选时 活动面板入参
+ */
+const show = (type: number, refresh?: boolean) => {
+  editorType.value = type;
+  LjSelectorRef.value.show(refresh);
+  nextTick(() => {
+    dialogVisible.value = true;
+  });
+};
+
+/**
+ * @description cancel 取消
+ */
+const hide = () => {
+  // 关闭弹窗
+  LjSelectorRef.value.hide();
+  dialogVisible.value = false;
+};
+
+defineExpose({
+  show,
+  hide
+});
+</script>
+
+<style lang="scss">
+.lj-selector {
+  padding: 0;
+  .el-tree {
+    background: unset;
+  }
+}
+.ljselector-aside-collapse {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  // background-color: $color-gray-2;
+
+  .el-collapse-item {
+    display: flex;
+    flex-direction: column;
+    overflow: auto;
+    height: auto;
+
+    &.is-active {
+      flex: 1;
+    }
+    &:not(.is-active) {
+      flex-shrink: 0;
+    }
+    .el-collapse-item__header {
+      flex-shrink: 0;
+    }
+    .el-collapse-item__wrap {
+      flex: 1;
+      overflow: auto;
+      background-color: $color-gray-2;
+      padding: 8px 4px;
+
+      .lj-infor-item {
+        background-color: $color-gray-1;
+      }
+    }
+  }
+}
+</style>