Răsfoiți Sursa

修改用户样式

GTong 9 luni în urmă
părinte
comite
d7fa137c8d

+ 2 - 2
config.toml

@@ -3,13 +3,13 @@ ip = "127.0.0.1"
 port = "8080"
 
 [database]
-oadb_ip = "127.0.0.1"
+oadb_ip = "10.28.20.233"
 oadb_port = "5138"
 oadb_db = "OAdb"
 oadb_user = "SYSDBA"
 oadb_password = "SYSDBA"
 
-licdb_ip = "127.0.0.1"
+licdb_ip = "10.28.20.233"
 licdb_port = "5138"
 licdb_db = "license"
 licdb_user = "SYSDBA"

+ 14 - 0
internal/api/license_api.go

@@ -1,5 +1,7 @@
 package api
 
+import "database/sql"
+
 type AllLicenseInfoResponse struct {
 	UniqueID               string `json:"UniqueID"` // 每行数据的唯一值ID,理论上有oa的REQUESTID就可以了
 	OAId                   int64  `json:"oa_id"`
@@ -85,3 +87,15 @@ type ConditionalSearchRequest struct {
 	EndDate      string `json:"end_date,omitempty"`
 	AnySearch    string `json:"any_search,omitempty"`
 }
+
+type UserInfoRequest struct {
+	Id        int           `json:"id,omitempty"`
+	UniqueID  string        `json:"unique_id,omitempty"`
+	Username  string        `json:"username,omitempty"`
+	Account   string        `json:"account,omitempty"`
+	Password  string        `json:"password,omitempty"`
+	Telephone string        `json:"telephone,omitempty"`
+	Email     string        `json:"email,omitempty"`
+	Role      string        `json:"role,omitempty"`
+	GroupId   sql.NullInt32 `json:"group_id,omitempty"`
+}

+ 40 - 12
internal/controllers/OALicenseInfo_controllers.go

@@ -671,26 +671,54 @@ func ConditionalSearchController(c *gin.Context) {
 		return
 	}
 
-	licInfos, _, err := services.GetConditionalSearchService(request)
+	//获取用户信息和权限
+	userInfo, err := getLoginInfo(c)
 	if err != nil {
-		c.JSON(400, gin.H{
-			"error": errors.Errorf("查询失败: %s", err.Error()),
-		})
-		return
+		c.JSON(http.StatusUnauthorized, gin.H{"error": "用户信息不存在"})
+		c.Abort()
 	}
 
-	if ret, err := returnLicenseInfo(licInfos); err != nil {
-		c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintln("数据转换失败: ", err.Error())})
-	} else {
-		c.JSON(http.StatusOK, gin.H{
-			"success": true,
-			"data":    ret,
-		})
+	if userInfo.Permission[middlewares.ReadAllLicense] == middlewares.ReadAllLicense {
+		licInfos, _, err := services.GetConditionalSearchService(request, middlewares.ReadAllLicense, userInfo.Account)
+		if err != nil {
+			c.JSON(400, gin.H{
+				"error": errors.Errorf("查询失败: %s", err.Error()),
+			})
+			return
+		}
+
+		if ret, err := returnLicenseInfo(licInfos); err != nil {
+			c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintln("数据转换失败: ", err.Error())})
+		} else {
+			c.JSON(http.StatusOK, gin.H{
+				"success": true,
+				"data":    ret,
+			})
+		}
+
+	} else if userInfo.Permission[middlewares.ReadLicense] == middlewares.ReadLicense {
+		licInfos, _, err := services.GetConditionalSearchService(request, middlewares.ReadLicense, userInfo.Account)
+		if err != nil {
+			c.JSON(400, gin.H{
+				"error": errors.Errorf("查询失败: %s", err.Error()),
+			})
+			return
+		}
+
+		if ret, err := returnLicenseInfo(licInfos); err != nil {
+			c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintln("数据转换失败: ", err.Error())})
+		} else {
+			c.JSON(http.StatusOK, gin.H{
+				"success": true,
+				"data":    ret,
+			})
+		}
 	}
 
 }
 
 func returnLicenseInfo(datas1 *[]models.OALicenseInfo) ([][]api.AllLicenseInfoResponse, error) {
+
 	// 初始化存储 `OARequestID` 相同的 `ApiLicenseInfoTemp` 列表的 map
 	oaRequestIDMap := make(map[int64][]api.AllLicenseInfoResponse)
 

+ 8 - 2
internal/controllers/user_controllers.go

@@ -5,6 +5,7 @@ import (
 	"net/http"
 	"regexp"
 
+	"xugu_license/internal/api"
 	"xugu_license/internal/global"
 	middlewares "xugu_license/internal/middleware"
 	"xugu_license/internal/models"
@@ -215,7 +216,7 @@ func UpdateUserInfo(c *gin.Context) {
 		c.Abort()
 	}
 
-	var req models.UserInfo
+	var req api.UserInfoRequest
 	if err := c.ShouldBindBodyWithJSON(&req); err != nil {
 		c.JSON(http.StatusBadRequest, gin.H{
 			"error": err.Error(),
@@ -225,7 +226,12 @@ func UpdateUserInfo(c *gin.Context) {
 	if userInfo.Permission[middlewares.UpdateRole] != middlewares.UpdateRole {
 		req.Role = userInfo.Role
 	}
-
+	//加密密码
+	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
+	if err != nil {
+		return
+	}
+	req.Password = string(hashedPassword)
 	fmt.Println("req", req)
 	if err := models.UpdateUserInfo(req); err != nil {
 		c.JSON(http.StatusBadRequest, gin.H{

+ 100 - 7
internal/models/license_oa_models.go

@@ -456,11 +456,46 @@ func CheckOaLicRequest(oaRequestID int64, userUNIQUEID string) (bool, error) {
 }
 
 // ------------------按搜索条件查询license表--------------------
-// 假设你有一个结构体保存传入的参数
-
-func buildSQL(params api.ConditionalSearchRequest) (string, []interface{}) {
+/*生成sql
+flag : 1 是全部
+		2 是用户拥有的license
+*/
+func buildConditionalSearchAllSQL(params api.ConditionalSearchRequest, flag int, user string) (string, []interface{}) {
 	// 基础SQL查询
-	baseSQL := `SELECT 
+	var baseSQL string
+
+	switch flag {
+	case 1:
+		baseSQL = `SELECT 
+		la.ID, la.Unique_ID, la.OA_ID, la.OA_REQUESTID, la.OA_REQUESTNAME, la.OA_REQUESTNAMENEW,
+		la.OA_REQUESTNAMEHTMLNEW, la.OA_GLXMID ,la.OA_GLXMNAME ,la.OA_SQSJ, la.OA_SALESPERSONNAME, la.OA_XSJSYX,
+		la.OA_OPERATIONSPERSONNAME, la.OA_JFJSYX, la.OA_SYDW, la.OA_XMXXMS, la.OA_JDS,
+		la.OA_NODECOUNT, la.OA_PRODUCTCODE, la.OA_PRODUCTNAME, la.OA_PRODUCTVERSION,
+		la.OA_CPU, la.OA_OPERATINGSYSTEM, la.OA_MAINMAC, la.OA_SECONDMAC, la.OA_CREATIONDATE,
+		la.OA_CREATIONTIME, la.OA_LASTOPERATEDATE, la.OA_LASTOPERATETIME, la.capture_Time,
+		la.del_Time, la.LAST_OPERATE_TIME,
+		li.ID AS License_ID, li.OA_ID, li.License_UniqueID, li.License_Flage, li.lic1, li.lic2, li.Creator_generate
+	FROM 
+		target_OA_license la
+	INNER JOIN 
+		License_generate_Info li
+		ON 
+		la.Unique_ID = li.License_UniqueID
+	WHERE 
+		OA_REQUESTID  IN (
+			SELECT OA_REQUESTID 
+			FROM (
+				SELECT OA_REQUESTID, rownum AS a 
+				FROM (
+					SELECT DISTINCT OA_REQUESTID FROM TARGET_OA_LICENSE
+				) a
+			) s
+			WHERE a BETWEEN 1 AND 1000
+		)
+		AND la.del_Time IS NULL
+	AND 1=1`
+	case 2:
+		baseSQL = fmt.Sprintf(`SELECT 
     la.ID, la.Unique_ID, la.OA_ID, la.OA_REQUESTID, la.OA_REQUESTNAME, la.OA_REQUESTNAMENEW,
     la.OA_REQUESTNAMEHTMLNEW, la.OA_GLXMID ,la.OA_GLXMNAME ,la.OA_SQSJ, la.OA_SALESPERSONNAME, la.OA_XSJSYX,
     la.OA_OPERATIONSPERSONNAME, la.OA_JFJSYX, la.OA_SYDW, la.OA_XMXXMS, la.OA_JDS,
@@ -475,6 +510,10 @@ INNER JOIN
     License_generate_Info li
     ON 
     la.Unique_ID = li.License_UniqueID
+INNER JOIN 
+    LICENSERECORDTOUSER ltr
+  	ON 
+    la.OA_REQUESTID = ltr.OA_REQUESTID AND ltr.USER_ACCOUNT = '%s'
 WHERE 
     OA_REQUESTID  IN (
         SELECT OA_REQUESTID 
@@ -487,7 +526,8 @@ WHERE
         WHERE a BETWEEN 1 AND 1000
     )
 	AND la.del_Time IS NULL
-AND 1=1`
+AND 1=1`, user)
+	}
 
 	// 动态条件部分
 	var conditions []string
@@ -519,7 +559,60 @@ AND 1=1`
 	return baseSQL, args
 }
 
-func GetConditionalSearch(params api.ConditionalSearchRequest) (*[]OALicenseInfo, int, error) {
+func GetConditionalSearchAll(params api.ConditionalSearchRequest) (*[]OALicenseInfo, int, error) {
+	total := 0
+	err := global.XuguDB.QueryRow(`
+		SELECT COUNT(*) from (SELECT OA_REQUESTID AS RequestCount
+		FROM TARGET_OA_LICENSE
+		where  Del_Time IS NULL
+		GROUP BY OA_REQUESTID 
+		)
+		HAVING COUNT(*) > 1;`).Scan(&total)
+	if err != nil {
+		return nil, 0, fmt.Errorf("count query error: %v", err)
+	}
+
+	// 构建SQL语句和参数
+	query, args := buildConditionalSearchAllSQL(params, 1, "")
+	// 输出SQL语句和参数
+	fmt.Println("Query:", query)
+	fmt.Println("Args:", args)
+	rows, err := global.XuguDB.Query(query, args...)
+	if err != nil {
+		global.Logger.Errorln("getLicInfoByOAUniqueID 数据查询失败: ", err.Error())
+		return nil, 0, fmt.Errorf("getLicInfoByOAUniqueID 数据查询失败: %v", err)
+	}
+	defer rows.Close()
+	var rest []OALicenseInfo
+	for rows.Next() {
+		var info OALicenseInfo
+		err = rows.Scan(
+			&info.LicInfo.ID, &info.LicInfo.UniqueID, &info.LicInfo.OAId, &info.LicInfo.OARequestID,
+			&info.LicInfo.OARequestName, &info.LicInfo.OARequestNameNew, &info.LicInfo.OARequestNameHTMLNew,
+			&info.LicInfo.OAGLXMID, &info.LicInfo.OAGLXMName,
+			&info.LicInfo.OASQSJ, &info.LicInfo.OASalespersonName, &info.LicInfo.OAXSJSYX,
+			&info.LicInfo.OAOperationsPersonName, &info.LicInfo.OAJFJSYX, &info.LicInfo.OASYDW,
+			&info.LicInfo.OAXMXXMS, &info.LicInfo.OAJDS, &info.LicInfo.OANodeCount,
+			&info.LicInfo.OAProductCode, &info.LicInfo.OAProductName, &info.LicInfo.OAProductVersion,
+			&info.LicInfo.OACPU, &info.LicInfo.OAOperatingSystem, &info.LicInfo.OAMainMAC,
+			&info.LicInfo.OASecondMAC, &info.LicInfo.OACreationDate, &info.LicInfo.OACreationTime,
+			&info.LicInfo.OALastOperateDate, &info.LicInfo.OALastOperateTime, &info.LicInfo.CaptureTime,
+			&info.LicInfo.DelTime, &info.LicInfo.LastOperateTime,
+			&info.GenrateInfo.ID, &info.GenrateInfo.OAId, &info.GenrateInfo.LicenseUniqueID, &info.GenrateInfo.LicenseFlage,
+			&info.GenrateInfo.Lic1, &info.GenrateInfo.Lic2, &info.GenrateInfo.CreatorGenerate,
+		)
+		if err != nil {
+			log.Fatal(err)
+		}
+		rest = append(rest, info)
+
+		fmt.Println("info", info)
+	}
+
+	return &rest, total, nil
+}
+
+func GetConditionalSearchUser(params api.ConditionalSearchRequest, user string) (*[]OALicenseInfo, int, error) {
 	total := 0
 	err := global.XuguDB.QueryRow(`
 		SELECT COUNT(*) from (SELECT OA_REQUESTID AS RequestCount
@@ -533,7 +626,7 @@ func GetConditionalSearch(params api.ConditionalSearchRequest) (*[]OALicenseInfo
 	}
 
 	// 构建SQL语句和参数
-	query, args := buildSQL(params)
+	query, args := buildConditionalSearchAllSQL(params, 2, user)
 	// 输出SQL语句和参数
 	fmt.Println("Query:", query)
 	fmt.Println("Args:", args)

+ 4 - 3
internal/models/user_models.go

@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"time"
+	"xugu_license/internal/api"
 	"xugu_license/internal/global"
 	tokens "xugu_license/internal/utils/token"
 
@@ -156,7 +157,7 @@ func GetAllUser() (*[]UserInfo, error) {
 	return &uS, nil
 }
 
-func UpdateUserInfo(u UserInfo) error {
+func UpdateUserInfo(u api.UserInfoRequest) error {
 	tx, err := global.XuguDB.Begin()
 	if err != nil {
 		return fmt.Errorf("begin transaction: %v", err)
@@ -172,8 +173,8 @@ func UpdateUserInfo(u UserInfo) error {
 
 	//插入 LicenseInfo 表
 	_, err = tx.Exec(`
-UPDATE lic_USER SET Username = ?,TELEPHONE = ?,EMAIL = ?,ROLE =? WHERE id = ?;
-	`, u.Username, u.Telephone, u.Email, u.Role, u.Id)
+UPDATE lic_USER SET Username = ?,TELEPHONE = ?,EMAIL = ?,PASSWORD =? ,ROLE =? WHERE id = ?;
+	`, u.Username, u.Telephone, u.Email, u.Password, u.Role, u.Id)
 
 	if err != nil {
 

+ 2 - 2
internal/module/email/email.go

@@ -45,7 +45,7 @@ func NewEmail(from string, pwd string, to []string, smtpServer string, smtpPort
 // subject := "Subject: Test email\n"
 // body := "This is a test email sent using Go and SSL."
 
-func BuildEmail(lic *models.OALicenseInfo, emils []string, licStr string, licStr2 string) (*Email, error) {
+func BuildEmail(lic *models.OALicenseInfo, emils []string, licStr []byte, licStr2 string) (*Email, error) {
 	var em *Email
 	err := CheckEmailFormat(emils)
 	if err != nil {
@@ -91,7 +91,7 @@ func SendEmail(emInfo *Email) error {
 
 		encoded := base64.StdEncoding.EncodeToString(fileData)
 		msg.WriteString("Content-Type: application/octet-stream\r\n")
-		msg.WriteString(fmt.Sprintf("Content-Disposition: attachment; filename=\"%s\"\r\n", "license.dat"))
+		msg.WriteString(fmt.Sprintf("Content-Disposition: attachment; filename=\"%s\"\r\n", "license.zip"))
 		msg.WriteString("Content-Transfer-Encoding: base64\r\n\r\n")
 		msg.WriteString(encoded)
 		msg.WriteString("\r\n--BOUNDARY\r\n")

+ 90 - 90
internal/services/OALicenseInfo_services.go

@@ -1,6 +1,8 @@
 package services
 
 import (
+	"archive/zip"
+	"bytes"
 	"fmt"
 	"strings"
 	"xugu_license/internal/api"
@@ -167,31 +169,6 @@ func DistributeLicenseToEmailServices(OperatorUniqueID string, OaRequestId int64
 	if len(EmailArray) == 0 {
 		return nil, nil
 	}
-	//将licenses里的lic串们打包在zip里
-	// 1. 创建 ZIP 文件并存储在内存中
-	// var buffer bytes.Buffer
-	// zipWriter := zip.NewWriter(&buffer)
-	// for _, lic := range *LicInfos {
-	// 	// 将数据添加到 ZIP 中
-	// 	file1, err := zipWriter.Create("file1.txt")
-	// 	if err != nil {
-	// 		global.Logger.Errorln(err)
-	// 	}
-	// 	_, err = file1.Write(lic)
-	// 	if err != nil {
-	// 		global.Logger.Errorln(err)
-	// 	}
-
-	// }
-
-	// file2, err := zipWriter.Create("file2.txt")
-	// if err != nil {
-	// 	global.Logger.Errorln(err)
-	// }
-	// _, err = file2.Write(data2)
-	// if err != nil {
-	// 	global.Logger.Errorln(err)
-	// }
 
 	//获取一个申请单的多个license信息
 	LicInfos, _, err := models.GetOALicenseInfo(1, 1, "", "", "", OaRequestId)
@@ -199,31 +176,74 @@ func DistributeLicenseToEmailServices(OperatorUniqueID string, OaRequestId int64
 		return err, nil
 	}
 
+	//将licenses里的lic串们打包在zip里
+	//1. 创建 ZIP 文件并存储在内存中
+	var buffer bytes.Buffer
+	zipWriter := zip.NewWriter(&buffer)
+	for i, lic := range *LicInfos {
+		num := 1
+		filetestName := fmt.Sprintf("%d_%s_license_jdCount%d_%d", i, lic.LicInfo.OAGLXMName, lic.LicInfo.OANodeCount.Int64, num)
+		num++
+		// 将数据添加到 ZIP 中
+		file1, err := zipWriter.Create(filetestName)
+		if err != nil {
+			global.Logger.Errorln(err)
+		}
+		if lic.GenrateInfo.Lic1.Valid {
+			_, err = file1.Write([]byte(lic.GenrateInfo.Lic1.String))
+			if err != nil {
+				global.Logger.Errorln(err)
+			}
+		}
+		file2, err := zipWriter.Create(filetestName)
+		if lic.GenrateInfo.Lic2.Valid {
+			if err != nil {
+				global.Logger.Errorln(err)
+			}
+			_, err = file2.Write([]byte(lic.GenrateInfo.Lic2.String))
+			if err != nil {
+				global.Logger.Errorln(err)
+			}
+
+		}
+
+	}
+
+	// 关闭 zip.Writer
+	if err := zipWriter.Close(); err != nil {
+		global.Logger.Errorln(err)
+	}
+
+	// 将 ZIP 内容转换为 []byte
+	zipBytes := buffer.Bytes()
+
 	fmt.Println("EmailArray : ", EmailArray)
 	emails := strings.Join(EmailArray, ",")
 	if !strings.Contains(emails, "@") {
 		return nil, nil
 	}
-	for _, lic := range *LicInfos {
 
-		if lic.GenrateInfo.Lic1.String == "" {
-			global.Logger.Errorln("DistributeOALicenseServices : license生成信息为空 ")
-			return errors.New("license生成信息为空"), nil
-		}
+	// if lic.GenrateInfo.Lic1.String == "" {
+	// 	global.Logger.Errorln("DistributeOALicenseServices : license生成信息为空 ")
+	// 	return errors.New("license生成信息为空"), nil
+	// }
 
-		//组装邮件
-		em, err := email.BuildEmail(&lic, EmailArray, lic.GenrateInfo.Lic1.String, lic.GenrateInfo.Lic2.String)
-		if err != nil {
-			global.Logger.Errorln("邮件生成失败", err.Error())
-			return err, nil
-		}
-		//发送邮件
-		err = email.SendEmail(em)
-		if err != nil {
-			global.Logger.Errorln("邮件发送失败", err.Error())
+	lic := &(*LicInfos)[0]
+	//组装邮件
+	em, err := email.BuildEmail(lic, EmailArray, zipBytes, "")
+	if err != nil {
+		global.Logger.Errorln("邮件生成失败", err.Error())
+		return err, nil
+	}
+	//发送邮件
+	err = email.SendEmail(em)
+	if err != nil {
+		global.Logger.Errorln("邮件发送失败", err.Error())
 
-			return err, nil
-		}
+		return err, nil
+	}
+
+	for _, lic := range *LicInfos {
 		//将分发的lic信息插入lic分发邮箱表中
 		err = models.InsertlicenseRecordByEmailRow(OaRequestId, lic.LicInfo.UniqueID.String, emails, OperatorUniqueID)
 		if err != nil {
@@ -231,6 +251,34 @@ func DistributeLicenseToEmailServices(OperatorUniqueID string, OaRequestId int64
 			return err, nil
 		}
 	}
+
+	// for _, lic := range *LicInfos {
+
+	// 	if lic.GenrateInfo.Lic1.String == "" {
+	// 		global.Logger.Errorln("DistributeOALicenseServices : license生成信息为空 ")
+	// 		return errors.New("license生成信息为空"), nil
+	// 	}
+
+	// 	//组装邮件
+	// 	em, err := email.BuildEmail(&lic, EmailArray, lic.GenrateInfo.Lic1.String, lic.GenrateInfo.Lic2.String)
+	// 	if err != nil {
+	// 		global.Logger.Errorln("邮件生成失败", err.Error())
+	// 		return err, nil
+	// 	}
+	// 	//发送邮件
+	// 	err = email.SendEmail(em)
+	// 	if err != nil {
+	// 		global.Logger.Errorln("邮件发送失败", err.Error())
+
+	// 		return err, nil
+	// 	}
+	// 	//将分发的lic信息插入lic分发邮箱表中
+	// 	err = models.InsertlicenseRecordByEmailRow(OaRequestId, lic.LicInfo.UniqueID.String, emails, OperatorUniqueID)
+	// 	if err != nil {
+	// 		global.Logger.Errorln("数据库插入失败: ", err.Error())
+	// 		return err, nil
+	// 	}
+	// }
 	return nil, nil
 }
 
@@ -325,51 +373,3 @@ func generateLicenseStrSub(UniqueID string) error {
 	}
 	return nil
 }
-
-func GetDistributeButtenCheckService(OARequestId int64) (error, bool) {
-	if OARequestId != 0 {
-		//一个OARequestId会有多条数据UniqueID
-		OALics, _, err := models.GetOALicenseInfo(0, 0, "", "", "", OARequestId)
-		if err != nil || OALics == nil {
-			global.Logger.Errorln("LicenseInfo数据查询失败:  ", err.Error())
-			return errors.Errorf("LicenseInfo数据查询失败 : %v", err.Error()), false
-		}
-
-		//校验license信息是否与oa一致
-		var isCheck bool
-		for _, license := range *OALics {
-			//检测该数据是否与oa库数据库一致 //todo
-			isCheckTmp, err := models.CheckLicenseInfoInOADB(&license.LicInfo)
-			if err != nil {
-				global.Logger.Errorln("LicenseInfo数据对比oa库 校验失败:  ", err.Error())
-				return errors.Errorf("LicenseInfo数据对比oa库 校验失败 %v", err.Error()), false
-			}
-			if isCheckTmp {
-				global.Logger.Errorf("\nLicenseInfo数据对比oa库 不一致:  %v\n", license.LicInfo.UniqueID)
-				isCheck = isCheckTmp
-				err = models.UpdatelicenseInfoRow(license)
-				if err != nil {
-					return err, false
-				}
-				err = models.UpdatelicenseGenerateInfoRow(license)
-				if err != nil {
-					return err, false
-				}
-			}
-		}
-		//不一致则返回
-		if isCheck {
-			return nil, true
-		}
-		return nil, false
-	}
-	return errors.Errorf("该申请单没有oa单号"), false
-}
-
-func GetConditionalSearchService(request api.ConditionalSearchRequest) (*[]models.OALicenseInfo, int, error) {
-	lic, total, err := models.GetConditionalSearch(request)
-	if err != nil {
-		return nil, total, err
-	}
-	return lic, total, nil
-}

+ 70 - 0
internal/services/license_search_services.go

@@ -0,0 +1,70 @@
+package services
+
+import (
+	"xugu_license/internal/api"
+	"xugu_license/internal/global"
+	middlewares "xugu_license/internal/middleware"
+	"xugu_license/internal/models"
+
+	"github.com/pkg/errors"
+)
+
+func GetDistributeButtenCheckService(OARequestId int64) (error, bool) {
+	if OARequestId != 0 {
+		//一个OARequestId会有多条数据UniqueID
+		OALics, _, err := models.GetOALicenseInfo(0, 0, "", "", "", OARequestId)
+		if err != nil || OALics == nil {
+			global.Logger.Errorln("LicenseInfo数据查询失败:  ", err.Error())
+			return errors.Errorf("LicenseInfo数据查询失败 : %v", err.Error()), false
+		}
+
+		//校验license信息是否与oa一致
+		var isCheck bool
+		for _, license := range *OALics {
+			//检测该数据是否与oa库数据库一致 //todo
+			isCheckTmp, err := models.CheckLicenseInfoInOADB(&license.LicInfo)
+			if err != nil {
+				global.Logger.Errorln("LicenseInfo数据对比oa库 校验失败:  ", err.Error())
+				return errors.Errorf("LicenseInfo数据对比oa库 校验失败 %v", err.Error()), false
+			}
+			if isCheckTmp {
+				global.Logger.Errorf("\nLicenseInfo数据对比oa库 不一致:  %v\n", license.LicInfo.UniqueID)
+				isCheck = isCheckTmp
+				err = models.UpdatelicenseInfoRow(license)
+				if err != nil {
+					return err, false
+				}
+				err = models.UpdatelicenseGenerateInfoRow(license)
+				if err != nil {
+					return err, false
+				}
+			}
+		}
+		//不一致则返回
+		if isCheck {
+			return nil, true
+		}
+		return nil, false
+	}
+	return errors.Errorf("该申请单没有oa单号"), false
+}
+
+func GetConditionalSearchService(request api.ConditionalSearchRequest, role middlewares.Permission, user string) (*[]models.OALicenseInfo, int, error) {
+
+	if role == middlewares.ReadAllLicense {
+		lic, total, err := models.GetConditionalSearchAll(request)
+		if err != nil {
+			return nil, total, err
+		}
+		return lic, total, nil
+	} else if role == middlewares.ReadLicense {
+		lic, total, err := models.GetConditionalSearchUser(request, user)
+		if err != nil {
+			return nil, total, err
+		}
+		return lic, total, nil
+	} else {
+		return nil, 0, errors.Errorf("没有权限")
+	}
+
+}

+ 137 - 5
static/license_info/license_info.css

@@ -8,15 +8,145 @@ body {
 
 /* 头部样式 */
 header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
     background-color: #ffffff;
     color: #333;
-  
-    height: 50px; /* 明确指定较小的高度 */
+    height: 100px; /* 根据需要调整高度 */
+    padding: 0 20px; /* 调整左右内边距 */
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+header h1 {
+    flex: 1; /* 标题占据左边 */
+    
+    margin: 0;
+}
+
+.right-container {
+    display: flex;
+    flex: 1; /* 让右边部分占据剩余的空间 */
+    justify-content: flex-end; /* 将右边的两个 div 靠右对齐 */
+}
+
+/* 调整 .right-container 内的 div 样式 */
+.right-container div {
+    border: 1px solid #ccc;
+    padding: 10px;
+    margin-left: 10px; /* 两个子 div 之间的间距 */
+}
+
+/* iOS 风格 login-button 按钮 */
+.login-button {
+    background-color: #76b2f1; /* iOS 风格蓝色 */
+    color: white;
+    padding: 12px 0; /* 让按钮的高度保持一致,内容居中 */
+    border-radius: 15px; /* 圆角按钮 */
+    font-size: 14px; /* 较小字体以适应60px的宽度 */
+    font-weight: 600;
+    cursor: pointer; /* 鼠标悬停时的手型指针 */
+    transition: background-color 0.3s ease;
+    border: none;
+    width: 60px; /* 限制宽度为60px */
+    text-align: center; /* 内容居中对齐 */
+    overflow: hidden; /* 如果文字超过,隐藏多余部分 */
+    white-space: nowrap; /* 避免换行 */
+    text-overflow: ellipsis; /* 用省略号表示超出的文字 */
+    margin-left: 10px; /* 跟其他 div 保持一致的间距 */
+    flex-shrink: 0; /* 确保按钮不会缩放 */
+}
+
+.login-button:hover {
+    background-color: #005bb5; /* 悬停时的颜色变深 */
+}
+
+
+/* login-modal 样式 - 隐藏模态框 */
+/* iOS 风格的模态框背景 */
+.login-modal {
+    display: none; /* 初始隐藏 */
+    position: fixed;
+    z-index: 1000;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.4); /* iOS 风格的半透明背景 */
+    justify-content: center;
+    align-items: center;
+}
+
+/* iOS 风格的模态框内容 */
+.login-modal-content {
+    background-color: #ffffff;
+    padding: 20px;
+    border-radius: 15px; /* iOS 风格的圆角 */
+    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); /* iOS 风格的阴影效果 */
+    max-width: 400px;
+    width: 80%;
     text-align: center;
-    align-items: center; /* 垂直居中内容 */
-    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); /* 轻微阴影 */
+    animation: fadeIn 0.3s ease-in-out; /* 动画效果 */
+    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+    position: relative; /* 设置相对定位 */
+}
+
+
+/* 关闭按钮 iOS 风格 */
+.login-modal-close {
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    font-size: 24px;
+    color: #007aff; /* iOS 蓝色 */
+    cursor: pointer;
+    font-weight: bold;
+    z-index: 1001; /* 确保在模态框内容的上方 */
+}
+
+/* 模态框中的文本样式 */
+#userInfoContainer p {
+    margin: 10px 0; /* 增加上下间距 */
+    font-size: 16px; /* iOS 字体大小 */
+    color: #333; /* 深灰色字体 */
+    font-weight: 500;
+    line-height: 1.5; /* 增加行高 */
+}
+
+/* iOS 风格的弹出动画 */
+@keyframes fadeIn {
+    from {
+        opacity: 0;
+        transform: scale(0.95); /* 轻微缩放效果 */
+    }
+    to {
+        opacity: 1;
+        transform: scale(1);
+    }
+}
+
+/* iOS 风格退出按钮 */
+.logout-button {
+    background-color: #ff3b30; /* iOS 风格红色 */
+    color: white;
+    padding: 12px 20px;
+    border-radius: 15px; /* 圆角 */
+    font-size: 16px;
+    font-weight: 600;
+    cursor: pointer;
+    transition: background-color 0.3s ease;
+    border: none;
+    width: 100%; /* 占满模态框的宽度 */
+    margin-top: 20px; /* 增加与其他元素的距离 */
 }
 
+.logout-button:hover {
+    background-color: #d12a1f; /* 悬停时颜色稍深 */
+}
+
+/*----------------*/
+
+
 /* 容器布局:包含侧边栏和主内容 */
 .container {
     display: flex;
@@ -83,8 +213,9 @@ nav ul li a i {
 main {
     flex: 1; /* 占据剩余宽度 */
     padding: 20px;
-    overflow-y: auto; /* 启用垂直滚动 */
+    overflow-y: scroll; /* 启用垂直滚动 */
     background-color: #ecf0f1; /* 浅灰色背景 */
+    height: auto; /* 自动调整高度 */
 }
 
 
@@ -92,6 +223,7 @@ main {
 /* 瀑布流容器样式,每行最多显示4个卡片 */
 .license-info-container {
     display: flex;
+    
     flex-wrap: wrap;
     gap: 20px; /* 卡片之间的间距 */
 }

+ 17 - 2
static/license_info/license_info.html

@@ -11,9 +11,23 @@
 
 
     <header>
-        <h1>XUGU License </h1>
-
+        <h1>XUGU License</h1>
+        <div class="right-container">
+            <div>左边的子div</div>
+            <div class="login-button">点击显示用户信息</div>
+        </div>
     </header>
+    
+    <!-- 模态框结构 -->
+    <div id="loginModal" class="login-modal">
+        <div class="login-modal-content">
+            <span class="login-modal-close">&times;</span> <!-- 关闭按钮放在这里 -->
+            <div id="userInfoContainer"></div>
+        </div>
+    </div>
+    
+    
+    
 
     <div class="container">
         <aside>
@@ -145,6 +159,7 @@
 
 
 
+
     <script src="license_info.js"></script>
     <script src="license_info_distribution.js"></script>
     <script

+ 69 - 2
static/license_info/license_info.js

@@ -9,7 +9,7 @@ const preLoadDistance = 300; // 距离底部300px时提前加载
 
 // 假设 Authorization 值存储在 localStorage 中,key 为 "authToken"
 const authToken = localStorage.getItem("Authorization");
-const currentUserInfo  = fetchUsername(); // 获取当前用户登录信息
+let currentUserInfo ; // 获取当前用户登录信息
 let currentUserPermissions; // 用于存储用户权限信息
 
 //获取  主内容区域
@@ -49,6 +49,57 @@ function closeModal(modalId) {
 }
 
 
+//-----------头部--------------------------------
+function setupUserInfoModal(currentUserInfo) {
+    console.log("currentUserInfo,", currentUserInfo);
+    // 获取按钮、模态框和关闭按钮的 DOM 元素
+    const loginButton = document.querySelector('.login-button');
+    const loginModal = document.getElementById('loginModal');
+    const loginModalClose = document.querySelector('.login-modal-close');
+    const userInfoContainer = document.getElementById('userInfoContainer');
+
+    // 设置按钮的显示内容为当前用户的名称
+    loginButton.textContent = currentUserInfo.Username;
+
+    // 点击按钮时显示模态框,并将用户信息填充到模态框中
+    loginButton.addEventListener('click', () => {
+        userInfoContainer.innerHTML = `
+            <p><strong>用户名:</strong> ${currentUserInfo.Username}</p>
+            <p><strong>邮箱:</strong> ${currentUserInfo.Email}</p>
+            <p><strong>电话:</strong> ${currentUserInfo.Telephone}</p>
+            <p><strong>账号:</strong> ${currentUserInfo.Account}</p>
+            <p><strong>角色:</strong> ${currentUserInfo.Role}</p>
+            <button class="logout-button">退出登录</button> <!-- 退出登录按钮 -->
+        `;
+        loginModal.style.display = 'flex';
+
+        // 为退出登录按钮绑定点击事件
+        const logoutButton = document.querySelector('.logout-button');
+        logoutButton.addEventListener('click', logout);
+    });
+
+    // 点击关闭按钮时隐藏模态框
+    loginModalClose.addEventListener('click', () => {
+        loginModal.style.display = 'none';
+    });
+
+    // 点击模态框外部区域时关闭模态框
+    window.addEventListener('click', (event) => {
+        if (event.target === loginModal) {
+            loginModal.style.display = 'none';
+        }
+    });
+}
+
+// 退出登录函数
+function logout() {
+    localStorage.removeItem('Authorization');
+    window.location.href = '/';
+}
+
+
+
+
 //-----------侧边栏----------------------------
 
 // 获取所有菜单项
@@ -71,6 +122,16 @@ const userManagementLink = document.getElementById('user-management-link');
 const licenseInfoLink = document.getElementById('license-info-link');
 const roleManagementLink = document.getElementById('role-management-link');
 
+// 根据用户权限控制菜单显示
+function updateMenuVisibility() {
+    console.log("updateMenuVisibility: ",currentUserPermissions);
+    if (currentUserPermissions) {
+        userManagementLink.style.display = currentUserPermissions.includes('read_user') ? 'block' : 'none';
+        roleManagementLink.style.display = currentUserPermissions.includes('get_role') ? 'block' : 'none';
+        licenseInfoLink.style.display = (currentUserPermissions.includes('read_license') || currentUserPermissions.includes('read_all_license')) ? 'block' : 'none';
+    }
+}
+
 // 监听用户管理按钮的点击事件
 userManagementLink.addEventListener('click', function(event) {
     event.preventDefault(); // 阻止默认的跳转行为
@@ -479,7 +540,7 @@ modalHeader.innerHTML = `
                 : ''
             }
             <button class="license-info-modal-button" id="downloadAllLicenses-button">打包下载所有license.dat</button>
-            <button id="viewDistributionHistory-button">查看分发历史</button>
+            <button class="license-info-modal-button" id="viewDistributionHistory-button">查看分发历史</button>
         </div>
     </div>
 `;
@@ -874,12 +935,18 @@ async function fetchUsername() {
         // 使用获取到的角色,调用获取权限的接口
         await fetchPermissionsByRole(currentUserRole);
         console.log('当前用户角色:', data);
+        currentUserInfo = data.data;
+        // 调用该函数,初始化模态框
+        setupUserInfoModal(currentUserInfo);
+        updateMenuVisibility();
         return data.data; // 返回获取到的用户信息数据
     
     } catch (error) {
         console.error('Error fetching user info or permissions:', error);
     }
 }
+fetchUsername();
+// 调用函数更新菜单可见性
 
 // 将 fetchPermissionsByRole 转换为异步函数
 async function fetchPermissionsByRole(role) {

+ 73 - 0
static/license_info/license_info_distribution.css

@@ -205,3 +205,76 @@
     transform: translateY(-50%);
     pointer-events: none; /* 让箭头不可点击 */
 }
+
+/*分发历史模态框----------*/
+/* 模态框背景 */
+.distributionHistory-modal {
+    display: none; /* 默认隐藏 */
+    position: fixed;
+    z-index: 999;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.5); /* 半透明黑色背景 */
+}
+
+/* 模态框内容 */
+.distributionHistory-modal-content {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    background-color: #ffffff;
+    border-radius: 12px; /* 圆角 */
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+    width: 90%;
+    max-width: 500px;
+    padding: 20px; /* 内边距 */
+}
+
+/* 关闭按钮 */
+.distributionHistory-modal-close {
+    color: #888;
+    float: right;
+    font-size: 24px;
+    font-weight: bold;
+    cursor: pointer;
+}
+
+/* 标题 */
+.distributionHistory-modal h2 {
+    margin: 0;
+    font-size: 20px;
+    font-weight: bold;
+    text-align: center;
+}
+
+/* 用户记录和邮箱记录容器 */
+.distributionHistory-user-content,
+.distributionHistory-email-content {
+    margin-top: 15px; /* 上外边距 */
+    margin-bottom: 15px; /* 下外边距 */
+    border: 5px solid #02556e; /* 边框 */
+    border-radius: 8px; /* 圆角 */
+    padding: 10px; /* 内边距 */
+    background-color: #f9f9f9; /* 背景色 */
+}
+/* 用户记录 */
+.distributionHistoryModal-user {
+    padding: 10px;
+    border-bottom: 1px solid #eaeaea;
+}
+
+/* 邮箱记录 */
+.distributionHistoryModal-email {
+    padding: 10px;
+    border-bottom: 1px solid #eaeaea;
+}
+
+/* 无记录提示 */
+.distributionHistoryModal-no-record {
+    text-align: center;
+    color: #999;
+    padding: 10px;
+}

+ 86 - 20
static/license_info/license_info_distribution.js

@@ -52,6 +52,7 @@ function showDistributeModal(item) {
 
 
 function handleEmailSection(item,usersInfo) {
+    console.log('调用邮箱处理');
     console.log('handleEmailSection 用户信息:', usersInfo); // 打印用户信息
     const emailInputs = document.getElementById('DistributeModal-email-inputs');
     emailInputs.innerHTML = ''; // 清空之前添加的邮箱输入框
@@ -418,6 +419,57 @@ function distributeUser(item, uniqueIDArray, usernameArray, accountArray) {
 
 
 //--------------分发历史模态框------------------------
+// function showDistributionHistory(selectedRowData) {
+//     fetch('http://127.0.0.1:8080/api/admin/GetlicenseRecord', {
+//         method: 'POST',
+//         headers: {
+//             'Authorization': `Bearer ${authToken}`,
+//             'Content-Type': 'application/json'
+//         },
+//         body: JSON.stringify({ uniqueID: selectedRowData.UniqueID, oa_request_id: selectedRowData.oa_request_id })
+//     })
+//     .then(response => response.json())
+//     .then(data => {
+//         const userDistributionContent = document.getElementById('distributionHistory-user-content');
+//         const emailDistributionContent = document.getElementById('distributionHistory-email-content');
+        
+//         // 检查 license_record_to_user 是否是数组,如果不是则默认为空数组
+//         const userRecords = Array.isArray(data?.data?.license_record_to_user) ? data.data.license_record_to_user : [];
+        
+//         // 如果 license_record_to_emails 是 null,则设置为空数组
+//         const emailRecords = Array.isArray(data?.data?.license_record_to_emails) ? data.data.license_record_to_emails : [];
+    
+//         // 显示用户分发记录
+//         userDistributionContent.innerHTML = userRecords.length > 0 
+//             ? userRecords.map(record => `<p>已转发给用户: ${record.user_account} 时间: ${formatDateTime(record.up_time)}</p>`).join('') 
+//             : '<p>没有用户分发记录。</p>';
+    
+//         // 显示邮箱分发记录
+//         emailDistributionContent.innerHTML = emailRecords.length > 0 
+//             ? emailRecords.map(record => `<p>已发给邮箱: ${record.emails} 时间: ${formatDateTime(record.up_time)}</p>`).join('') 
+//             : '<p>没有邮箱分发记录。</p>';
+    
+//         // 显示模态框
+//         document.getElementById('distributionHistory-modal').style.display = 'block';
+//     })
+//     .catch(error => {
+//         console.error('Error fetching distribution history:', error);
+//     });
+
+//     // 关闭模态框 (点击关闭按钮)
+//     document.querySelector('.distributionHistory-modal-close').addEventListener('click', () => {  
+//         document.getElementById('distributionHistory-modal').style.display = 'none';
+//     });
+
+//     // 点击模态框外部关闭模态框
+//     window.addEventListener('click', function(event) {
+//         const modal = document.getElementById('distributionHistory-modal');
+//         if (event.target === modal) {  // 检查点击的是否是模态框背景
+//             modal.style.display = 'none';  // 关闭模态框
+//         }
+//     });
+// }
+
 function showDistributionHistory(selectedRowData) {
     fetch('http://127.0.0.1:8080/api/admin/GetlicenseRecord', {
         method: 'POST',
@@ -429,27 +481,40 @@ function showDistributionHistory(selectedRowData) {
     })
     .then(response => response.json())
     .then(data => {
-        const userDistributionContent = document.getElementById('distributionHistory-user-content');
-        const emailDistributionContent = document.getElementById('distributionHistory-email-content');
-        
-        // 检查 license_record_to_user 是否是数组,如果不是则默认为空数组
-        const userRecords = Array.isArray(data?.data?.license_record_to_user) ? data.data.license_record_to_user : [];
+        console.log("showDistributionHistory", data);
+
+        // 提取用户记录和邮箱记录
+        const userRecords = data.data.license_record_to_user || [];
+        const emailRecords = data.data.license_record_to_emails || [];
+
+        // 动态生成用户记录的 HTML
+        const userContent = userRecords.length > 0 ? 
+            userRecords.map(user => `
+                <div class="distributionHistory-user">
+                    <div>用户名: ${user.user_account}</div>
+                    <div>唯一用户 ID: ${user.user_unique_id}</div>
+                    <div>更新时间: ${new Date(user.up_time).toLocaleString()}</div>
+                </div>
+            `).join('') : 
+            '<div class="distributionHistory-no-record">无用户记录</div>';
         
-        // 如果 license_record_to_emails 是 null,则设置为空数组
-        const emailRecords = Array.isArray(data?.data?.license_record_to_emails) ? data.data.license_record_to_emails : [];
-    
-        // 显示用户分发记录
-        userDistributionContent.innerHTML = userRecords.length > 0 
-            ? userRecords.map(record => `<p>已转发给用户: ${record.user_account} 时间: ${formatDateTime(record.up_time)}</p>`).join('') 
-            : '<p>没有用户分发记录。</p>';
-    
-        // 显示邮箱分发记录
-        emailDistributionContent.innerHTML = emailRecords.length > 0 
-            ? emailRecords.map(record => `<p>已发给邮箱: ${record.emails} 时间: ${formatDateTime(record.up_time)}</p>`).join('') 
-            : '<p>没有邮箱分发记录。</p>';
-    
+        // 动态生成邮箱记录的 HTML
+        const emailContent = emailRecords.length > 0 ? 
+            emailRecords.map(email => `
+                <div class="distributionHistory-email">
+                    <div>邮箱: ${email.emails}</div>
+                    <div>更新时间: ${new Date(email.up_time).toLocaleString()}</div>
+                </div>
+            `).join('') : 
+            '<div class="distributionHistory-no-record">无邮箱记录</div>';
+
+        // 将内容插入到模态框中的对应 div
+        document.getElementById('distributionHistory-user-content').innerHTML = userContent;
+        document.getElementById('distributionHistory-email-content').innerHTML = emailContent;
+
         // 显示模态框
         document.getElementById('distributionHistory-modal').style.display = 'block';
+
     })
     .catch(error => {
         console.error('Error fetching distribution history:', error);
@@ -463,12 +528,13 @@ function showDistributionHistory(selectedRowData) {
     // 点击模态框外部关闭模态框
     window.addEventListener('click', function(event) {
         const modal = document.getElementById('distributionHistory-modal');
-        if (event.target === modal) {  // 检查点击的是否是模态框背景
-            modal.style.display = 'none';  // 关闭模态框
+        if (event.target === modal) {
+            modal.style.display = 'none';
         }
     });
 }
 
+
 function formatDateTime(dateString) {
     const date = new Date(dateString);
 

+ 65 - 0
static/role/role.css

@@ -71,3 +71,68 @@
 .role-info-button-delete:hover {
     background-color: #c23321;
 }
+
+
+/*创建角色模态框*/
+.role-info-modal {
+    display: none; /* 初始隐藏模态框 */
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: rgba(0, 0, 0, 0.5);
+    justify-content: center;
+    align-items: center;
+    z-index: 1000; /* 确保模态框在最上层 */
+}
+
+.role-info-modal.show {
+    display: flex; /* 添加一个类以显示模态框 */
+}
+
+.createRoleModal-content {
+    background: white;
+    border-radius: 10px;
+    width: 400px;
+    padding: 20px;
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
+}
+
+.createRoleModal-content h3 {
+    margin: 0 0 15px 0;
+}
+
+.createRoleModal-content input[type="text"] {
+    width: 100%;
+    padding: 10px;
+    margin-bottom: 15px;
+    border: 1px solid #ccc;
+    border-radius: 5px;
+}
+
+.createRole-buttons {
+    display: flex;
+    justify-content: flex-end;
+}
+
+.createRole-button {
+    background-color: #007aff; /* iOS蓝色 */
+    color: white;
+    border: none;
+    padding: 10px 15px;
+    border-radius: 5px;
+    cursor: pointer;
+}
+
+.createRole-button:hover {
+    background-color: #005bb5; /* 深蓝色 */
+}
+
+.close-button {
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    cursor: pointer;
+    font-size: 20px;
+}

+ 7 - 3
static/role/role.html

@@ -9,19 +9,23 @@
 <body>
 
     <h2>角色管理页面</h2>
-
+    <!-- 创建角色按钮,仅在有权限时显示 role-info-create-role-button-->
+    <button id="createRoleButton" class="role-info-create-role-button" type="button">创建角色</button>
+    
     <div id="roles-container" class="role-info-cards-container">
         <!-- 角色将通过JS动态插入到这里 -->
     </div>
 
-    <!-- 创建角色按钮,仅在有权限时显示 -->
-    <button id="createRoleButton" class="role-info-create-role-button" style="display: none;">创建角色</button>
+
 
     <!-- 角色弹出菜单 -->
     <div id="role-action-menu" class="role-info-modal" style="display: none;">
         <!-- 通过JavaScript动态生成菜单内容 -->
     </div>
 
+
+
+    
     <script src="role.js"></script>
 
 </body>

+ 73 - 67
static/role/role.js

@@ -1,21 +1,15 @@
 // role.js
 
+fetchRoles()
 
+  // 处理修改用户按钮点击
+  document.getElementById("createRoleButton").onclick = () => {
+      
+    ShowCreateRoleModal(); // 打开编辑用户模态框
+};
 
-
-
-// 页面加载时获取角色列表
-document.addEventListener('DOMContentLoaded', function() {
-    fetchRoles();
-
-    // 绑定创建角色按钮的点击事件
-    document.getElementById('createRoleButton').addEventListener('click', function() {
-        createRole();
-    });
-});
-
-fetchRoles()
 function fetchRoles() {
+    
     fetch('http://127.0.0.1:8080/api/admin/GetRoles', {
         method: 'POST',
         headers: {
@@ -300,60 +294,72 @@ function deleteRole(roleName) {
 }
 
 
-function showCreateRoleModal() {
-    const extraInfoContent = document.getElementById('extraInfoContent');
-    extraInfoContent.innerHTML = `
-        <h3>创建新角色</h3>
-        <label for="newRoleName">角色名称:</label>
-        <input type="text" id="newRoleName" required><br><br>
-        <label for="newPermissions">权限:</label><br>
-        <div id="newPermissions">
-            <div>
-                <input type="checkbox" id="license" name="permissions" value="license" onchange="toggleSubPermissions('license', this)">
-                <label for="license">许可证</label>
-                <div id="licenseSubPermissions" style="margin-left: 20px;">
-                    <input type="checkbox" id="generate_license" name="permissions" value="generate_license">
-                    <label for="generate_license">生成许可证</label><br>
-                    <input type="checkbox" id="upload_license" name="permissions" value="upload_license">
-                    <label for="upload_license">上传许可证(废弃)</label><br>
-                    <input type="checkbox" id="read_license" name="permissions" value="read_license">
-                    <label for="read_license">读取许可证</label><br>
-                    <input type="checkbox" id="update_license" name="permissions" value="update_license">
-                    <label for="update_license">更新许可证(废弃)</label><br>
-                    <input type="checkbox" id="delete_license" name="permissions" value="delete_license">
-                    <label for="delete_license">删除许可证(废弃)</label><br>
-                </div>
-            </div>
-            <div>
-                <input type="checkbox" id="user" name="permissions" value="user" onchange="toggleSubPermissions('user', this)">
-                <label for="user">用户</label>
-                <div id="userSubPermissions" style="margin-left: 20px;">
-                    <input type="checkbox" id="create_user" name="permissions" value="create_user">
-                    <label for="create_user">创建用户</label><br>
-                    <input type="checkbox" id="read_user" name="permissions" value="read_user">
-                    <label for="read_user">读取用户</label><br>
-                    <input type="checkbox" id="update_user" name="permissions" value="update_user">
-                    <label for="update_user">更新用户</label><br>
-                    <input type="checkbox" id="delete_user" name="permissions" value="delete_user">
-                    <label for="delete_user">删除用户</label><br>
-                </div>
-            </div>
-            <div>
-                <input type="checkbox" id="role" name="permissions" value="role" onchange="toggleSubPermissions('role', this)">
-                <label for="role">角色</label>
-                <div id="roleSubPermissions" style="margin-left: 20px;">
-                    <input type="checkbox" id="create_role" name="permissions" value="create_role">
-                    <label for="create_role">创建角色</label><br>
-                    <input type="checkbox" id="delete_role" name="permissions" value="delete_role">
-                    <label for="delete_role">删除角色</label><br>
-                    <input type="checkbox" id="update_role" name="permissions" value="update_role">
-                    <label for="update_role">更新角色</label><br>
-                    <input type="checkbox" id="get_role" name="permissions" value="get_role">
-                    <label for="get_role">获取角色</label><br>
+
+function ShowCreateRoleModal() {
+    console.log('Creating role...');
+    const createRoleButton = document.getElementById('createRoleButton');
+    const roleActionMenu = document.getElementById('role-action-menu');
+
+    createRoleButton.style.display = 'block'; // 显示创建角色按钮
+
+    // 点击事件处理程序
+    createRoleButton.addEventListener('click', handleCreateRoleButtonClick);
+
+    function handleCreateRoleButtonClick() {
+        openCreateRoleModal();
+    }
+
+    function openCreateRoleModal() {
+        roleActionMenu.classList.add('show'); // 显示模态框
+        roleActionMenu.innerHTML = `
+            <div class="createRoleModal-content">
+                <span class="close-button">&times;</span>
+                <h3>创建角色</h3>
+                <label for="roleName">角色名:</label>
+                <input type="text" id="roleName" required>
+                <h4>权限选择:</h4>
+                ${generateCheckboxes()}
+                <div class="createRole-buttons">
+                    <button id="submitRoleButton">提交</button>
                 </div>
             </div>
-        </div><br><br>
-        <button onclick="createNewRole()">创建</button>
-    `;
-    document.getElementById('extraInfoModal').style.display = 'block';
+        `;
+
+        // 关闭模态框
+        roleActionMenu.querySelector('.close-button').onclick = function() {
+            roleActionMenu.classList.remove('show');
+        };
+
+        document.getElementById('submitRoleButton').onclick = function() {
+            // 处理角色创建逻辑
+            console.log("角色名:", document.getElementById('roleName').value);
+            roleActionMenu.classList.remove('show');
+        };
+    }
+
+    function generateCheckboxes() {
+        const permissions = {
+            'generate_license': '生成许可证',
+            'upload_license': '上传许可证(废弃)',
+            'read_license': '读取许可证',
+            'read_license_record': '读取许可证分发记录',
+            'update_license': '修改许可证(废弃)',
+            'delete_license': '删除许可证(废弃)',
+            'dispat_license': '分发许可证',
+            'create_user': '创建用户',
+            'read_user': '读取用户',
+            'update_user': '更新用户',
+            'delete_user': '删除用户',
+            'create_role': '创建角色',
+            'delete_role': '删除角色',
+            'update_role': '更新角色',
+            'get_role': '获取角色'
+        };
+
+        return Object.entries(permissions).map(([key, value]) => `
+            <label>
+                <input type="checkbox" name="${key}" value="${key}"> ${value}
+            </label><br>
+        `).join('');
+    }
 }

+ 69 - 1
static/user/user.css

@@ -127,7 +127,7 @@
 .add-user-modal-content {
     background-color: #fefefe;
     margin: 1% auto; /* 模态框居中 */
-    padding: 20px;
+    padding: 50px;
     border: 1px solid #888;
     max-width: 1000px;
     width: 550px; /* 模态框宽度 */
@@ -195,3 +195,71 @@
 .add-user-flat-rounded-button:active {
     background-color: #004a99; /* 按下时的颜色变化 */
 }
+
+/*修改用户样式----------------------*/
+
+.editUser-modal {
+    display: none; /* 初始隐藏模态框 */
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: rgba(0, 0, 0, 0.5);
+    justify-content: center;
+    align-items: center;
+}
+
+
+.editUser-modal.show {
+    display: flex; /* 添加一个类以显示模态框 */
+}
+
+.editUser-modal-content {
+    background: white;
+    border-radius: 10px;
+    width: 400px;
+    padding: 20px;
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
+}
+
+.editUser-form-group {
+    display: flex;
+    align-items: center;
+    margin-bottom: 15px;
+}
+
+.editUser-form-group label {
+    flex: 0 0 80px;
+}
+
+.editUser-form-group input,
+.editUser-form-group select {
+    flex: 1;
+    padding: 10px;
+    border: 1px solid #ccc;
+    border-radius: 5px;
+}
+
+.editUser-role-select {
+    margin-top: 15px;
+}
+
+.editUser-buttons {
+    display: flex;
+    justify-content: space-between;
+    margin-top: 20px;
+}
+
+.editUser-button {
+    background-color: #007aff; /* iOS蓝色 */
+    color: white;
+    border: none;
+    padding: 10px 15px;
+    border-radius: 5px;
+    cursor: pointer;
+}
+
+.editUser-button:hover {
+    background-color: #005bb5; /* 深蓝色 */
+}

+ 124 - 17
static/user/user.js

@@ -74,7 +74,6 @@ function fetchUsers() {
     });
 }
 
-//打开用户信息模态框
 function openUserActionModal(user) {
     // 填充用户信息到模态框
     document.getElementById("modal-username").innerText = `用户名: ${user.Username}`;
@@ -88,7 +87,8 @@ function openUserActionModal(user) {
 
     // 处理修改用户按钮点击
     document.getElementById("editUserButton").onclick = () => {
-        editUser(user);
+        closeModal("userActionModal"); // 先关闭用户信息模态框
+        editUser(user); // 打开编辑用户模态框
     };
 
     // 处理删除用户按钮点击
@@ -96,10 +96,7 @@ function openUserActionModal(user) {
         deleteUser(user);
     };
 
-    // 处理修改密码按钮点击
-    document.getElementById("resetPasswordButton").onclick = () => {
-        resetUserPassword(user);
-    };
+
 
     // 关闭模态框的点击事件(右上角关闭按钮)
     document.querySelector(".user-info-close").onclick = function() {
@@ -117,21 +114,133 @@ function openUserActionModal(user) {
 
 
 
-
+//修改用户
 function editUser(user) {
-    console.log("Edit user", user);
-    // 在这里实现修改用户逻辑
+    const modal = document.getElementById("editUserModal");
+    const usernameInput = document.getElementById("username");
+    const telephoneInput = document.getElementById("telephone");
+    const emailInput = document.getElementById("email");
+    const passwordInput = document.getElementById("password");
+    const roleSelectDiv = document.getElementById("roleSelectDiv");
+    const roleSelect = document.getElementById("role");
+
+    // 填充用户信息
+    usernameInput.value = user.Username;
+    telephoneInput.value = user.Telephone;
+    emailInput.value = user.Email;
+
+
+    // 检查权限并填充角色选择框
+    if (currentUserPermissions.includes('update_role')) {
+        roleSelectDiv.style.display = "block";
+        fetch('http://127.0.0.1:8080/api/admin/GetRoleNames', {
+            method: 'GET',
+            headers: {
+                'Authorization': `Bearer ${authToken}`,
+                'Content-Type': 'application/json'
+            }
+        })
+        .then(response => response.json())
+        .then(data => {
+            roleSelect.innerHTML = ''; // 清空选项
+            data.roles.forEach(role => {
+                const option = document.createElement('option');
+                option.value = role;
+                option.textContent = role;
+                if (user.Role === role) {
+                    option.selected = true;
+                }
+                roleSelect.appendChild(option);
+            });
+        })
+        .catch(error => console.error('获取角色列表时出错:', error));
+    } else {
+        roleSelectDiv.style.display = "none";
+    }
+
+    // 显示编辑用户模态框
+    modal.classList.add("show");
+
+    // 关闭模态框事件
+    document.getElementById("closeModalButton").onclick = () => {
+        modal.classList.remove("show");
+    };
+    console.log("user",user);
+    // 保存修改事件
+    document.getElementById("saveChangesButton").onclick = () => {
+        const updatedUser = {
+            id: user.Id,
+            unique_id : user.UniqueID,
+            account: user.Account,
+            username: usernameInput.value,
+            telephone: telephoneInput.value,
+            email: emailInput.value,
+            password: passwordInput.value,
+            role: roleSelect.value
+        };
+
+        // API 请求保存用户信息
+        fetch('http://127.0.0.1:8080/api/admin/updateUser', {
+            method: 'POST',
+            headers: {
+                'Authorization': `Bearer ${authToken}`,
+                'Content-Type': 'application/json'
+            },
+            body: JSON.stringify(updatedUser)
+        })
+        .then(response => {
+            if (response.ok) {
+                console.log('用户信息保存成功');
+                modal.classList.remove("show"); // 关闭模态框
+                alert('用户信息修改成功!'); // 使用alert弹出提示
+                fetchUsers(); 
+                //window.location.reload(); // 刷新页面
+                
+                // 可以在这里添加成功提示
+            } else {
+                alert('用户信息修改失败:', response.statusText); // 使用alert弹出提示
+                console.error('保存用户信息失败:', response.statusText);
+            }
+        })
+        .catch(error => console.error('请求出错:', error));
+    };
 }
+// 绑定按钮点击事件
+document.getElementById("editUserButton").onclick = () => {
+    editUser(user);
+};
+
+
 
+
+//删除用户
 function deleteUser(user) {
-    console.log("Delete user", user);
-    // 在这里实现删除用户逻辑
+    const uniqueID = user.UniqueID; // 获取用户的唯一ID
+    fetch('http://127.0.0.1:8080/api/admin/deleteUser', {
+        method: 'POST',
+        headers: {
+            'Authorization': `Bearer ${authToken}`,
+            'Content-Type': 'application/json'
+        },
+        body: JSON.stringify({ UniqueID: uniqueID })
+    })
+    .then(response => response.json())
+    .then(data => {
+        if (data.success) {
+            closeModal("userActionModal"); // 使用封装好的 closeModal 函数
+            alert('用户删除成功!');
+            fetchUsers(); // 重新加载用户列表
+        } else {
+            closeModal("userActionModal"); // 使用封装好的 closeModal 函数
+            alert('用户删除失败:' + data.error);
+        }
+    })
+    .catch(error => {
+        console.error('删除用户时发生错误:', error);
+        alert('删除用户时发生错误,请稍后再试。');
+    });
 }
 
-function resetUserPassword(user) {
-    console.log("Reset password for user", user);
-    // 在这里实现修改密码逻辑
-}
 
 
 
@@ -141,8 +250,6 @@ function resetUserPassword(user) {
 // 保存新用户
 // 保存新用户的函数,并在适当的时候打开和关闭模态框
 function saveNewUserActionModal(user) {
-
-
     openModal('user-info-addUserModal'); // 打开的是添加用户的模态框
 
     // 点击模态框外部时关闭模态框

+ 46 - 1
static/user/user_management.html

@@ -39,7 +39,7 @@
         <div class="user-info-modal-buttons">
             <button id="editUserButton" class="user-info-button">修改用户</button>
             <button id="deleteUserButton" class="user-info-button">删除用户</button>
-            <button id="resetPasswordButton" class="user-info-button">修改密码</button>
+
         </div>
     </div>
 </div>
@@ -81,6 +81,51 @@
         </form>
     </div>
 </div>
+
+
+<!-- 修改用户模态框 HTML -->
+<div id="editUserModal" class="editUser-modal">
+    <div class="editUser-modal-content">
+        <h2>修改用户</h2>
+        <form id="editUserForm">
+            <div class="editUser-form-group">
+                <label for="username">用户名:</label>
+                <input type="text" id="username" name="username" required>
+            </div>
+            <div class="editUser-form-group">
+                <label for="telephone">电话:</label>
+                <input type="text" id="telephone" name="telephone" required>
+            </div>
+            <div class="editUser-form-group">
+                <label for="email">邮箱:</label>
+                <input type="email" id="email" name="email" required>
+            </div>
+            <div class="editUser-form-group">
+                <label for="password">密码:</label>
+                <input type="password" id="password" name="password">
+            </div>
+        </form>
+        <div id="roleSelectDiv" class="editUser-role-select" style="display: none;">
+            <div class="editUser-form-group">
+                <label for="role">权限:</label>
+                <select id="role" name="role"></select>
+            </div>
+        </div>
+        <div class="editUser-buttons">
+            <button id="saveChangesButton" class="editUser-button">保存修改</button>
+            <button id="closeModalButton" class="editUser-button">关闭</button>
+        </div>
+    </div>
+</div>
+
+
+
+
+
+
+
+
+
 <script src="../user/user.js"></script>
 
 </body>

+ 2 - 2
支持库建表语句.sql

@@ -4,9 +4,9 @@ use license;
 CREATE TABLE lic_USER (
     id INT IDENTITY(10,1) PRIMARY KEY,         -- 自增主键,从10开始,每次递增1
     UNIQUEID VARCHAR(36) NOT NULL UNIQUE,     -- 唯一值ID
-    Username VARCHAR(255) NOT NULL DEFAULT '访客',     -- 用户名,不能为空且唯一
+    Username VARCHAR(255) NOT NULL UNIQUE DEFAULT '访客',     -- 用户名,不能为空且唯一
     Account VARCHAR(255) NOT NULL UNIQUE,  --账号
-    PassWord VARCHAR(255) NOT NULL UNIQUE,            -- 密码,不能为空
+    PassWord VARCHAR(255) NOT NULL ,            -- 密码,不能为空
     TELEPHONE VARCHAR(20) NOT NULL UNIQUE,                     -- 电话号码
     EMAIL VARCHAR(100) NOT NULL UNIQUE,        -- 电子邮件,不能为空且唯一,长度调整为100
     Role VARCHAR(20) NOT NULL DEFAULT 'guest',   -- 角色,不能为空,默认值为 'user'