merge: 合并代码20240531
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"be.ems/lib/dborm"
|
"be.ems/lib/dborm"
|
||||||
"be.ems/lib/global"
|
"be.ems/lib/global"
|
||||||
@@ -14,13 +15,197 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
UriCDREvent = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrEvent"
|
UriIMSCDREvent = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrEvent"
|
||||||
UriCDRFile = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrFile"
|
UriIMSCDRFile = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrFile"
|
||||||
|
UriSMFCDREvent = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/smf/objectType/cdrEvent"
|
||||||
|
UriSMFCDRFile = config.DefaultUriPrefix + "/cdrManagement/v1/elementType/smf/objectType/cdrFile"
|
||||||
|
|
||||||
CustomUriCDREvent = config.UriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrEvent"
|
CustomUriIMSCDREvent = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrEvent"
|
||||||
CustomUriCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/{elementTypeValue}/objectType/cdrFile"
|
CustomUriIMSCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrFile"
|
||||||
|
CustomUriSMFCDREvent = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrEvent"
|
||||||
|
CustomUriSMFCDRFile = config.UriPrefix + "/cdrManagement/v1/elementType/ims/objectType/cdrFile"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SMF CDR
|
||||||
|
type CdrSubscriptionID struct {
|
||||||
|
SubscriptionIDType string `json:"subscriptionIDType"`
|
||||||
|
SubscriptionIDData string `json:"subscriptionIDData"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrNetWorkFuctionInfomation struct {
|
||||||
|
NetworkFunctionality string `json:"networkFunctionality"`
|
||||||
|
NetworkFunctionName string `json:"networkFunctionName,omitempty"`
|
||||||
|
NetworkFunctionIPv4Address string `json:"networkFunctionIPv4Address,omitempty"`
|
||||||
|
NetworkFunctionIPv6Address string `json:"networkFunctionIPv6Address,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SMFTrigger string
|
||||||
|
|
||||||
|
const (
|
||||||
|
TimeThresholdReached SMFTrigger = "timeThresholdReached"
|
||||||
|
VolumeThresholdReached SMFTrigger = "volumeThresholdReached"
|
||||||
|
UnitThresholdReached SMFTrigger = "unitThresholdReached"
|
||||||
|
TimeQuotaExhausted SMFTrigger = "timeQuotaExhausted"
|
||||||
|
VolumeQuotaExhausted SMFTrigger = "volumeQuotaExhausted"
|
||||||
|
UnitQuotaExhausted SMFTrigger = "unitQuotaExhausted"
|
||||||
|
ExpiryOfQuotaValidityTime SMFTrigger = "expiryOfQuotaValidityTime"
|
||||||
|
ExpiryOfQuotaHoldingTime SMFTrigger = "expiryOfQuotaHoldingTime"
|
||||||
|
EndOfPDUSession SMFTrigger = "endOfPDUSession"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CdrSMFTrigger struct {
|
||||||
|
SMFTrigger SMFTrigger `json:"sMFTrigger"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrQuotaManagementIndicator string
|
||||||
|
|
||||||
|
// List of QuotaManagementIndicator
|
||||||
|
const (
|
||||||
|
Cdr_QMI_ONLINE_CHARGING CdrQuotaManagementIndicator = "ONLINE_CHARGING"
|
||||||
|
Cdr_QMI_OFFLINE_CHARGING CdrQuotaManagementIndicator = "OFFLINE_CHARGING"
|
||||||
|
Cdr_QMI_QUOTA_MANAGEMENT_SUSPENDED CdrQuotaManagementIndicator = "QUOTA_MANAGEMENT_SUSPENDED"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CdrUsedUnitContainer struct {
|
||||||
|
ServiceIdentifier *int32 `json:"serviceIdentifier,omitempty"`
|
||||||
|
QuotaManagementIndicatorExt CdrQuotaManagementIndicator `json:"quotaManagementIndicatorExt,omitempty"`
|
||||||
|
Triggers []SMFTrigger `json:"triggers,omitempty"`
|
||||||
|
TriggerTimestamp *time.Time `json:"triggerTimestamp,omitempty"`
|
||||||
|
Time *uint32 `json:"time,omitempty"`
|
||||||
|
DataTotalVolume *uint64 `json:"dataTotalVolume,omitempty"`
|
||||||
|
DataVolumeUplink *uint64 `json:"dataVolumeUplink,omitempty"`
|
||||||
|
DataVolumeDownlink *uint64 `json:"dataVolumeDownlink,omitempty"`
|
||||||
|
ServiceSpecificUnits *uint64 `json:"serviceSpecificUnits,omitempty"`
|
||||||
|
EventTimeStamp *time.Time `json:"eventTimeStamp,omitempty"`
|
||||||
|
LocalSequenceNumber int32 `json:"localSequenceNumber"`
|
||||||
|
//PDUContainerInformation *PduContainerInformation `json:"pDUContainerInformation,omitempty"`
|
||||||
|
//NSPAContainerInformation *NspaContainerInformation `json:"nSPAContainerInformation,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrMultipleUnitUsage struct {
|
||||||
|
RatingGroup uint32 `json:"ratingGroup" yaml:"ratingGroup" bson:"ratingGroup" mapstructure:"RatingGroup"`
|
||||||
|
UsedUnitContainer []CdrUsedUnitContainer `json:"usedUnitContainer,omitempty" yaml:"usedUnitContainer" bson:"usedUnitContainer" mapstructure:"UsedUnitContainer"`
|
||||||
|
//UPFID string `json:"uPFID,omitempty" yaml:"uPFID" bson:"uPFID" mapstructure:"UPFID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrSubscriberEquipmentNumber struct {
|
||||||
|
SubscriberEquipmentNumberType string `json:"subscriberEquipmentNumberType"`
|
||||||
|
SubscriberEquipmentNumberData string `json:"subscriberEquipmentNumberData"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrNetworkSliceInstanceID struct {
|
||||||
|
SST int32 `json:"sST"`
|
||||||
|
|
||||||
|
SD string `json:"sD,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrPduAddress struct {
|
||||||
|
PDUIPv4Address string `json:"pDUIPv4Address,omitempty"`
|
||||||
|
PDUIPv6AddresswithPrefix string `json:"pDUIPv6AddresswithPrefix,omitempty"`
|
||||||
|
IPV4dynamicAddressFlag bool `json:"iPV4dynamicAddressFlag,omitempty"`
|
||||||
|
IPV6dynamicPrefixFlag bool `json:"iPv6dynamicPrefixFlag,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrArp struct {
|
||||||
|
PriorityLevel int32 `json:"priorityLevel"`
|
||||||
|
PreemptionCapability string `json:"preemptionCapability"`
|
||||||
|
PreemptionVulnerability string `json:"preemptionVulnerability"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrAuthorizedQosInformation struct {
|
||||||
|
FiveQi int `json:"fiveQi"`
|
||||||
|
ARP *CdrArp `json:"aRP,omitempty"`
|
||||||
|
PriorityLevel *int32 `json:"priorityLevel,omitempty"`
|
||||||
|
AverWindow *int32 `json:"averWindow,omitempty"`
|
||||||
|
MaxDataBurstVol *int32 `json:"maxDataBurstVol,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrSubscribedDefaultQos struct {
|
||||||
|
FiveQi int32 `json:"fiveQi,omitempty"`
|
||||||
|
ARP CdrArp `json:"aRP,omitempty"`
|
||||||
|
PriorityLevel *int32 `json:"priorityLevel,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrSessionAmbr struct {
|
||||||
|
Uplink string `json:"uplink"`
|
||||||
|
|
||||||
|
Downlink string `json:"downlink"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CdrPDUSessionChargingInformation struct {
|
||||||
|
PDUSessionChargingID int32 `json:"pDUSessionChargingID"`
|
||||||
|
UserIdentifier string `json:"userIdentifier,omitempty"` // isdn
|
||||||
|
UserEquipmentInfo *CdrSubscriberEquipmentNumber `json:"userEquipmentInfo,omitempty"` // imei/imeisv
|
||||||
|
//UserLocationInfomation *UserLocation `json:"userLocationinfo,omitempty"`
|
||||||
|
UserRoamerInOut string `json:"userRoamerInOut,omitempty"`
|
||||||
|
PDUSessionId int32 `json:"pDUSessionId"`
|
||||||
|
NetworkSliceInstanceID *CdrNetworkSliceInstanceID `json:"networkSliceInstanceID,omitempty"`
|
||||||
|
//PDUType PduSessionType `json:"pDUType,omitempty"`
|
||||||
|
SSCMode string `json:"sSCMode,omitempty"`
|
||||||
|
DNNID string `json:"dNNID"`
|
||||||
|
SUPIPLMNIdentifier string `json:"sUPIPLMNIdentifier,omitempty"`
|
||||||
|
//ServingNetworkFunctionID *ServingNetworkFunctionId `json:"servingNetworkFunctionID,omitempty"`
|
||||||
|
//RATType RatType `json:"rATType,omitempty"`
|
||||||
|
DataNetworkNameIdentifier string `json:"dataNetworkNameIdentifier,omitempty"`
|
||||||
|
PDUAddress CdrPduAddress `json:"pDUAddress,omitempty"`
|
||||||
|
AuthorizedQoSInformation *CdrAuthorizedQosInformation `json:"authorizedQoSInformation,omitempty"`
|
||||||
|
UETimeZone string `json:"uETimeZone,omitempty"`
|
||||||
|
PDUSessionstartTime *time.Time `json:"pDUSessionstartTime,omitempty"`
|
||||||
|
PDUSessionstopTime *time.Time `json:"pDUSessionstopTime,omitempty"`
|
||||||
|
Diagnostics *int `json:"diagnostics,omitempty"`
|
||||||
|
ChargingCharacteristics string `json:"chargingCharacteristics,omitempty"`
|
||||||
|
ChChSelectionMode string `json:"chChSelectionMode,omitempty"`
|
||||||
|
ThreeGPPPSDataOffStatus string `json:"threeGPPPSDataOffStatus,omitempty"`
|
||||||
|
//RANSecondaryRATUsageReport *RanSecondaryRatUsageReport `json:"rANSecondaryRATUsageReport,omitempty"`
|
||||||
|
SubscribedQoSInformation *CdrSubscribedDefaultQos `json:"subscribedQoSInformation,omitempty"`
|
||||||
|
AuthorizedSessionAMBR *CdrSessionAmbr `json:"authorizedSessionAMBR,omitempty"`
|
||||||
|
SubscribedSessionAMBR *CdrSessionAmbr `json:"subscribedSessionAMBR,omitempty"`
|
||||||
|
ServingCNPLMNID string `json:"servingCNPLMNID,omitempty"`
|
||||||
|
DnnSelectionMode string `json:"dnnSelectionMode,omitempty"`
|
||||||
|
HomeProvidedChargingID int32 `json:"homeProvidedChargingID,omitempty"`
|
||||||
|
|
||||||
|
//MAPDUNon3GPPUserLocationInfo *UserLocation `json:"mAPDUNon3GPPUserLocationInfo,omitempty" yaml:"mAPDUNon3GPPUserLocationInfo" bson:"mAPDUNon3GPPUserLocationInfo" mapstructure:"MAPDUNon3GPPUserLocationInfo"`
|
||||||
|
//PresenceReportingAreaInformation map[string]PresenceInfo `json:"presenceReportingAreaInformation,omitempty" yaml:"presenceReportingAreaInformation" bson:"presenceReportingAreaInformation" mapstructure:"PresenceReportingAreaInformation"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CauseForRecordClosing string
|
||||||
|
|
||||||
|
const (
|
||||||
|
NormalRelease CauseForRecordClosing = "normalRelease"
|
||||||
|
PartialRecord CauseForRecordClosing = "partialRecord"
|
||||||
|
AbnormalRelease CauseForRecordClosing = "abnormalRelease"
|
||||||
|
CAMELInitCallRelease CauseForRecordClosing = "cAMELInitCallRelease"
|
||||||
|
VolumeLimit CauseForRecordClosing = "volumeLimit"
|
||||||
|
TimeLimit CauseForRecordClosing = "timeLimit"
|
||||||
|
ServingNodeChange CauseForRecordClosing = "servingNodeChange"
|
||||||
|
MaxChangeCond CauseForRecordClosing = "maxChangeCond"
|
||||||
|
ManagementIntervention CauseForRecordClosing = "managementIntervention"
|
||||||
|
IntraSGSNIntersystemChange CauseForRecordClosing = "intraSGSNIntersystemChange"
|
||||||
|
RATChange CauseForRecordClosing = "rATChange"
|
||||||
|
MSTimeZoneChange CauseForRecordClosing = "mSTimeZoneChange"
|
||||||
|
SGSNPLMNIDChange CauseForRecordClosing = "sGSNPLMNIDChange "
|
||||||
|
SGWChange CauseForRecordClosing = "sGWChange"
|
||||||
|
APNAMBRChange CauseForRecordClosing = "aPNAMBRChange"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ChargingRecord struct {
|
||||||
|
RecordType string `json:"recordType"`
|
||||||
|
ChargingID int `json:"chargingID"`
|
||||||
|
RecordingNetworkFunctionID string `json:"recordingNetworkFunctionID"` // UUID
|
||||||
|
SubscriberIdentifier CdrSubscriptionID `json:"subscriberIdentifier,omitempty"`
|
||||||
|
NFunctionConsumerInformation CdrNetWorkFuctionInfomation `json:"nFunctionConsumerInformation"`
|
||||||
|
Triggers []CdrSMFTrigger `json:"triggers,omitempty"`
|
||||||
|
ListOfMultipleUnitUsage []CdrMultipleUnitUsage `json:"listOfMultipleUnitUsage,omitempty"`
|
||||||
|
RecordOpeningTime string `json:"recordOpeningTime"`
|
||||||
|
Duration int `json:"duration"`
|
||||||
|
RecordSequenceNumber int `json:"recordSequenceNumber,omitempty"`
|
||||||
|
CauseForRecClosing CauseForRecordClosing `json:"causeForRecClosing"`
|
||||||
|
Diagnostics *int `json:"diagnostics,omitempty"`
|
||||||
|
LocalRecordSequenceNumber int `json:"localRecordSequenceNumber,omitempty"`
|
||||||
|
PDUSessionChargingInformation CdrPDUSessionChargingInformation `json:"pDUSessionChargingInformation,omitempty"`
|
||||||
|
InvocationTimestamp string `json:"invocationTimestamp,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type CDREvent struct {
|
type CDREvent struct {
|
||||||
NeType string `json:"neType" xorm:"ne_type"`
|
NeType string `json:"neType" xorm:"ne_type"`
|
||||||
NeName string `json:"neName" xorm:"ne_name"`
|
NeName string `json:"neName" xorm:"ne_name"`
|
||||||
@@ -29,8 +214,8 @@ type CDREvent struct {
|
|||||||
CDR map[string]any `json:"CDR" xorm:"cdr_json"`
|
CDR map[string]any `json:"CDR" xorm:"cdr_json"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func PostCDREventFromNF(w http.ResponseWriter, r *http.Request) {
|
func PostCDREventFromIMS(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Info("PostCDREventFromNF processing... ")
|
log.Info("PostCDREventFromIMS processing... ")
|
||||||
|
|
||||||
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||||
@@ -49,9 +234,9 @@ func PostCDREventFromNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
log.Trace("cdrEvent:", cdrEvent)
|
log.Trace("cdrEvent:", cdrEvent)
|
||||||
|
|
||||||
affected, err := dborm.XormInsertTableOne("cdr_event", cdrEvent)
|
affected, err := dborm.XormInsertTableOne("cdr_event_ims", cdrEvent)
|
||||||
if err != nil && affected <= 0 {
|
if err != nil && affected <= 0 {
|
||||||
log.Error("Failed to insert cdr_event:", err)
|
log.Error("Failed to insert cdr_event_ims:", err)
|
||||||
services.ResponseInternalServerError500ProcessError(w, err)
|
services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -65,3 +250,40 @@ func PostCDREventFromNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
services.ResponseStatusOK204NoContent(w)
|
services.ResponseStatusOK204NoContent(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PostCDREventFromSMF(w http.ResponseWriter, r *http.Request) {
|
||||||
|
log.Info("PostCDREventFromSMF processing... ")
|
||||||
|
|
||||||
|
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||||
|
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Faile to io.ReadAll: ", err)
|
||||||
|
services.ResponseNotFound404UriNotExist(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cdrEvent := new(CDREvent)
|
||||||
|
err = json.Unmarshal(body, &cdrEvent)
|
||||||
|
if cdrEvent.NeType == "" || err != nil {
|
||||||
|
log.Error("Failed to Unmarshal cdrEvent:", err)
|
||||||
|
services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Trace("cdrEvent:", cdrEvent)
|
||||||
|
|
||||||
|
affected, err := dborm.XormInsertTableOne("cdr_event_smf", cdrEvent)
|
||||||
|
if err != nil && affected <= 0 {
|
||||||
|
log.Error("Failed to insert cdr_event_smf:", err)
|
||||||
|
services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 推送到ws订阅组
|
||||||
|
// if v, ok := cdrEvent.CDR["recordType"]; ok {
|
||||||
|
// if v == "MOC" || v == "MTSM" {
|
||||||
|
// wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_IMS_CDR, cdrEvent)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
services.ResponseStatusOK204NoContent(w)
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"be.ems/lib/core/utils/ctx"
|
||||||
"be.ems/lib/dborm"
|
"be.ems/lib/dborm"
|
||||||
"be.ems/lib/log"
|
"be.ems/lib/log"
|
||||||
"be.ems/lib/services"
|
"be.ems/lib/services"
|
||||||
"be.ems/restagent/config"
|
"be.ems/restagent/config"
|
||||||
|
neModel "be.ems/src/modules/network_element/model"
|
||||||
|
neService "be.ems/src/modules/network_element/service"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -503,22 +505,54 @@ func UploadLicenseFileData(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
neLicense := dborm.NeLicense{
|
|
||||||
NeType: neTypeUpper,
|
// neLicense := dborm.NeLicense{
|
||||||
NeID: neId,
|
// NeType: neTypeUpper,
|
||||||
Status: "ACTIVE",
|
// NeID: neId,
|
||||||
Path: licensePath,
|
// Status: "ACTIVE",
|
||||||
FileName: licenseFileName,
|
// Path: licensePath,
|
||||||
Comment: comment,
|
// FileName: licenseFileName,
|
||||||
|
// Comment: comment,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// log.Debug("neLicense:", neLicense)
|
||||||
|
// _, err = dborm.XormInsertTableOne("ne_license", neLicense)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Error("Faile to XormInsertTableOne:", err)
|
||||||
|
// services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
neLicense := neModel.NeLicense{
|
||||||
|
NeType: neTypeUpper,
|
||||||
|
NeId: neId,
|
||||||
|
Status: "0",
|
||||||
|
LicensePath: neFilePath,
|
||||||
|
Remark: comment,
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("neLicense:", neLicense)
|
log.Debug("neLicense:", neLicense)
|
||||||
_, err = dborm.XormInsertTableOne("ne_license", neLicense)
|
|
||||||
if err != nil {
|
// 检查是否存在授权记录
|
||||||
log.Error("Faile to XormInsertTableOne:", err)
|
neLicense2 := neService.NewNeLicenseImpl.SelectByNeTypeAndNeID(neTypeUpper, neId)
|
||||||
services.ResponseInternalServerError500ProcessError(w, err)
|
if neLicense2.NeId != neId {
|
||||||
return
|
// 读取授权码
|
||||||
|
code, _ := neService.NewNeLicenseImpl.ReadLicenseInfo(neLicense)
|
||||||
|
neLicense.ActivationRequestCode = code
|
||||||
|
|
||||||
|
neLicense.CreateBy = ctx.LoginUserToUserName(r)
|
||||||
|
insertId := neService.NewNeLicenseImpl.Insert(neLicense)
|
||||||
|
if insertId != "" {
|
||||||
|
services.ResponseStatusOK204NoContent(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
neLicense2.UpdateBy = ctx.LoginUserToUserName(r)
|
||||||
|
upRows := neService.NewNeLicenseImpl.Update(neLicense2)
|
||||||
|
if upRows > 0 {
|
||||||
|
services.ResponseStatusOK204NoContent(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
services.ResponseStatusOK204NoContent(w)
|
services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SoftwareStatusUploaded = "Uploaded"
|
SoftwareStatusUploaded = "3"
|
||||||
SoftwareStatusInactive = "Inactive"
|
SoftwareStatusInactive = "3"
|
||||||
SoftwareStatusActive = "Active"
|
SoftwareStatusActive = "1"
|
||||||
DigestsSignOkString = "digests signatures OK"
|
DigestsSignOkString = "digests signatures OK"
|
||||||
SoftwareVerifiedOk = "Verified OK"
|
SoftwareVerifiedOk = "Verified OK"
|
||||||
)
|
)
|
||||||
@@ -419,7 +419,7 @@ func DownloadSoftwareFile(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fileName := (*neSoftware)[0]["file_name"]
|
fileName := (*neSoftware)[0]["name"]
|
||||||
path := (*neSoftware)[0]["path"]
|
path := (*neSoftware)[0]["path"]
|
||||||
md5Sum := (*neSoftware)[0]["md5_sum"]
|
md5Sum := (*neSoftware)[0]["md5_sum"]
|
||||||
|
|
||||||
@@ -473,7 +473,7 @@ func DeleteSoftwareFile(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fileName := (*neSoftware)[0]["file_name"]
|
fileName := (*neSoftware)[0]["name"]
|
||||||
path := (*neSoftware)[0]["path"]
|
path := (*neSoftware)[0]["path"]
|
||||||
filePath := fmt.Sprintf("%s/%s", path, fileName)
|
filePath := fmt.Sprintf("%s/%s", path, fileName)
|
||||||
err = os.Remove(filePath)
|
err = os.Remove(filePath)
|
||||||
@@ -560,7 +560,7 @@ func DistributeSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fileName := (*neSoftware)[0]["file_name"]
|
fileName := (*neSoftware)[0]["name"]
|
||||||
path := (*neSoftware)[0]["path"]
|
path := (*neSoftware)[0]["path"]
|
||||||
srcFile := fmt.Sprintf("%s/%s", path, fileName)
|
srcFile := fmt.Sprintf("%s/%s", path, fileName)
|
||||||
|
|
||||||
@@ -611,7 +611,7 @@ func DistributeSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
Version: (*neSoftware)[0]["version"],
|
Version: (*neSoftware)[0]["version"],
|
||||||
FilePath: fmt.Sprintf("%s/software/%s/%s", config.GetYamlConfig().NE.OmcDir, neTypeLower, fileName),
|
FilePath: fmt.Sprintf("%s/software/%s/%s", config.GetYamlConfig().NE.OmcDir, neTypeLower, fileName),
|
||||||
PreVersion: (*neVersion)[0]["version"],
|
PreVersion: (*neVersion)[0]["version"],
|
||||||
PreFile: (*neVersion)[0]["file_path"],
|
PreFile: (*neVersion)[0]["path"],
|
||||||
Status: SoftwareStatusInactive,
|
Status: SoftwareStatusInactive,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -695,21 +695,29 @@ func ActiveSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
log.Trace("neVersion:", neVersion)
|
log.Trace("neVersion:", neVersion)
|
||||||
|
|
||||||
if !config.GetYamlConfig().OMC.TestMode {
|
if !config.GetYamlConfig().OMC.TestMode {
|
||||||
filePath := (*neVersion)[0]["file_path"]
|
filePath := (*neVersion)[0]["path"]
|
||||||
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
||||||
srcFile := fmt.Sprintf("%s/actpkg.sh", config.GetYamlConfig().OMC.BinDir)
|
|
||||||
|
|
||||||
|
runCmd := fmt.Sprintf("sudo rm -f %s/actpkg.sh", config.GetYamlConfig().NE.ScpDir)
|
||||||
|
err = RunSSHCmd(sshHost, runCmd)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to run cmd: %s", runCmd)
|
||||||
|
services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
srcFile := fmt.Sprintf("%s/actpkg.sh", config.GetYamlConfig().OMC.BinDir)
|
||||||
scpDir := fmt.Sprintf("%s@%s:%s", config.GetYamlConfig().NE.User,
|
scpDir := fmt.Sprintf("%s@%s:%s", config.GetYamlConfig().NE.User,
|
||||||
neInfo.Ip, config.GetYamlConfig().NE.ScpDir)
|
neInfo.Ip, config.GetYamlConfig().NE.ScpDir)
|
||||||
cmd := exec.Command("scp", "-r", srcFile, scpDir)
|
cmd := exec.Command("scp", "-r", srcFile, scpDir)
|
||||||
_, err := cmd.CombinedOutput()
|
_, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Faile to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip)
|
log.Errorf("Failed to scp NF: neType=%s, neId=%s, ip=%s", neType, neId, neInfo.Ip)
|
||||||
services.ResponseInternalServerError500ProcessError(w, err)
|
services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
runCmd := fmt.Sprintf("sudo %s/actpkg.sh '%s' %s",
|
runCmd = fmt.Sprintf("sudo %s/actpkg.sh '%s' %s",
|
||||||
config.GetYamlConfig().NE.ScpDir, filePath, neTypeUpper)
|
config.GetYamlConfig().NE.ScpDir, filePath, neTypeUpper)
|
||||||
if neTypeLower == "omc" {
|
if neTypeLower == "omc" {
|
||||||
idNeVersion, _ := strconv.Atoi((*neVersion)[0]["id"])
|
idNeVersion, _ := strconv.Atoi((*neVersion)[0]["id"])
|
||||||
@@ -897,6 +905,14 @@ func RollBackSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
if !config.GetYamlConfig().OMC.TestMode {
|
if !config.GetYamlConfig().OMC.TestMode {
|
||||||
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
sshHost := fmt.Sprintf("%s@%s", config.GetYamlConfig().NE.User, neInfo.Ip)
|
||||||
|
runCmd := fmt.Sprintf("sudo rm -f %s/rbkpkg.sh", config.GetYamlConfig().NE.ScpDir)
|
||||||
|
err = RunSSHCmd(sshHost, runCmd)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to run cmd: %s", runCmd)
|
||||||
|
services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
srcFile := fmt.Sprintf("%s/rbkpkg.sh", config.GetYamlConfig().OMC.BinDir)
|
srcFile := fmt.Sprintf("%s/rbkpkg.sh", config.GetYamlConfig().OMC.BinDir)
|
||||||
|
|
||||||
scpDir := fmt.Sprintf("%s@%s:%s", config.GetYamlConfig().NE.User,
|
scpDir := fmt.Sprintf("%s@%s:%s", config.GetYamlConfig().NE.User,
|
||||||
@@ -909,7 +925,7 @@ func RollBackSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
runCmd := fmt.Sprintf("sudo %s/rbkpkg.sh '%s' %s",
|
runCmd = fmt.Sprintf("sudo %s/rbkpkg.sh '%s' %s",
|
||||||
config.GetYamlConfig().NE.ScpDir, filePath, neTypeUpper)
|
config.GetYamlConfig().NE.ScpDir, filePath, neTypeUpper)
|
||||||
if neTypeLower == "omc" {
|
if neTypeLower == "omc" {
|
||||||
idNeVersion, _ := strconv.Atoi((*neVersion)[0]["id"])
|
idNeVersion, _ := strconv.Atoi((*neVersion)[0]["id"])
|
||||||
@@ -919,7 +935,7 @@ func RollBackSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
PreVersion: "-",
|
PreVersion: "-",
|
||||||
PreFile: "-",
|
PreFile: "-",
|
||||||
NewVersion: (*neVersion)[0]["version"],
|
NewVersion: (*neVersion)[0]["version"],
|
||||||
NewFile: (*neVersion)[0]["file_path"],
|
NewFile: (*neVersion)[0]["path"],
|
||||||
Status: SoftwareStatusActive,
|
Status: SoftwareStatusActive,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1021,7 +1037,7 @@ func RollBackSoftwareToNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
PreVersion: "-",
|
PreVersion: "-",
|
||||||
PreFile: "-",
|
PreFile: "-",
|
||||||
NewVersion: (*neVersion)[0]["version"],
|
NewVersion: (*neVersion)[0]["version"],
|
||||||
NewFile: (*neVersion)[0]["file_path"],
|
NewFile: (*neVersion)[0]["path"],
|
||||||
Status: SoftwareStatusActive,
|
Status: SoftwareStatusActive,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,13 +72,13 @@ func UploadFile(w http.ResponseWriter, r *http.Request) {
|
|||||||
fileName = fileNamePath
|
fileName = fileNamePath
|
||||||
} else {
|
} else {
|
||||||
path = config.GetYamlConfig().OMC.FrontUpload
|
path = config.GetYamlConfig().OMC.FrontUpload
|
||||||
fileName, err := services.HandleUploadFile(r, path, fileName)
|
fileNamePath, err := services.HandleUploadFile(r, path, fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Faile to HandleUploadFile:", err)
|
log.Error("Faile to HandleUploadFile:", err)
|
||||||
services.ResponseInternalServerError500ProcessError(w, err)
|
services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fileName = fileName
|
fileName = fileNamePath
|
||||||
}
|
}
|
||||||
log.Debugf("upload file=%s to path=%s", fileName, path)
|
log.Debugf("upload file=%s to path=%s", fileName, path)
|
||||||
|
|
||||||
|
|||||||
@@ -435,11 +435,20 @@ func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
SetAlarmAckInfo(valueJson, &alarmData)
|
SetAlarmAckInfo(valueJson, &alarmData)
|
||||||
}
|
}
|
||||||
log.Debug("alarmData:", alarmData)
|
log.Debug("alarmData:", alarmData)
|
||||||
affected, err := session.Insert(alarmData)
|
if alarmData.OrigSeverity == "Event" && config.GetYamlConfig().Alarm.SplitEventAlarm {
|
||||||
if err != nil && affected <= 0 {
|
affected, err := xEngine.Table("alarm_event").InsertOne(alarmData)
|
||||||
log.Error("Failed to insert alarm data:", err)
|
if err != nil && affected <= 0 {
|
||||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
log.Error("Failed to insert alarm_event:", err)
|
||||||
continue
|
services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
affected, err := session.Insert(alarmData)
|
||||||
|
if err != nil && affected <= 0 {
|
||||||
|
log.Error("Failed to insert alarm data:", err)
|
||||||
|
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
alarmLog := new(AlarmLog)
|
alarmLog := new(AlarmLog)
|
||||||
alarmLog.NeType = alarmData.NeType
|
alarmLog.NeType = alarmData.NeType
|
||||||
@@ -451,7 +460,7 @@ func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
alarmLog.EventTime = eventTime
|
alarmLog.EventTime = eventTime
|
||||||
log.Trace("alarmLog:", alarmLog)
|
log.Trace("alarmLog:", alarmLog)
|
||||||
|
|
||||||
affected, err = session.Insert(alarmLog)
|
affected, err := session.Insert(alarmLog)
|
||||||
if err != nil && affected <= 0 {
|
if err != nil && affected <= 0 {
|
||||||
log.Error("Failed to insert alarm_log:", err)
|
log.Error("Failed to insert alarm_log:", err)
|
||||||
}
|
}
|
||||||
@@ -470,6 +479,28 @@ func PostAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
services.ResponseStatusOK200Null(w)
|
services.ResponseStatusOK200Null(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AlarmEvent struct {
|
||||||
|
AlarmSeq int `json:"alarmSeq"`
|
||||||
|
AlarmId string `json:"alarmId" xorm:"alarm_id"`
|
||||||
|
NeId string `json:"neId"`
|
||||||
|
AlarmCode int `json:"alarmCode"`
|
||||||
|
AlarmTitle string `json:"alarmTitle"`
|
||||||
|
EventTime string `json:"eventTime"`
|
||||||
|
AlarmType string `json:"alarmType"`
|
||||||
|
OrigSeverity string `json:"origSeverity"`
|
||||||
|
PVFlag string `json:"pvFlag" xorm:"pv_flag"`
|
||||||
|
NeName string `json:"neName"`
|
||||||
|
NeType string `json:"neType"`
|
||||||
|
ObjectUid string `json:"objectUid" xorm:"object_uid"`
|
||||||
|
ObjectName string `json:"objectName" xorm:"object_name"`
|
||||||
|
ObjectType string `json:"objectType" xorm:"object_type"`
|
||||||
|
LocationInfo string `json:"locationInfo"`
|
||||||
|
Province string `json:"province"`
|
||||||
|
SpecificProblem string `json:"specificProblem"`
|
||||||
|
SpecificProblemID string `json:"specificProblemID" xorm:"specific_problem_id"`
|
||||||
|
AddInfo string `json:"addInfo"`
|
||||||
|
}
|
||||||
|
|
||||||
// process alarm get from NFs
|
// process alarm get from NFs
|
||||||
func GetAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
func GetAlarmFromNF(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Debug("GetAlarmFromNF processing... ")
|
log.Debug("GetAlarmFromNF processing... ")
|
||||||
|
|||||||
@@ -1,313 +0,0 @@
|
|||||||
package maintenance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path"
|
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/dborm"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
"be.ems/lib/services"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
"github.com/shirou/gopsutil/cpu"
|
|
||||||
"github.com/shirou/gopsutil/disk"
|
|
||||||
"github.com/shirou/gopsutil/mem"
|
|
||||||
)
|
|
||||||
|
|
||||||
// (1) OMC能够对相关的文件系统资源、内存、CPU资源、数据存储空间、数据库空间等系统指标进行监控管理;
|
|
||||||
// 对于虚拟化部署OMC系统,能够对虚机内存、虚机CPU、虚拟存储空间、文件系统资源、数据库空间等指标进行监控,提供界面截图 ;
|
|
||||||
|
|
||||||
// (2) 系统监控指标的采样时间和阈值可由用户设定,超过阈值将产生不同级别的告警,提供界面截图 ;
|
|
||||||
|
|
||||||
// (3) OMC能够方便的查询数据库连接情况;并可手工干预数据库的连接,能方便的终结非法的数据库连接 ;
|
|
||||||
|
|
||||||
// (4) 用户能方便的查询系统进程、应用进程等的进程名、进程类型、开始时间、运行主机等信息,提供界面截图
|
|
||||||
// (5) 用户能方便的对系统进程、应用进程等做中断或者启动操作,提供界面截图
|
|
||||||
|
|
||||||
// (6) 对于文件系统资源、内存、CPU资源、数据存储空间、数据库空间等系统指标数据,要求OMC能够保存至少3个月,提供界面截图 ;
|
|
||||||
// (7) 用户可以按照需求自定义报表模板并生成OMC系统维护数据报表,提供界面截图 ;
|
|
||||||
|
|
||||||
// (8) OMC具备自身告警管理功能,对于传统OMC系统,如:服务器单电源告警,存储硬盘告警、OMC系统软件故障等;
|
|
||||||
// 对于虚拟化OMC系统,如虚机告警、虚拟硬盘告警等,提供界面截图 。
|
|
||||||
|
|
||||||
var (
|
|
||||||
// parameter config management
|
|
||||||
Uri = config.UriPrefix + "/maintenance/{apiVersion}/zz"
|
|
||||||
|
|
||||||
// (1) OMC能够对相关的文件系统资源、内存、CPU资源、数据存储空间、数据库空间等系统指标进行监控管理;
|
|
||||||
UriPref = config.UriPrefix + "/maintenance/{apiVersion}/pref"
|
|
||||||
|
|
||||||
// (6) 对于文件系统资源、内存、CPU资源、数据存储空间、数据库空间等系统指标数据,要求OMC能够保存至少3个月,提供界面截图 ;
|
|
||||||
UriPrefLog = config.UriPrefix + "/maintenance/{apiVersion}/prefLog"
|
|
||||||
|
|
||||||
// (2) 系统监控指标的采样时间和阈值可由用户设定,超过阈值将产生不同级别的告警,提供界面截图 ;
|
|
||||||
UriConfig = config.UriPrefix + "/maintenance/{apiVersion}/config"
|
|
||||||
|
|
||||||
// (3) OMC能够方便的查询数据库连接情况;并可手工干预数据库的连接,能方便的终结非法的数据库连接
|
|
||||||
UriSqlClient = config.UriPrefix + "/maintenance/{apiVersion}/sqlClient"
|
|
||||||
|
|
||||||
// (4) 用户能方便的查询系统进程、应用进程等的进程名、进程类型、开始时间、运行主机等信息,提供界面截图
|
|
||||||
// (5) 用户能方便的对系统进程、应用进程等做中断或者启动操作,提供界面截图
|
|
||||||
UriTop = config.UriPrefix + "/maintenance/{apiVersion}/top"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// 定時收集 TODO
|
|
||||||
prefLogSave("")
|
|
||||||
}
|
|
||||||
|
|
||||||
func List(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Println("zz List")
|
|
||||||
services.ResponseStatusOK200Null(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 性能指標
|
|
||||||
func prefInfo(dirName string) map[string]any {
|
|
||||||
data := make(map[string]any)
|
|
||||||
|
|
||||||
// 显示文件資源目录
|
|
||||||
dirPath := "D://"
|
|
||||||
if runtime.GOOS == "linux" {
|
|
||||||
dirPath = "/home"
|
|
||||||
}
|
|
||||||
// 訪問下級
|
|
||||||
if dirName != "" {
|
|
||||||
dirPath = path.Join(dirPath, dirName)
|
|
||||||
}
|
|
||||||
dir_list, e := os.ReadDir(dirPath)
|
|
||||||
if e != nil {
|
|
||||||
log.Error(e)
|
|
||||||
}
|
|
||||||
list := make([]map[string]any, 0)
|
|
||||||
for _, v := range dir_list {
|
|
||||||
o, err := v.Info()
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
list = append(list, map[string]any{
|
|
||||||
"name": o.Name(),
|
|
||||||
"size": o.Size(),
|
|
||||||
"mode": o.Mode().String(),
|
|
||||||
"modTime": o.ModTime().Format("2006-01-02 15:04:05"),
|
|
||||||
"isDir": o.IsDir(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
data["dirList"] = list
|
|
||||||
|
|
||||||
// 文件資源使用率
|
|
||||||
u, _ := disk.Usage(dirPath)
|
|
||||||
usedGB := int(u.Used) / (1024 * 1024 * 1024 * 1)
|
|
||||||
data["dirUse"] = fmt.Sprintf("%d", usedGB)
|
|
||||||
|
|
||||||
// CPU使用率
|
|
||||||
percent, err := cpu.Percent(time.Second, false)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
}
|
|
||||||
data["cpuUse"] = fmt.Sprintf("%.2f", percent[0])
|
|
||||||
|
|
||||||
// 内存使用率
|
|
||||||
memInfo, err := mem.VirtualMemory()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
}
|
|
||||||
data["memUse"] = memInfo.UsedPercent
|
|
||||||
|
|
||||||
// 獲取數據庫占用空間
|
|
||||||
if dborm.DbClient.XEngine != nil {
|
|
||||||
conf := config.GetYamlConfig()
|
|
||||||
result, err := dborm.DbClient.XEngine.QueryString(`SELECT
|
|
||||||
CONCAT(TRUNCATE(SUM(data_length)/1024/1024,2),'MB') AS data_size,
|
|
||||||
CONCAT(TRUNCATE(SUM(max_data_length)/1024/1024,2),'MB') AS max_data_size,
|
|
||||||
CONCAT(TRUNCATE(SUM(data_free)/1024/1024,2),'MB') AS data_free,
|
|
||||||
CONCAT(TRUNCATE(SUM(index_length)/1024/1024,2),'MB') AS index_size
|
|
||||||
FROM information_schema.tables WHERE TABLE_SCHEMA = ?;
|
|
||||||
`, conf.Database.Name)
|
|
||||||
if err == nil {
|
|
||||||
data["dbInfo"] = result[0]
|
|
||||||
} else {
|
|
||||||
data["dbInfo"] = map[string]string{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// 性能指標存入數據庫
|
|
||||||
func prefLogSave(dirName string) {
|
|
||||||
if dborm.DbClient.XEngine != nil {
|
|
||||||
data := prefInfo(dirName)
|
|
||||||
|
|
||||||
dirListByte, err := json.Marshal(data["dirList"])
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
}
|
|
||||||
dbInfoByte, err := json.Marshal(data["dbInfo"])
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
}
|
|
||||||
rse, err := dborm.DbClient.XEngine.Exec(`INSERT INTO sys_perf_data
|
|
||||||
(id, create_time, dir_used, dir_list, db_info, mem_used, cpu_used)
|
|
||||||
VALUES(NULL, NOW(), ?, ?, ?, ?, ?);
|
|
||||||
`, data["dirUse"], string(dirListByte), string(dbInfoByte), data["memUse"], data["cpuUse"])
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
}
|
|
||||||
fmt.Println(rse.LastInsertId())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET http://192.168.21.183:3040/api/rest/maintenance/v1/pref?dir=true
|
|
||||||
func Pref(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// 知道下級文件資源目录
|
|
||||||
dirName := r.URL.Query().Get("dirName")
|
|
||||||
data := prefInfo(dirName)
|
|
||||||
services.ResponseWithJson(w, http.StatusOK, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// POST http://192.168.21.183:3040/api/rest/maintenance/v1/config
|
|
||||||
func Config(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// json 請求參數獲取
|
|
||||||
var bodyArgs struct {
|
|
||||||
Key string `json:"key"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
}
|
|
||||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("io.ReadAll is failed:", err)
|
|
||||||
services.ResponseNotFound404UriNotExist(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 進行值更新
|
|
||||||
if dborm.DbClient.XEngine != nil {
|
|
||||||
result, err := dborm.DbClient.XEngine.QueryString("SELECT * FROM information_schema.processlist")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
fmt.Println(result)
|
|
||||||
rse, err := dborm.DbClient.XEngine.Exec("UPDATE sys_config SET value = ? where id = ?", "true", 100)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
fmt.Println(rse)
|
|
||||||
}
|
|
||||||
|
|
||||||
services.ResponseStatusOK200Null(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
// http://192.168.21.183:3040/api/rest/maintenance/v1/sqlClient?type=close
|
|
||||||
// http://192.168.21.183:3040/api/rest/maintenance/v1/sqlClient?type=connet
|
|
||||||
// http://192.168.21.183:3040/api/rest/maintenance/v1/sqlClient?type=user
|
|
||||||
func SqlClient(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// 关闭
|
|
||||||
isClose := r.URL.Query().Get("type")
|
|
||||||
if isClose == "close" && dborm.DbClient.XEngine != nil {
|
|
||||||
dborm.DbClient.XEngine.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重连
|
|
||||||
isConnet := r.URL.Query().Get("type")
|
|
||||||
if isConnet == "connet" && dborm.DbClient.XEngine == nil {
|
|
||||||
conf := config.GetYamlConfig()
|
|
||||||
err := dborm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
|
|
||||||
conf.Database.Host, conf.Database.Port, conf.Database.Name, conf.Database.ConnParam)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("dborm.initDbClient err:", err)
|
|
||||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询实例
|
|
||||||
isUser := r.URL.Query().Get("type")
|
|
||||||
if isUser == "user" && dborm.DbClient.XEngine != nil {
|
|
||||||
result, err := dborm.DbClient.XEngine.QueryString("SELECT * FROM information_schema.processlist")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
fmt.Println(result)
|
|
||||||
rse, err := dborm.DbClient.XEngine.Exec("KILL CONNECTION CONNECTION_ID()")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
fmt.Println(rse)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 进行连接测试
|
|
||||||
err := dborm.DbClient.XEngine.Ping()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
services.ResponseStatusOK200Null(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET http://192.168.21.183:3040/api/rest/maintenance/v1/top?grep=
|
|
||||||
func Top(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// 過濾命令
|
|
||||||
grep := r.URL.Query().Get("grep")
|
|
||||||
// 命令拼接
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "linux":
|
|
||||||
command := "ps -ef "
|
|
||||||
if grep != "" {
|
|
||||||
command += grep
|
|
||||||
}
|
|
||||||
cmd = exec.Command(command)
|
|
||||||
case "windows":
|
|
||||||
command := "wmic process list brief "
|
|
||||||
if grep != "" {
|
|
||||||
command += grep
|
|
||||||
}
|
|
||||||
cmd = exec.Command("cmd", "/C", command)
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
fmt.Println(string(out))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
services.ResponseWithJson(w, http.StatusOK, string(out))
|
|
||||||
}
|
|
||||||
|
|
||||||
// PATCH http://192.168.21.183:3040/api/rest/maintenance/v1/top?ops=&name=
|
|
||||||
func TopOps(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// json 請求參數獲取
|
|
||||||
var bodyArgs struct {
|
|
||||||
Ops string `json:"ops"`
|
|
||||||
Pid string `json:"pid"`
|
|
||||||
}
|
|
||||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("io.ReadAll is failed:", err)
|
|
||||||
services.ResponseNotFound404UriNotExist(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 命令拼接
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "linux":
|
|
||||||
switch bodyArgs.Ops {
|
|
||||||
case "kill":
|
|
||||||
cmd = exec.Command("kill", "-9", bodyArgs.Pid)
|
|
||||||
}
|
|
||||||
case "windows":
|
|
||||||
switch bodyArgs.Ops {
|
|
||||||
case "kill":
|
|
||||||
cmd = exec.Command("cmd", "/C", "taskkill", "-PID", bodyArgs.Pid, "-F")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := cmd.CombinedOutput()
|
|
||||||
fmt.Println(string(out))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
services.ResponseWithJson(w, http.StatusOK, string(out))
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package monitor
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
type MonitorBase struct {
|
|
||||||
ID uint `xorm:"id" json:"id"`
|
|
||||||
CreatedAt time.Time `xorm:"created_at" json:"createdAt"`
|
|
||||||
UpdatedAt time.Time `xorm:"updated_at" json:"updatedAt"`
|
|
||||||
|
|
||||||
Cpu float64 `xorm:"cpu" json:"cpu"`
|
|
||||||
|
|
||||||
LoadUsage float64 `xorm:"load_usage" json:"loadUsage"`
|
|
||||||
CpuLoad1 float64 `xorm:"cpu_load1" json:"cpuLoad1"`
|
|
||||||
CpuLoad5 float64 `xorm:"cpu_load5" json:"cpuLoad5"`
|
|
||||||
CpuLoad15 float64 `xorm:"cpu_load15" json:"cpuLoad15"`
|
|
||||||
|
|
||||||
Memory float64 `xorm:"memory" json:"memory"`
|
|
||||||
|
|
||||||
DbSize uint `xorm:"db_size" json:"dbSize"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MonitorIO struct {
|
|
||||||
ID uint `xorm:"id" json:"id"`
|
|
||||||
CreatedAt time.Time `xorm:"created_at" json:"createdAt"`
|
|
||||||
UpdatedAt time.Time `xorm:"updated_at" json:"updatedAt"`
|
|
||||||
|
|
||||||
Name string `xorm:"name" json:"name"`
|
|
||||||
Read uint64 `xorm:"read" json:"read"`
|
|
||||||
Write uint64 `xorm:"write" json:"write"`
|
|
||||||
Count uint64 `xorm:"count" json:"count"`
|
|
||||||
Time uint64 `xorm:"time" json:"time"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MonitorNetwork struct {
|
|
||||||
ID uint `xorm:"id" json:"id"`
|
|
||||||
CreatedAt time.Time `xorm:"created_at" json:"createdAt"`
|
|
||||||
UpdatedAt time.Time `xorm:"updated_at" json:"updatedAt"`
|
|
||||||
|
|
||||||
Name string `xorm:"name" json:"name"`
|
|
||||||
Up float64 `xorm:"up" json:"up"`
|
|
||||||
Down float64 `xorm:"down" json:"down"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MonitorSearch struct {
|
|
||||||
Param string `json:"param" validate:"required,oneof=all cpu memory load io network"`
|
|
||||||
Info string `json:"info"`
|
|
||||||
StartTime time.Time `json:"startTime"`
|
|
||||||
EndTime time.Time `json:"endTime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MonitorData struct {
|
|
||||||
Param string `json:"param" validate:"required,oneof=cpu memory load io network"`
|
|
||||||
Date []time.Time `json:"date"`
|
|
||||||
Value []interface{} `json:"value"`
|
|
||||||
}
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
package monitor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/dborm"
|
|
||||||
"be.ems/lib/services"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
"github.com/shirou/gopsutil/disk"
|
|
||||||
"github.com/shirou/gopsutil/net"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 点击【主机 - 监控】菜单,进入监控报表,直观的了解服务器的运行状态,包含【平均负载】、【CPU性能监控】、【内存使用监控】、【磁盘IO监控】、【网络IO监控】
|
|
||||||
|
|
||||||
// 可以查看昨天,今天,最近7天,最近30天,自定义时间的监控指标情况。
|
|
||||||
// 默认监控是开启的,可以在【面板设置 - 监控】页面中根据需求对监控进行开启和关闭。
|
|
||||||
// 监控数据默认保存30天,可以自行修改,也可手动清理该日志。
|
|
||||||
|
|
||||||
var (
|
|
||||||
// IP地址
|
|
||||||
UriIPAddr = config.DefaultUriPrefix + "/monitor/{apiVersion}/monitor/ipaddr"
|
|
||||||
// 可选网络
|
|
||||||
UriNetOpt = config.DefaultUriPrefix + "/monitor/{apiVersion}/monitor/netoptions"
|
|
||||||
// 可选磁盘
|
|
||||||
UriIoOpt = config.DefaultUriPrefix + "/monitor/{apiVersion}/monitor/iooptions"
|
|
||||||
// 加载
|
|
||||||
UriLoad = config.DefaultUriPrefix + "/monitor/{apiVersion}/monitor/load"
|
|
||||||
|
|
||||||
// IP地址
|
|
||||||
UriIPAddrOAM = config.UriPrefix + "/monitor/{apiVersion}/monitor/ipaddr"
|
|
||||||
// 可选网络
|
|
||||||
UriNetOptOAM = config.UriPrefix + "/monitor/{apiVersion}/monitor/netoptions"
|
|
||||||
// 可选磁盘
|
|
||||||
UriIoOptOAM = config.UriPrefix + "/monitor/{apiVersion}/monitor/iooptions"
|
|
||||||
// 加载
|
|
||||||
UriLoadOAM = config.UriPrefix + "/monitor/{apiVersion}/monitor/load"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IPAddr IP地址
|
|
||||||
func IPAddr(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ipAddrs := []map[string]string{}
|
|
||||||
interfaces, err := net.Interfaces()
|
|
||||||
if err == nil {
|
|
||||||
for _, iface := range interfaces {
|
|
||||||
addrs := map[string]string{}
|
|
||||||
for _, v := range iface.Addrs {
|
|
||||||
prefix := strings.Split(v.Addr, "/")[0]
|
|
||||||
if strings.Contains(prefix, "::") {
|
|
||||||
addrs["IPv6"] = prefix
|
|
||||||
}
|
|
||||||
if strings.Contains(prefix, ".") {
|
|
||||||
addrs["IPv4"] = prefix
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ipAddrs = append(ipAddrs, addrs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
services.ResponseWithJson(w, 200, ipAddrs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Netoptions 可选网络
|
|
||||||
func Netoptions(w http.ResponseWriter, r *http.Request) {
|
|
||||||
netStat, _ := net.IOCounters(true)
|
|
||||||
var options []string
|
|
||||||
options = append(options, "all")
|
|
||||||
for _, net := range netStat {
|
|
||||||
options = append(options, net.Name)
|
|
||||||
}
|
|
||||||
sort.Strings(options)
|
|
||||||
services.ResponseWithJson(w, 200, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iooptions 可选磁盘
|
|
||||||
func Iooptions(w http.ResponseWriter, r *http.Request) {
|
|
||||||
diskStat, _ := disk.IOCounters()
|
|
||||||
var options []string
|
|
||||||
options = append(options, "all")
|
|
||||||
for _, net := range diskStat {
|
|
||||||
options = append(options, net.Name)
|
|
||||||
}
|
|
||||||
sort.Strings(options)
|
|
||||||
services.ResponseWithJson(w, 200, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadMonitor 载入监控
|
|
||||||
func LoadMonitor(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// json 請求參數獲取
|
|
||||||
var bodyArgs MonitorSearch
|
|
||||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
|
||||||
if err != nil || dborm.DbClient.XEngine == nil {
|
|
||||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
loc := time.Now().Location()
|
|
||||||
bodyArgs.StartTime = bodyArgs.StartTime.In(loc)
|
|
||||||
bodyArgs.EndTime = bodyArgs.EndTime.In(loc)
|
|
||||||
|
|
||||||
var backdatas []MonitorData
|
|
||||||
if bodyArgs.Param == "all" || bodyArgs.Param == "cpu" || bodyArgs.Param == "memory" || bodyArgs.Param == "load" {
|
|
||||||
var bases []MonitorBase
|
|
||||||
err := dborm.DbClient.XEngine.Table("monitor_base").
|
|
||||||
Where("created_at > ? AND created_at < ?", bodyArgs.StartTime, bodyArgs.EndTime).
|
|
||||||
Desc("created_at").
|
|
||||||
Find(&bases)
|
|
||||||
if err != nil {
|
|
||||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var itemData MonitorData
|
|
||||||
itemData.Param = "base"
|
|
||||||
for _, base := range bases {
|
|
||||||
itemData.Date = append(itemData.Date, base.CreatedAt)
|
|
||||||
itemData.Value = append(itemData.Value, base)
|
|
||||||
}
|
|
||||||
backdatas = append(backdatas, itemData)
|
|
||||||
}
|
|
||||||
if bodyArgs.Param == "all" || bodyArgs.Param == "io" {
|
|
||||||
var bases []MonitorIO
|
|
||||||
err := dborm.DbClient.XEngine.Table("monitor_io").
|
|
||||||
Where("created_at > ? AND created_at < ?", bodyArgs.StartTime, bodyArgs.EndTime).
|
|
||||||
Desc("created_at").
|
|
||||||
Find(&bases)
|
|
||||||
if err != nil {
|
|
||||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var itemData MonitorData
|
|
||||||
itemData.Param = "io"
|
|
||||||
for _, base := range bases {
|
|
||||||
itemData.Date = append(itemData.Date, base.CreatedAt)
|
|
||||||
itemData.Value = append(itemData.Value, base)
|
|
||||||
}
|
|
||||||
backdatas = append(backdatas, itemData)
|
|
||||||
}
|
|
||||||
if bodyArgs.Param == "all" || bodyArgs.Param == "network" {
|
|
||||||
var bases []MonitorNetwork
|
|
||||||
err := dborm.DbClient.XEngine.Table("monitor_network").
|
|
||||||
Where("name = ? AND created_at > ? AND created_at < ?", bodyArgs.Info, bodyArgs.StartTime, bodyArgs.EndTime).
|
|
||||||
Desc("created_at").
|
|
||||||
Find(&bases)
|
|
||||||
if err != nil {
|
|
||||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var itemData MonitorData
|
|
||||||
itemData.Param = "network"
|
|
||||||
for _, base := range bases {
|
|
||||||
itemData.Date = append(itemData.Date, base.CreatedAt)
|
|
||||||
itemData.Value = append(itemData.Value, base)
|
|
||||||
}
|
|
||||||
backdatas = append(backdatas, itemData)
|
|
||||||
}
|
|
||||||
services.ResponseWithJson(w, 200, backdatas)
|
|
||||||
}
|
|
||||||
@@ -1,233 +0,0 @@
|
|||||||
package monitor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/lib/dborm"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
"github.com/robfig/cron/v3"
|
|
||||||
"github.com/shirou/gopsutil/v3/cpu"
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
"github.com/shirou/gopsutil/v3/load"
|
|
||||||
"github.com/shirou/gopsutil/v3/mem"
|
|
||||||
"github.com/shirou/gopsutil/v3/net"
|
|
||||||
)
|
|
||||||
|
|
||||||
type MonitorService struct{}
|
|
||||||
|
|
||||||
type IMonitorService interface {
|
|
||||||
Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewIMonitorService() IMonitorService {
|
|
||||||
return &MonitorService{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MonitorService) Run() {
|
|
||||||
// monitorStatus, _ := dborm.XormGetConfig("SystemMonitor", "MonitorStatus")
|
|
||||||
// if monitorStatus["value"] == "disable" {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
var itemModel MonitorBase
|
|
||||||
itemModel.CreatedAt = time.Now()
|
|
||||||
itemModel.UpdatedAt = time.Now()
|
|
||||||
|
|
||||||
totalPercent, _ := cpu.Percent(3*time.Second, false)
|
|
||||||
if len(totalPercent) == 1 {
|
|
||||||
itemModel.Cpu = totalPercent[0]
|
|
||||||
}
|
|
||||||
cpuCount, _ := cpu.Counts(false)
|
|
||||||
|
|
||||||
loadInfo, _ := load.Avg()
|
|
||||||
itemModel.CpuLoad1 = loadInfo.Load1
|
|
||||||
itemModel.CpuLoad5 = loadInfo.Load5
|
|
||||||
itemModel.CpuLoad15 = loadInfo.Load15
|
|
||||||
itemModel.LoadUsage = loadInfo.Load1 / (float64(cpuCount*2) * 0.75) * 100
|
|
||||||
|
|
||||||
memoryInfo, _ := mem.VirtualMemory()
|
|
||||||
itemModel.Memory = memoryInfo.UsedPercent
|
|
||||||
|
|
||||||
var dataSize int
|
|
||||||
conf := config.GetYamlConfig()
|
|
||||||
result, err := dborm.DbClient.XEngine.QueryString("SELECT SUM(data_length) AS data_size FROM information_schema.tables WHERE TABLE_SCHEMA = ?;", conf.Database.Name)
|
|
||||||
if err != nil {
|
|
||||||
dataSize = 0
|
|
||||||
} else {
|
|
||||||
v, _ := strconv.Atoi(result[0]["data_size"])
|
|
||||||
dataSize = v
|
|
||||||
}
|
|
||||||
itemModel.DbSize = uint(dataSize)
|
|
||||||
|
|
||||||
_, errx := dborm.DbClient.XEngine.Table("monitor_base").Insert(itemModel)
|
|
||||||
if errx != nil {
|
|
||||||
log.Errorf("Insert basic monitoring data failed, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
go loadDiskIO()
|
|
||||||
go loadNetIO()
|
|
||||||
|
|
||||||
// 删除保留的记录
|
|
||||||
// monitorStoreDays, _ := dborm.XormGetConfig("SystemMonitor", "MonitorStoreDays")
|
|
||||||
// if monitorStoreDays["value"] != "" {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// storeDays, err := strconv.Atoi(MonitorStoreDays.Value)
|
|
||||||
// if err != nil {
|
|
||||||
// timeForDelete := time.Now().AddDate(0, 0, -storeDays)
|
|
||||||
// DelMonitorBase(timeForDelete)
|
|
||||||
// DelMonitorIO(timeForDelete)
|
|
||||||
// DelMonitorNet(timeForDelete)
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadDiskIO() {
|
|
||||||
ioStat, _ := disk.IOCounters()
|
|
||||||
|
|
||||||
time.Sleep(60 * time.Second)
|
|
||||||
|
|
||||||
ioStat2, _ := disk.IOCounters()
|
|
||||||
var ioList []MonitorIO
|
|
||||||
for _, io2 := range ioStat2 {
|
|
||||||
for _, io1 := range ioStat {
|
|
||||||
if io2.Name == io1.Name {
|
|
||||||
var itemIO MonitorIO
|
|
||||||
itemIO.CreatedAt = time.Now()
|
|
||||||
itemIO.UpdatedAt = time.Now()
|
|
||||||
|
|
||||||
itemIO.Name = io1.Name
|
|
||||||
if io2.ReadBytes != 0 && io1.ReadBytes != 0 && io2.ReadBytes > io1.ReadBytes {
|
|
||||||
itemIO.Read = uint64(float64(io2.ReadBytes-io1.ReadBytes) / 60)
|
|
||||||
}
|
|
||||||
if io2.WriteBytes != 0 && io1.WriteBytes != 0 && io2.WriteBytes > io1.WriteBytes {
|
|
||||||
itemIO.Write = uint64(float64(io2.WriteBytes-io1.WriteBytes) / 60)
|
|
||||||
}
|
|
||||||
|
|
||||||
if io2.ReadCount != 0 && io1.ReadCount != 0 && io2.ReadCount > io1.ReadCount {
|
|
||||||
itemIO.Count = uint64(float64(io2.ReadCount-io1.ReadCount) / 60)
|
|
||||||
}
|
|
||||||
writeCount := uint64(0)
|
|
||||||
if io2.WriteCount != 0 && io1.WriteCount != 0 && io2.WriteCount > io1.WriteCount {
|
|
||||||
writeCount = uint64(float64(io2.WriteCount-io1.WriteCount) / 60)
|
|
||||||
}
|
|
||||||
if writeCount > itemIO.Count {
|
|
||||||
itemIO.Count = writeCount
|
|
||||||
}
|
|
||||||
|
|
||||||
if io2.ReadTime != 0 && io1.ReadTime != 0 && io2.ReadTime > io1.ReadTime {
|
|
||||||
itemIO.Time = uint64(float64(io2.ReadTime-io1.ReadTime) / 60)
|
|
||||||
}
|
|
||||||
writeTime := uint64(0)
|
|
||||||
if io2.WriteTime != 0 && io1.WriteTime != 0 && io2.WriteTime > io1.WriteTime {
|
|
||||||
writeTime = uint64(float64(io2.WriteTime-io1.WriteTime) / 60)
|
|
||||||
}
|
|
||||||
if writeTime > itemIO.Time {
|
|
||||||
itemIO.Time = writeTime
|
|
||||||
}
|
|
||||||
ioList = append(ioList, itemIO)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, err := dborm.DbClient.XEngine.Table("monitor_io").Insert(ioList)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Insert io monitoring data failed, err: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadNetIO() {
|
|
||||||
netStat, _ := net.IOCounters(true)
|
|
||||||
netStatAll, _ := net.IOCounters(false)
|
|
||||||
|
|
||||||
time.Sleep(60 * time.Second)
|
|
||||||
|
|
||||||
netStat2, _ := net.IOCounters(true)
|
|
||||||
var netList []MonitorNetwork
|
|
||||||
for _, net2 := range netStat2 {
|
|
||||||
for _, net1 := range netStat {
|
|
||||||
if net2.Name == net1.Name {
|
|
||||||
var itemNet MonitorNetwork
|
|
||||||
itemNet.CreatedAt = time.Now()
|
|
||||||
itemNet.UpdatedAt = time.Now()
|
|
||||||
|
|
||||||
itemNet.Name = net1.Name
|
|
||||||
|
|
||||||
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
|
||||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / 60
|
|
||||||
}
|
|
||||||
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
|
||||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / 60
|
|
||||||
}
|
|
||||||
netList = append(netList, itemNet)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
netStatAll2, _ := net.IOCounters(false)
|
|
||||||
for _, net2 := range netStatAll2 {
|
|
||||||
for _, net1 := range netStatAll {
|
|
||||||
if net2.Name == net1.Name {
|
|
||||||
var itemNet MonitorNetwork
|
|
||||||
itemNet.Name = net1.Name
|
|
||||||
if net2.BytesSent != 0 && net1.BytesSent != 0 && net2.BytesSent > net1.BytesSent {
|
|
||||||
itemNet.Up = float64(net2.BytesSent-net1.BytesSent) / 1024 / 60
|
|
||||||
}
|
|
||||||
|
|
||||||
if net2.BytesRecv != 0 && net1.BytesRecv != 0 && net2.BytesRecv > net1.BytesRecv {
|
|
||||||
itemNet.Down = float64(net2.BytesRecv-net1.BytesRecv) / 1024 / 60
|
|
||||||
}
|
|
||||||
netList = append(netList, itemNet)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := dborm.DbClient.XEngine.Table("monitor_network").Insert(netList)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Insert network monitoring data failed, err: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var c *cron.Cron
|
|
||||||
var monitorCronID int
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
c = cron.New()
|
|
||||||
c.Start()
|
|
||||||
monitorCronID = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// StartMonitor 开始监控任务 removeBefore删除上次任务,间隔interval分钟
|
|
||||||
func StartMonitor(removeBefore bool, interval string) error {
|
|
||||||
if removeBefore {
|
|
||||||
c.Remove(cron.EntryID(monitorCronID))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取配置
|
|
||||||
if interval == "" {
|
|
||||||
v, err := dborm.XormGetConfig("SystemMonitor", "sampleTime")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
data := make(map[string]any)
|
|
||||||
err = json.Unmarshal([]byte(v["value_json"].(string)), &data)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("json StartMonitor:%s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
interval = data["sampleTime"].(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
imservice := NewIMonitorService()
|
|
||||||
monitorID, err := c.AddJob(fmt.Sprintf("@every %sm", interval), imservice)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
imservice.Run()
|
|
||||||
monitorCronID = int(monitorID)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
package psnet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
"be.ems/lib/services"
|
|
||||||
"be.ems/lib/wsinfo"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
"github.com/shirou/gopsutil/process"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// websockte通信
|
|
||||||
UriWs = config.DefaultUriPrefix + "/monitor/{apiVersion}/psnet/ws"
|
|
||||||
// 停止进程
|
|
||||||
UriStop = config.DefaultUriPrefix + "/monitor/{apiVersion}/psnet/stop"
|
|
||||||
|
|
||||||
// 检查ip端口请求
|
|
||||||
UriPing = config.DefaultUriPrefix + "/monitor/{apiVersion}/psnet/ping"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 进程管理
|
|
||||||
var wsUpgrade = websocket.Upgrader{
|
|
||||||
CheckOrigin: func(r *http.Request) bool {
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessWs
|
|
||||||
func ProcessWs(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ws, err := wsUpgrade.Upgrade(w, r, nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
wsClient := wsinfo.NewWsClient("processClient", ws)
|
|
||||||
go wsClient.Read()
|
|
||||||
go wsClient.Write()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 停止进程 {"PID":30040}
|
|
||||||
func StopProcess(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// json 請求參數獲取
|
|
||||||
var bodyArgs struct {
|
|
||||||
PID int32 `json:"PID" validate:"required"`
|
|
||||||
}
|
|
||||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("io.ReadAll is failed:", err)
|
|
||||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
proc, err := process.NewProcess(bodyArgs.PID)
|
|
||||||
if err != nil {
|
|
||||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := proc.Kill(); err != nil {
|
|
||||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
services.ResponseStatusOK200Null(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查ip端口请求
|
|
||||||
func Ping(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// json 請求參數獲取
|
|
||||||
var bodyArgs struct {
|
|
||||||
Host string `json:"host" validate:"required"`
|
|
||||||
Port string `json:"port" validate:"required"`
|
|
||||||
}
|
|
||||||
err := ctx.ShouldBindJSON(r, &bodyArgs)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("io.ReadAll is failed:", err)
|
|
||||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%s", bodyArgs.Host, bodyArgs.Port), 3*time.Second)
|
|
||||||
if err != nil {
|
|
||||||
services.ResponseErrorWithJson(w, 400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
services.ResponseStatusOK200Null(w)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -65,16 +65,16 @@ type GoldKpi struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type KpiData struct {
|
type KpiData struct {
|
||||||
ID int `json:"id" xorm:"pk 'id' '<-' autoincr"`
|
ID int `json:"id" xorm:"pk 'id' '<-' autoincr"`
|
||||||
NEType string `json:"neType" xorm:"ne_type"`
|
NEType string `json:"neType" xorm:"ne_type"`
|
||||||
NEName string `json:"neName" xorm:"ne_name"`
|
NEName string `json:"neName" xorm:"ne_name"`
|
||||||
RmUid string `json:"rmUid" xorm:"rm_uid"`
|
RmUid string `json:"rmUid" xorm:"rm_uid"`
|
||||||
Date string `json:"date" xorm:"date"`
|
Date string `json:"date" xorm:"date"`
|
||||||
StartTime time.Time `json:"startTime" xorm:"start_time"`
|
StartTime string `json:"startTime" xorm:"start_time"`
|
||||||
EndTime time.Time `json:"endTime" xorm:"end_time"`
|
EndTime string `json:"endTime" xorm:"end_time"`
|
||||||
Index int `json:"index" xorm:"index"`
|
Index int `json:"index" xorm:"index"`
|
||||||
Granularity int8 `json:"granularity" xorm:"granularity"`
|
Granularity int8 `json:"granularity" xorm:"granularity"`
|
||||||
KPIValues []KPIVal `json:"kpiValues" xorm:"json 'kpi_values'"`
|
KPIValues []KPIVal `json:"kpiValues" xorm:"json 'kpi_values'"`
|
||||||
//CreatedAt int64 `json:"createdAt" xorm:"created 'created_at'"`
|
//CreatedAt int64 `json:"createdAt" xorm:"created 'created_at'"`
|
||||||
CreatedAt int64 `json:"createdAt" xorm:"'created_at'"`
|
CreatedAt int64 `json:"createdAt" xorm:"'created_at'"`
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ func GetDateTimeFromTimeString(fmtString string, timeString string) string {
|
|||||||
return t.Format(global.DateTime)
|
return t.Format(global.DateTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// process alarm post message from NFs
|
// process KPI report post message from NFs
|
||||||
func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) {
|
func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Debug("PostKPIReportFromNF processing... ")
|
log.Debug("PostKPIReportFromNF processing... ")
|
||||||
|
|
||||||
@@ -202,6 +202,91 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||||
|
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Faile to io.ReadAll: ", err)
|
||||||
|
services.ResponseNotFound404UriNotExist(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//log.Trace("Request body:", string(body))
|
||||||
|
kpiReport := new(KpiReport)
|
||||||
|
_ = json.Unmarshal(body, &kpiReport)
|
||||||
|
//log.Trace("kpiReport:", kpiReport)
|
||||||
|
|
||||||
|
layout := time.RFC3339Nano
|
||||||
|
//kpiDate := GetDateFromTimeString(layout, kpiReport.Task.Period.StartTime)
|
||||||
|
kpiIndex, _ := strconv.Atoi(vars["index"])
|
||||||
|
startTime := global.GetFmtTimeString(layout, kpiReport.Task.Period.StartTime, time.DateTime)
|
||||||
|
endTime := global.GetFmtTimeString(layout, kpiReport.Task.Period.EndTime, time.DateTime)
|
||||||
|
// get time granularity from startTime and endTime
|
||||||
|
seconds, _ := global.GetSecondDuration(startTime, endTime)
|
||||||
|
var granularity int8 = 60
|
||||||
|
if seconds != 0 && seconds <= math.MaxInt8 && seconds >= math.MinInt8 {
|
||||||
|
granularity = int8(seconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 黄金指标事件对象
|
||||||
|
kpiEvent := map[string]any{
|
||||||
|
// kip_id ...
|
||||||
|
"neType": kpiReport.Task.NE.NeType,
|
||||||
|
"neName": kpiReport.Task.NE.NEName,
|
||||||
|
"startIndex": kpiIndex,
|
||||||
|
"timeGroup": startTime,
|
||||||
|
}
|
||||||
|
// insert into new kpi_report_xxx table
|
||||||
|
kpiData := new(KpiData)
|
||||||
|
kpiData.Date = startTime
|
||||||
|
kpiData.Index = kpiIndex
|
||||||
|
//stime, _ := time.ParseInLocation(time.RFC3339Nano, kpiReport.Task.Period.StartTime, time.Local)
|
||||||
|
//etime, _ := time.ParseInLocation(time.RFC3339Nano, kpiReport.Task.Period.EndTime, time.Local)
|
||||||
|
kpiData.StartTime = startTime
|
||||||
|
kpiData.EndTime = endTime
|
||||||
|
kpiData.Granularity = granularity
|
||||||
|
kpiData.NEName = kpiReport.Task.NE.NEName
|
||||||
|
kpiData.NEType = kpiReport.Task.NE.NeType
|
||||||
|
kpiData.RmUid = kpiReport.Task.NE.RmUID
|
||||||
|
kpiVal := new(KPIVal)
|
||||||
|
kpiData.CreatedAt = time.Now().UnixMilli()
|
||||||
|
for _, k := range kpiReport.Task.NE.KPIs {
|
||||||
|
kpiEvent[k.KPIID] = k.Value // kip_id
|
||||||
|
|
||||||
|
kpiVal.KPIID = k.KPIID
|
||||||
|
kpiVal.Value = int64(k.Value)
|
||||||
|
kpiVal.Err = k.Err
|
||||||
|
kpiData.KPIValues = append(kpiData.KPIValues, *kpiVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert kpi_report table, no session
|
||||||
|
tableName := "kpi_report_" + strings.ToLower(kpiReport.Task.NE.NeType)
|
||||||
|
affected, err := xEngine.Table(tableName).Insert(kpiData)
|
||||||
|
if err != nil && affected <= 0 {
|
||||||
|
log.Errorf("Failed to insert %s:%v", tableName, err)
|
||||||
|
services.ResponseInternalServerError500ProcessError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 推送到ws订阅组
|
||||||
|
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_KPI, kpiEvent)
|
||||||
|
if kpiReport.Task.NE.NeType == "UPF" {
|
||||||
|
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_KPI_UPF, kpiEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
services.ResponseStatusOK204NoContent(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// post kpi report from NEs, insert insto gold_kpi table, discard...
|
||||||
|
func PostGoldKPIFromNF(w http.ResponseWriter, r *http.Request) {
|
||||||
|
log.Debug("PostKPIReportFromNF processing... ")
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
apiVer := vars["apiVersion"]
|
||||||
|
if apiVer != global.ApiVersionV1 {
|
||||||
|
log.Error("Uri api version is invalid. apiVersion:", apiVer)
|
||||||
|
services.ResponseNotFound404UriNotExist(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
// body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||||
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
body, err := io.ReadAll(io.LimitReader(r.Body, global.RequestBodyMaxLen))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -244,12 +329,10 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
kpiData := new(KpiData)
|
kpiData := new(KpiData)
|
||||||
kpiData.Date = goldKpi.Date
|
kpiData.Date = goldKpi.Date
|
||||||
kpiData.Index = goldKpi.Index
|
kpiData.Index = goldKpi.Index
|
||||||
st, _ := time.ParseInLocation(time.RFC3339Nano, kpiReport.Task.Period.StartTime, time.Local)
|
//st, _ := time.ParseInLocation(time.RFC3339Nano, kpiReport.Task.Period.StartTime, time.Local)
|
||||||
et, _ := time.ParseInLocation(time.RFC3339Nano, kpiReport.Task.Period.EndTime, time.Local)
|
//et, _ := time.ParseInLocation(time.RFC3339Nano, kpiReport.Task.Period.EndTime, time.Local)
|
||||||
// kpiData.StartTime = goldKpi.StartTime
|
kpiData.StartTime = goldKpi.StartTime
|
||||||
// kpiData.EndTime = goldKpi.EndTime
|
kpiData.EndTime = goldKpi.EndTime
|
||||||
kpiData.StartTime = st
|
|
||||||
kpiData.EndTime = et
|
|
||||||
kpiData.Granularity = goldKpi.Granularity
|
kpiData.Granularity = goldKpi.Granularity
|
||||||
kpiData.NEName = goldKpi.NEName
|
kpiData.NEName = goldKpi.NEName
|
||||||
kpiData.NEType = goldKpi.NEType
|
kpiData.NEType = goldKpi.NEType
|
||||||
@@ -969,9 +1052,9 @@ func PostMeasurementFromNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
layout := time.RFC3339
|
layout := time.RFC3339
|
||||||
measurement.Date = GetDateFromTimeString(layout, measurement.StartTime)
|
measurement.Date = GetDateFromTimeString(layout, measurement.StartTime)
|
||||||
measurement.StartTime = GetDateTimeFromTimeString(layout, measurement.StartTime)
|
measurement.StartTime = GetDateTimeFromTimeString(layout, measurement.StartTime)
|
||||||
affected, err := session.Table("northbound_pm").Insert(measurement)
|
affected, err := session.Table("nbi_pm").Insert(measurement)
|
||||||
if err != nil && affected <= 0 {
|
if err != nil && affected <= 0 {
|
||||||
log.Error("Failed to insert northbound_pm:", err)
|
log.Error("Failed to insert nbi_pm:", err)
|
||||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1052,9 +1135,9 @@ func GetMeasurementFromNF(w http.ResponseWriter, r *http.Request) {
|
|||||||
layout := time.RFC3339
|
layout := time.RFC3339
|
||||||
measurement.Date = GetDateFromTimeString(layout, measurement.StartTime)
|
measurement.Date = GetDateFromTimeString(layout, measurement.StartTime)
|
||||||
measurement.StartTime = GetDateTimeFromTimeString(layout, measurement.StartTime)
|
measurement.StartTime = GetDateTimeFromTimeString(layout, measurement.StartTime)
|
||||||
affected, err := session.Table("northbound_pm").Insert(measurement)
|
affected, err := session.Table("nbi_pm").Insert(measurement)
|
||||||
if err != nil && affected <= 0 {
|
if err != nil && affected <= 0 {
|
||||||
log.Error("Failed to insert northbound_pm:", err)
|
log.Error("Failed to insert nbi_pm:", err)
|
||||||
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
services.ResponseInternalServerError500DatabaseOperationFailed(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,30 +2,16 @@ package security
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"image/color"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/features/security/service"
|
|
||||||
sysConfigService "be.ems/features/sys_config/service"
|
|
||||||
"be.ems/lib/core/account"
|
|
||||||
"be.ems/lib/core/cache"
|
|
||||||
"be.ems/lib/core/constants/cachekey"
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/core/vo/result"
|
|
||||||
"be.ems/lib/dborm"
|
"be.ems/lib/dborm"
|
||||||
"be.ems/lib/global"
|
"be.ems/lib/global"
|
||||||
"be.ems/lib/log"
|
"be.ems/lib/log"
|
||||||
"be.ems/lib/oauth"
|
"be.ems/lib/oauth"
|
||||||
"be.ems/lib/services"
|
"be.ems/lib/services"
|
||||||
"be.ems/restagent/config"
|
"be.ems/restagent/config"
|
||||||
srcConfig "be.ems/src/framework/config"
|
|
||||||
"be.ems/src/framework/redis"
|
|
||||||
"github.com/mojocn/base64Captcha"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -34,22 +20,6 @@ var (
|
|||||||
|
|
||||||
CustomUriOauthToken = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
|
CustomUriOauthToken = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/token"
|
||||||
CustomUriOauthHandshake = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
|
CustomUriOauthHandshake = config.UriPrefix + "/securityManagement/{apiVersion}/{elementTypeValue}/handshake"
|
||||||
|
|
||||||
// 系统登录
|
|
||||||
UriLogin = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/login"
|
|
||||||
CustomUriLogin = config.UriPrefix + "/securityManagement/{apiVersion}/login"
|
|
||||||
|
|
||||||
// 获取验证码
|
|
||||||
UriCaptchaImage = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/captchaImage"
|
|
||||||
CustomUriCaptchaImage = config.UriPrefix + "/securityManagement/{apiVersion}/captchaImage"
|
|
||||||
|
|
||||||
// 登录用户信息
|
|
||||||
UriUserInfo = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/getUserInfo"
|
|
||||||
CustomUriUserInfo = config.UriPrefix + "/securityManagement/{apiVersion}/getUserInfo"
|
|
||||||
|
|
||||||
// 登录用户路由信息
|
|
||||||
UriRouters = config.DefaultUriPrefix + "/securityManagement/{apiVersion}/getRouters"
|
|
||||||
CustomUriRouters = config.UriPrefix + "/securityManagement/{apiVersion}/getRouters"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
|
func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -134,14 +104,8 @@ func LoginFromOMC(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if user != nil {
|
if user != nil {
|
||||||
// 缓存用户信息
|
empty := []string{}
|
||||||
account.CacheLoginUser(user)
|
services.ResponseStatusOK200LoginWhitRP(w, token, user, empty, empty)
|
||||||
redis.SetByExpire("", "session_token", token, time.Second*1800)
|
|
||||||
// 角色权限集合,管理员拥有所有权限
|
|
||||||
userId := fmt.Sprint(user.Id)
|
|
||||||
isAdmin := srcConfig.IsAdmin(userId)
|
|
||||||
roles, perms := service.NewServiceAccount.RoleAndMenuPerms(userId, isAdmin)
|
|
||||||
services.ResponseStatusOK200LoginWhitRP(w, token, user, roles, perms)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
services.ResponseBadRequest400IncorrectLogin(w)
|
services.ResponseBadRequest400IncorrectLogin(w)
|
||||||
@@ -223,189 +187,3 @@ func HandshakeFromOMC(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
services.ResponseStatusOK200Null(w)
|
services.ResponseStatusOK200Null(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 系统登录
|
|
||||||
//
|
|
||||||
// POST /login
|
|
||||||
func LoginOMC(w http.ResponseWriter, r *http.Request) {
|
|
||||||
log.Info("LoginOMC processing... ")
|
|
||||||
var body struct {
|
|
||||||
Username string `json:"username" binding:"required"` // Username 用户名
|
|
||||||
Password string `json:"password" binding:"required"` // Password 用户密码
|
|
||||||
Code string `json:"code"` // Code 验证码
|
|
||||||
UUID string `json:"uuid"` // UUID 验证码唯一标识
|
|
||||||
}
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Invalid Json Format")
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// response 400-5
|
|
||||||
if body.Username == "" || body.Password == "" {
|
|
||||||
log.Error("Wrong parameter value")
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验验证码
|
|
||||||
// 从数据库配置获取验证码开关 true开启,false关闭
|
|
||||||
captchaEnabledStr := sysConfigService.NewServiceSysConfig.SelectConfigValueByKey("sys.account.captchaEnabled")
|
|
||||||
captchaEnabled, err := strconv.ParseBool(captchaEnabledStr)
|
|
||||||
if err != nil {
|
|
||||||
captchaEnabled = false
|
|
||||||
}
|
|
||||||
if captchaEnabled {
|
|
||||||
if body.Code == "" || body.UUID == "" {
|
|
||||||
log.Error("Authentication failed, mismatch captcha")
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "Verification code information error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
verifyKey := cachekey.CAPTCHA_CODE_KEY + body.UUID
|
|
||||||
captcha, ok := cache.GetLocalTTL(verifyKey)
|
|
||||||
if captcha == nil || !ok {
|
|
||||||
log.Error("Authentication failed, captcha emtry")
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "The verification code has expired"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cache.DeleteLocalTTL(verifyKey)
|
|
||||||
if captcha.(string) != body.Code {
|
|
||||||
log.Error("Authentication failed, not match captcha")
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "Verification code error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
validUser, user, err := dborm.XormCheckLoginUser(body.Username, body.Password, config.GetYamlConfig().Auth.Crypt)
|
|
||||||
if !validUser || err != nil {
|
|
||||||
// response 400-4
|
|
||||||
log.Error("Authentication failed, mismatch user or password")
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
token := oauth.GenRandToken("omc") // Generate new token to session ID
|
|
||||||
sourceAddr := r.RemoteAddr[:strings.Index(r.RemoteAddr, ":")]
|
|
||||||
affected, err := dborm.XormInsertSession(body.Username, sourceAddr, token,
|
|
||||||
config.GetExpiresFromConfig(), config.GetYamlConfig().Auth.Session)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Failed to XormInsertSession:", err)
|
|
||||||
if affected == -1 {
|
|
||||||
services.ResponseForbidden403MultiLoginNotAllowed(w)
|
|
||||||
} else {
|
|
||||||
services.ResponseBadRequest400IncorrectLogin(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if user != nil {
|
|
||||||
// 缓存用户信息
|
|
||||||
account.CacheLoginUser(user)
|
|
||||||
redis.SetByExpire("", "session_token", token, time.Second*1800)
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"accessToken": token,
|
|
||||||
}))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取验证码
|
|
||||||
//
|
|
||||||
// GET /captchaImage
|
|
||||||
func CaptchaImage(w http.ResponseWriter, r *http.Request) {
|
|
||||||
configService := sysConfigService.NewServiceSysConfig
|
|
||||||
|
|
||||||
// 从数据库配置获取验证码开关 true开启,false关闭
|
|
||||||
captchaEnabledStr := configService.SelectConfigValueByKey("sys.account.captchaEnabled")
|
|
||||||
captchaEnabled, err := strconv.ParseBool(captchaEnabledStr)
|
|
||||||
if err != nil {
|
|
||||||
captchaEnabled = false
|
|
||||||
}
|
|
||||||
if !captchaEnabled {
|
|
||||||
ctx.JSON(w, 200, result.Ok(map[string]any{
|
|
||||||
"captchaEnabled": captchaEnabled,
|
|
||||||
}))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成唯一标识
|
|
||||||
verifyKey := ""
|
|
||||||
data := map[string]any{
|
|
||||||
"captchaEnabled": captchaEnabled,
|
|
||||||
"uuid": "",
|
|
||||||
"img": "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
|
|
||||||
}
|
|
||||||
|
|
||||||
// char 字符验证
|
|
||||||
driverCaptcha := &base64Captcha.DriverString{
|
|
||||||
//Height png height in pixel.
|
|
||||||
Height: 40,
|
|
||||||
// Width Captcha png width in pixel.
|
|
||||||
Width: 120,
|
|
||||||
//NoiseCount text noise count.
|
|
||||||
NoiseCount: 4,
|
|
||||||
//Length random string length.
|
|
||||||
Length: 4,
|
|
||||||
//Source is a unicode which is the rand string from.
|
|
||||||
Source: "023456789abcdefghjkmnprstuvwxyz",
|
|
||||||
//ShowLineOptions := OptionShowHollowLine | OptionShowSlimeLine | OptionShowSineLine .
|
|
||||||
ShowLineOptions: base64Captcha.OptionShowHollowLine,
|
|
||||||
//BgColor captcha image background color (optional)
|
|
||||||
BgColor: &color.RGBA{
|
|
||||||
R: 250,
|
|
||||||
G: 250,
|
|
||||||
B: 250,
|
|
||||||
A: 255, // 不透明
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// 验证码生成
|
|
||||||
id, question, answer := driverCaptcha.GenerateIdQuestionAnswer()
|
|
||||||
// 验证码表达式解析输出
|
|
||||||
item, err := driverCaptcha.DrawCaptcha(question)
|
|
||||||
if err != nil {
|
|
||||||
log.Infof("Generate Id Question Answer %s : %v", question, err)
|
|
||||||
} else {
|
|
||||||
data["uuid"] = id
|
|
||||||
data["img"] = item.EncodeB64string()
|
|
||||||
verifyKey = cachekey.CAPTCHA_CODE_KEY + id
|
|
||||||
cache.SetLocalTTL(verifyKey, answer, 120*time.Second)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 本地开发下返回验证码结果,方便接口调试
|
|
||||||
// text, ok := cache.GetLocalTTL(verifyKey)
|
|
||||||
// if ok {
|
|
||||||
// data["text"] = text.(string)
|
|
||||||
// }
|
|
||||||
|
|
||||||
ctx.JSON(w, 200, result.Ok(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 登录用户信息
|
|
||||||
func UserInfo(w http.ResponseWriter, r *http.Request) {
|
|
||||||
loginUser, err := ctx.LoginUser(r)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.OkData(err.Error()))
|
|
||||||
}
|
|
||||||
// 角色权限集合,管理员拥有所有权限
|
|
||||||
userId := fmt.Sprint(loginUser.UserID)
|
|
||||||
isAdmin := srcConfig.IsAdmin(userId)
|
|
||||||
roles, perms := service.NewServiceAccount.RoleAndMenuPerms(userId, isAdmin)
|
|
||||||
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"user": loginUser.User,
|
|
||||||
"roles": roles,
|
|
||||||
"permissions": perms,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 登录用户路由信息
|
|
||||||
func Routers(w http.ResponseWriter, r *http.Request) {
|
|
||||||
userID := ctx.LoginUserToUserID(r)
|
|
||||||
|
|
||||||
// 前端路由,管理员拥有所有
|
|
||||||
isAdmin := srcConfig.IsAdmin(userID)
|
|
||||||
buildMenus := service.NewServiceAccount.RouteMenus(userID, isAdmin)
|
|
||||||
ctx.JSON(w, 200, result.OkData(buildMenus))
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
menuService "be.ems/features/sys_menu/service"
|
|
||||||
roleService "be.ems/features/sys_role/service"
|
|
||||||
userService "be.ems/features/sys_user/service"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/core/vo"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 ServiceAccount 结构体
|
|
||||||
var NewServiceAccount = &ServiceAccount{
|
|
||||||
sysUserService: userService.NewServiceSysUser,
|
|
||||||
sysRoleService: roleService.NewServiceSysRole,
|
|
||||||
sysMenuService: menuService.NewServiceSysMenu,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 账号身份操作服务 服务层处理
|
|
||||||
type ServiceAccount struct {
|
|
||||||
// 用户信息服务
|
|
||||||
sysUserService *userService.ServiceSysUser
|
|
||||||
// 角色服务
|
|
||||||
sysRoleService *roleService.ServiceSysRole
|
|
||||||
// 菜单服务
|
|
||||||
sysMenuService *menuService.ServiceSysMenu
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoleAndMenuPerms 角色和菜单数据权限
|
|
||||||
func (s *ServiceAccount) RoleAndMenuPerms(userId string, isAdmin bool) ([]string, []string) {
|
|
||||||
if isAdmin {
|
|
||||||
return []string{"admin"}, []string{"*:*:*"}
|
|
||||||
} else {
|
|
||||||
// 角色key
|
|
||||||
roleGroup := []string{}
|
|
||||||
roles := s.sysRoleService.SelectRoleListByUserId(userId)
|
|
||||||
for _, role := range roles {
|
|
||||||
roleGroup = append(roleGroup, role.RoleKey)
|
|
||||||
}
|
|
||||||
// 菜单权限key
|
|
||||||
perms := s.sysMenuService.SelectMenuPermsByUserId(userId)
|
|
||||||
return parse.RemoveDuplicates(roleGroup), parse.RemoveDuplicates(perms)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RouteMenus 前端路由所需要的菜单
|
|
||||||
func (s *ServiceAccount) RouteMenus(userId string, isAdmin bool) []vo.Router {
|
|
||||||
var buildMenus []vo.Router
|
|
||||||
if isAdmin {
|
|
||||||
menus := s.sysMenuService.SelectMenuTreeByUserId("*")
|
|
||||||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
|
||||||
} else {
|
|
||||||
menus := s.sysMenuService.SelectMenuTreeByUserId(userId)
|
|
||||||
buildMenus = s.sysMenuService.BuildRouteMenus(menus, "")
|
|
||||||
}
|
|
||||||
return buildMenus
|
|
||||||
}
|
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
package sysconfig
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/features/sys_config/model"
|
|
||||||
"be.ems/features/sys_config/service"
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/core/vo/result"
|
|
||||||
"be.ems/lib/midware"
|
|
||||||
"be.ems/lib/services"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 参数配置信息接口添加到路由
|
|
||||||
func Routers() []services.RouterItem {
|
|
||||||
// 实例化控制层 SysConfigApi 结构体
|
|
||||||
var apis = &SysConfigApi{
|
|
||||||
sysConfigService: service.NewServiceSysConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
rs := [...]services.RouterItem{
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/configs",
|
|
||||||
Handler: apis.List,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/config/{configId}",
|
|
||||||
Handler: apis.Info,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "POST",
|
|
||||||
Pattern: "/config",
|
|
||||||
Handler: apis.Add,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "PUT",
|
|
||||||
Pattern: "/config",
|
|
||||||
Handler: apis.Edit,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "DELETE",
|
|
||||||
Pattern: "/config/{configIds}",
|
|
||||||
Handler: apis.Remove,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "PUT",
|
|
||||||
Pattern: "/config/refreshCache",
|
|
||||||
Handler: apis.RefreshCache,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/config/configKey/{configKey}",
|
|
||||||
Handler: apis.ConfigKey,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
// 添加更多的 Router 对象...
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成两组前缀路由
|
|
||||||
rsPrefix := []services.RouterItem{}
|
|
||||||
for _, v := range rs {
|
|
||||||
path := "/configManage/{apiVersion}" + v.Pattern
|
|
||||||
// 固定前缀
|
|
||||||
v.Pattern = config.DefaultUriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
// 可配置
|
|
||||||
v.Pattern = config.UriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
}
|
|
||||||
return rsPrefix
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数配置信息
|
|
||||||
//
|
|
||||||
// PATH /configManage
|
|
||||||
type SysConfigApi struct {
|
|
||||||
// 参数配置服务
|
|
||||||
sysConfigService *service.ServiceSysConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数配置列表
|
|
||||||
//
|
|
||||||
// GET /list
|
|
||||||
func (s *SysConfigApi) List(w http.ResponseWriter, r *http.Request) {
|
|
||||||
querys := ctx.QueryMap(r)
|
|
||||||
data := s.sysConfigService.SelectConfigPage(querys)
|
|
||||||
ctx.JSON(w, 200, result.Ok(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数配置信息
|
|
||||||
//
|
|
||||||
// GET /:configId
|
|
||||||
func (s *SysConfigApi) Info(w http.ResponseWriter, r *http.Request) {
|
|
||||||
configId := ctx.Param(r, "configId")
|
|
||||||
if configId == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data := s.sysConfigService.SelectConfigById(configId)
|
|
||||||
if data.ConfigID == configId {
|
|
||||||
ctx.JSON(w, 200, result.OkData(data))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数配置新增
|
|
||||||
//
|
|
||||||
// POST /
|
|
||||||
func (s *SysConfigApi) Add(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body model.SysConfig
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.ConfigID != "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查属性值唯一
|
|
||||||
uniqueConfigKey := s.sysConfigService.CheckUniqueConfigKey(body.ConfigKey, "")
|
|
||||||
if !uniqueConfigKey {
|
|
||||||
msg := fmt.Sprintf("[%s] Parameter key name already exists", body.ConfigKey)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body.CreateBy = ctx.LoginUserToUserName(r)
|
|
||||||
insertId := s.sysConfigService.InsertConfig(body)
|
|
||||||
if insertId != "" {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数配置修改
|
|
||||||
//
|
|
||||||
// PUT /
|
|
||||||
func (s *SysConfigApi) Edit(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body model.SysConfig
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.ConfigID == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查属性值唯一
|
|
||||||
uniqueConfigKey := s.sysConfigService.CheckUniqueConfigKey(body.ConfigKey, body.ConfigID)
|
|
||||||
if !uniqueConfigKey {
|
|
||||||
msg := fmt.Sprintf("[%s] Parameter key name already exists", body.ConfigKey)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否存在
|
|
||||||
config := s.sysConfigService.SelectConfigById(body.ConfigID)
|
|
||||||
if config.ConfigID != body.ConfigID {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access parameter configuration data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body.UpdateBy = ctx.LoginUserToUserName(r)
|
|
||||||
rows := s.sysConfigService.UpdateConfig(body)
|
|
||||||
if rows > 0 {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数配置删除
|
|
||||||
//
|
|
||||||
// DELETE /:configIds
|
|
||||||
func (s *SysConfigApi) Remove(w http.ResponseWriter, r *http.Request) {
|
|
||||||
configIds := ctx.Param(r, "configIds")
|
|
||||||
if configIds == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 处理字符转id数组后去重
|
|
||||||
ids := strings.Split(configIds, ",")
|
|
||||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
|
||||||
if len(uniqueIDs) <= 0 {
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rows, err := s.sysConfigService.DeleteConfigByIds(uniqueIDs)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
msg := fmt.Sprintf("删除成功:%d", rows)
|
|
||||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数配置刷新缓存
|
|
||||||
//
|
|
||||||
// PUT /refreshCache
|
|
||||||
func (s *SysConfigApi) RefreshCache(w http.ResponseWriter, r *http.Request) {
|
|
||||||
s.sysConfigService.ResetConfigCache()
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数配置根据参数键名
|
|
||||||
//
|
|
||||||
// GET /configKey/:configKey
|
|
||||||
func (s *SysConfigApi) ConfigKey(w http.ResponseWriter, r *http.Request) {
|
|
||||||
configKey := ctx.Param(r, "configKey")
|
|
||||||
if configKey == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
key := s.sysConfigService.SelectConfigValueByKey(configKey)
|
|
||||||
if key != "" {
|
|
||||||
ctx.JSON(w, 200, result.OkData(key))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
// 参数配置对象 sys_config
|
|
||||||
type SysConfig struct {
|
|
||||||
// 参数主键
|
|
||||||
ConfigID string `json:"configId"`
|
|
||||||
// 参数名称
|
|
||||||
ConfigName string `json:"configName" binding:"required"`
|
|
||||||
// 参数键名
|
|
||||||
ConfigKey string `json:"configKey" binding:"required"`
|
|
||||||
// 参数键值
|
|
||||||
ConfigValue string `json:"configValue" binding:"required"`
|
|
||||||
// 系统内置(Y是 N否)
|
|
||||||
ConfigType string `json:"configType"`
|
|
||||||
// 创建者
|
|
||||||
CreateBy string `json:"createBy"`
|
|
||||||
// 创建时间
|
|
||||||
CreateTime int64 `json:"createTime"`
|
|
||||||
// 更新者
|
|
||||||
UpdateBy string `json:"updateBy"`
|
|
||||||
// 更新时间
|
|
||||||
UpdateTime int64 `json:"updateTime"`
|
|
||||||
// 备注
|
|
||||||
Remark string `json:"remark"`
|
|
||||||
}
|
|
||||||
@@ -1,336 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/features/sys_config/model"
|
|
||||||
"be.ems/lib/core/datasource"
|
|
||||||
"be.ems/lib/core/utils/date"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 RepoSysConfig 结构体
|
|
||||||
var NewRepoSysConfig = &RepoSysConfig{
|
|
||||||
selectSql: `select
|
|
||||||
config_id, config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark
|
|
||||||
from sys_config`,
|
|
||||||
|
|
||||||
resultMap: map[string]string{
|
|
||||||
"config_id": "ConfigID",
|
|
||||||
"config_name": "ConfigName",
|
|
||||||
"config_key": "ConfigKey",
|
|
||||||
"config_value": "ConfigValue",
|
|
||||||
"config_type": "ConfigType",
|
|
||||||
"remark": "Remark",
|
|
||||||
"create_by": "CreateBy",
|
|
||||||
"create_time": "CreateTime",
|
|
||||||
"update_by": "UpdateBy",
|
|
||||||
"update_time": "UpdateTime",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepoSysConfig 参数配置表 数据层处理
|
|
||||||
type RepoSysConfig struct {
|
|
||||||
// 查询视图对象SQL
|
|
||||||
selectSql string
|
|
||||||
// 结果字段与实体映射
|
|
||||||
resultMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
|
||||||
func (r *RepoSysConfig) convertResultRows(rows []map[string]any) []model.SysConfig {
|
|
||||||
arr := make([]model.SysConfig, 0)
|
|
||||||
for _, row := range rows {
|
|
||||||
sysConfig := model.SysConfig{}
|
|
||||||
for key, value := range row {
|
|
||||||
if keyMapper, ok := r.resultMap[key]; ok {
|
|
||||||
datasource.SetFieldValue(&sysConfig, keyMapper, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr = append(arr, sysConfig)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictDataPage 分页查询参数配置列表数据
|
|
||||||
func (r *RepoSysConfig) SelectConfigPage(query map[string]any) map[string]any {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if v, ok := query["configName"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "config_name like concat(?, '%')")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["configType"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "config_type = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["configKey"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "config_key like concat(?, '%')")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
beginTime, ok := query["beginTime"]
|
|
||||||
if !ok {
|
|
||||||
beginTime, ok = query["params[beginTime]"]
|
|
||||||
}
|
|
||||||
if ok && beginTime != "" {
|
|
||||||
conditions = append(conditions, "create_time >= ?")
|
|
||||||
beginDate := date.ParseStrToDate(beginTime.(string), date.YYYY_MM_DD)
|
|
||||||
params = append(params, beginDate.UnixMilli())
|
|
||||||
}
|
|
||||||
endTime, ok := query["endTime"]
|
|
||||||
if !ok {
|
|
||||||
endTime, ok = query["params[endTime]"]
|
|
||||||
}
|
|
||||||
if ok && endTime != "" {
|
|
||||||
conditions = append(conditions, "create_time <= ?")
|
|
||||||
endDate := date.ParseStrToDate(endTime.(string), date.YYYY_MM_DD)
|
|
||||||
params = append(params, endDate.UnixMilli())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
totalSql := "select count(1) as 'total' from sys_config"
|
|
||||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("total err => %v", err)
|
|
||||||
}
|
|
||||||
total := parse.Number(totalRows[0]["total"])
|
|
||||||
if total == 0 {
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": []model.SysConfig{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
|
||||||
pageSql := " limit ?,? "
|
|
||||||
params = append(params, pageNum*pageSize)
|
|
||||||
params = append(params, pageSize)
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + pageSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
rows := r.convertResultRows(results)
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": rows,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectConfigList 查询参数配置列表
|
|
||||||
func (r *RepoSysConfig) SelectConfigList(sysConfig model.SysConfig) []model.SysConfig {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysConfig.ConfigName != "" {
|
|
||||||
conditions = append(conditions, "config_name like concat(?, '%')")
|
|
||||||
params = append(params, sysConfig.ConfigName)
|
|
||||||
}
|
|
||||||
if sysConfig.ConfigType != "" {
|
|
||||||
conditions = append(conditions, "config_type = ?")
|
|
||||||
params = append(params, sysConfig.ConfigType)
|
|
||||||
}
|
|
||||||
if sysConfig.ConfigKey != "" {
|
|
||||||
conditions = append(conditions, "config_key like concat(?, '%')")
|
|
||||||
params = append(params, sysConfig.ConfigKey)
|
|
||||||
}
|
|
||||||
if sysConfig.CreateTime > 0 {
|
|
||||||
conditions = append(conditions, "create_time >= ?")
|
|
||||||
params = append(params, sysConfig.CreateTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysConfig{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectConfigValueByKey 通过参数键名查询参数键值
|
|
||||||
func (r *RepoSysConfig) SelectConfigValueByKey(configKey string) string {
|
|
||||||
querySql := "select config_value as 'str' from sys_config where config_key = ?"
|
|
||||||
results, err := datasource.RawDB("", querySql, []any{configKey})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return fmt.Sprint(results[0]["str"])
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectConfigByIds 通过配置ID查询参数配置信息
|
|
||||||
func (r *RepoSysConfig) SelectConfigByIds(configIds []string) []model.SysConfig {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(configIds))
|
|
||||||
querySql := r.selectSql + " where config_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(configIds)
|
|
||||||
results, err := datasource.RawDB("", querySql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysConfig{}
|
|
||||||
}
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueConfig 校验配置参数是否唯一
|
|
||||||
func (r *RepoSysConfig) CheckUniqueConfig(sysConfig model.SysConfig) string {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysConfig.ConfigKey != "" {
|
|
||||||
conditions = append(conditions, "config_key = ?")
|
|
||||||
params = append(params, sysConfig.ConfigKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
} else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := "select config_id as 'str' from sys_config " + whereSql + " limit 1"
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err %v", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return fmt.Sprint(results[0]["str"])
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertConfig 新增参数配置
|
|
||||||
func (r *RepoSysConfig) InsertConfig(sysConfig model.SysConfig) string {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysConfig.ConfigName != "" {
|
|
||||||
params["config_name"] = sysConfig.ConfigName
|
|
||||||
}
|
|
||||||
if sysConfig.ConfigKey != "" {
|
|
||||||
params["config_key"] = sysConfig.ConfigKey
|
|
||||||
}
|
|
||||||
if sysConfig.ConfigValue != "" {
|
|
||||||
params["config_value"] = sysConfig.ConfigValue
|
|
||||||
}
|
|
||||||
if sysConfig.ConfigType != "" {
|
|
||||||
params["config_type"] = sysConfig.ConfigType
|
|
||||||
}
|
|
||||||
if sysConfig.Remark != "" {
|
|
||||||
params["remark"] = sysConfig.Remark
|
|
||||||
}
|
|
||||||
if sysConfig.CreateBy != "" {
|
|
||||||
params["create_by"] = sysConfig.CreateBy
|
|
||||||
params["create_time"] = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
|
||||||
sql := "insert into sys_config (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
|
||||||
|
|
||||||
// 执行插入
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
insertId, err := results.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return fmt.Sprint(insertId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateConfig 修改参数配置
|
|
||||||
func (r *RepoSysConfig) UpdateConfig(sysConfig model.SysConfig) int64 {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysConfig.ConfigName != "" {
|
|
||||||
params["config_name"] = sysConfig.ConfigName
|
|
||||||
}
|
|
||||||
if sysConfig.ConfigKey != "" {
|
|
||||||
params["config_key"] = sysConfig.ConfigKey
|
|
||||||
}
|
|
||||||
if sysConfig.ConfigValue != "" {
|
|
||||||
params["config_value"] = sysConfig.ConfigValue
|
|
||||||
}
|
|
||||||
if sysConfig.ConfigType != "" {
|
|
||||||
params["config_type"] = sysConfig.ConfigType
|
|
||||||
}
|
|
||||||
if sysConfig.Remark != "" {
|
|
||||||
params["remark"] = sysConfig.Remark
|
|
||||||
}
|
|
||||||
if sysConfig.UpdateBy != "" {
|
|
||||||
params["update_by"] = sysConfig.UpdateBy
|
|
||||||
params["update_time"] = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, values := datasource.KeyValueByUpdate(params)
|
|
||||||
sql := "update sys_config set " + strings.Join(keys, ",") + " where config_id = ?"
|
|
||||||
|
|
||||||
// 执行更新
|
|
||||||
values = append(values, sysConfig.ConfigID)
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update row : %v", err.Error())
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteConfigByIds 批量删除参数配置信息
|
|
||||||
func (r *RepoSysConfig) DeleteConfigByIds(configIds []string) int64 {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(configIds))
|
|
||||||
sql := "delete from sys_config where config_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(configIds)
|
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"be.ems/features/sys_config/model"
|
|
||||||
"be.ems/lib/core/cache"
|
|
||||||
"be.ems/lib/core/constants/cachekey"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 ServiceSysConfig 结构体
|
|
||||||
var NewServiceSysConfig = &ServiceSysConfig{
|
|
||||||
sysConfigRepository: NewRepoSysConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceSysConfig 参数配置 服务层处理
|
|
||||||
type ServiceSysConfig struct {
|
|
||||||
// 参数配置表
|
|
||||||
sysConfigRepository *RepoSysConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictDataPage 分页查询参数配置列表数据
|
|
||||||
func (r *ServiceSysConfig) SelectConfigPage(query map[string]any) map[string]any {
|
|
||||||
return r.sysConfigRepository.SelectConfigPage(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectConfigList 查询参数配置列表
|
|
||||||
func (r *ServiceSysConfig) SelectConfigList(sysConfig model.SysConfig) []model.SysConfig {
|
|
||||||
return r.sysConfigRepository.SelectConfigList(sysConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectConfigValueByKey 通过参数键名查询参数键值
|
|
||||||
func (r *ServiceSysConfig) SelectConfigValueByKey(configKey string) string {
|
|
||||||
cacheKey := r.getCacheKey(configKey)
|
|
||||||
// 从缓存中读取
|
|
||||||
cacheValue, ok := cache.GetLocal(cacheKey)
|
|
||||||
if cacheValue != nil && ok {
|
|
||||||
return cacheValue.(string)
|
|
||||||
}
|
|
||||||
// 无缓存时读取数据放入缓存中
|
|
||||||
configValue := r.sysConfigRepository.SelectConfigValueByKey(configKey)
|
|
||||||
if configValue != "" {
|
|
||||||
cache.SetLocal(cacheKey, configValue)
|
|
||||||
return configValue
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectConfigById 通过配置ID查询参数配置信息
|
|
||||||
func (r *ServiceSysConfig) SelectConfigById(configId string) model.SysConfig {
|
|
||||||
if configId == "" {
|
|
||||||
return model.SysConfig{}
|
|
||||||
}
|
|
||||||
configs := r.sysConfigRepository.SelectConfigByIds([]string{configId})
|
|
||||||
if len(configs) > 0 {
|
|
||||||
return configs[0]
|
|
||||||
}
|
|
||||||
return model.SysConfig{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueConfigKey 校验参数键名是否唯一
|
|
||||||
func (r *ServiceSysConfig) CheckUniqueConfigKey(configKey, configId string) bool {
|
|
||||||
uniqueId := r.sysConfigRepository.CheckUniqueConfig(model.SysConfig{
|
|
||||||
ConfigKey: configKey,
|
|
||||||
})
|
|
||||||
if uniqueId == configId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertConfig 新增参数配置
|
|
||||||
func (r *ServiceSysConfig) InsertConfig(sysConfig model.SysConfig) string {
|
|
||||||
configId := r.sysConfigRepository.InsertConfig(sysConfig)
|
|
||||||
if configId != "" {
|
|
||||||
r.loadingConfigCache(sysConfig.ConfigKey)
|
|
||||||
}
|
|
||||||
return configId
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateConfig 修改参数配置
|
|
||||||
func (r *ServiceSysConfig) UpdateConfig(sysConfig model.SysConfig) int64 {
|
|
||||||
rows := r.sysConfigRepository.UpdateConfig(sysConfig)
|
|
||||||
if rows > 0 {
|
|
||||||
r.loadingConfigCache(sysConfig.ConfigKey)
|
|
||||||
}
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteConfigByIds 批量删除参数配置信息
|
|
||||||
func (r *ServiceSysConfig) DeleteConfigByIds(configIds []string) (int64, error) {
|
|
||||||
// 检查是否存在
|
|
||||||
configs := r.sysConfigRepository.SelectConfigByIds(configIds)
|
|
||||||
if len(configs) <= 0 {
|
|
||||||
return 0, errors.New("does not have permission to access parameter configuration data")
|
|
||||||
}
|
|
||||||
for _, config := range configs {
|
|
||||||
// 检查是否为内置参数
|
|
||||||
if config.ConfigType == "Y" {
|
|
||||||
return 0, errors.New(config.ConfigID + " Configuration parameters are built-in parameters and their deletion is prohibited!")
|
|
||||||
}
|
|
||||||
// 清除缓存
|
|
||||||
r.clearConfigCache(config.ConfigKey)
|
|
||||||
}
|
|
||||||
if len(configs) == len(configIds) {
|
|
||||||
rows := r.sysConfigRepository.DeleteConfigByIds(configIds)
|
|
||||||
return rows, nil
|
|
||||||
}
|
|
||||||
return 0, errors.New("failed to delete parameter configuration information")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResetConfigCache 重置参数缓存数据
|
|
||||||
func (r *ServiceSysConfig) ResetConfigCache() {
|
|
||||||
r.clearConfigCache("*")
|
|
||||||
r.loadingConfigCache("*")
|
|
||||||
}
|
|
||||||
|
|
||||||
// getCacheKey 组装缓存key
|
|
||||||
func (r *ServiceSysConfig) getCacheKey(configKey string) string {
|
|
||||||
return cachekey.SYS_CONFIG_KEY + configKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// loadingConfigCache 加载参数缓存数据
|
|
||||||
func (r *ServiceSysConfig) loadingConfigCache(configKey string) {
|
|
||||||
// 查询全部参数
|
|
||||||
if configKey == "*" {
|
|
||||||
sysConfigs := r.SelectConfigList(model.SysConfig{})
|
|
||||||
for _, v := range sysConfigs {
|
|
||||||
key := r.getCacheKey(v.ConfigKey)
|
|
||||||
cache.DeleteLocal(key)
|
|
||||||
cache.SetLocal(key, v.ConfigValue)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 指定参数
|
|
||||||
if configKey != "" {
|
|
||||||
cacheValue := r.sysConfigRepository.SelectConfigValueByKey(configKey)
|
|
||||||
if cacheValue != "" {
|
|
||||||
key := r.getCacheKey(configKey)
|
|
||||||
cache.DeleteLocal(key)
|
|
||||||
cache.SetLocal(key, cacheValue)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// clearConfigCache 清空参数缓存数据
|
|
||||||
func (r *ServiceSysConfig) clearConfigCache(configKey string) bool {
|
|
||||||
key := r.getCacheKey(configKey)
|
|
||||||
keys := cache.GetLocalKeys(key)
|
|
||||||
for _, v := range keys {
|
|
||||||
cache.DeleteLocal(v)
|
|
||||||
}
|
|
||||||
return len(keys) > 0
|
|
||||||
}
|
|
||||||
@@ -1,247 +0,0 @@
|
|||||||
package sysdictdata
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/features/sys_dict_data/model"
|
|
||||||
sysDictDataService "be.ems/features/sys_dict_data/service"
|
|
||||||
sysDictTypeService "be.ems/features/sys_dict_type/service"
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/core/vo/result"
|
|
||||||
"be.ems/lib/midware"
|
|
||||||
"be.ems/lib/services"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 字典类型对应的字典数据信息接口添加到路由
|
|
||||||
func Routers() []services.RouterItem {
|
|
||||||
// 实例化控制层 SysDictDataApi 结构体
|
|
||||||
var apis = &SysDictDataApi{
|
|
||||||
sysDictDataService: sysDictDataService.NewServiceSysDictData,
|
|
||||||
sysDictTypeService: sysDictTypeService.NewServiceSysDictType,
|
|
||||||
}
|
|
||||||
|
|
||||||
rs := [...]services.RouterItem{
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/dictDatas",
|
|
||||||
Handler: apis.List,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/dictData/{dictCode}",
|
|
||||||
Handler: apis.Info,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "POST",
|
|
||||||
Pattern: "/dictData",
|
|
||||||
Handler: apis.Add,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "PUT",
|
|
||||||
Pattern: "/dictData",
|
|
||||||
Handler: apis.Edit,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "DELETE",
|
|
||||||
Pattern: "/dictData/{dictCodes}",
|
|
||||||
Handler: apis.Remove,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/dictData/type/{dictType}",
|
|
||||||
Handler: apis.DictType,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
// 添加更多的 Router 对象...
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成两组前缀路由
|
|
||||||
rsPrefix := []services.RouterItem{}
|
|
||||||
for _, v := range rs {
|
|
||||||
path := "/dictDataManage/{apiVersion}" + v.Pattern
|
|
||||||
// 固定前缀
|
|
||||||
v.Pattern = config.DefaultUriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
// 可配置
|
|
||||||
v.Pattern = config.UriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
}
|
|
||||||
return rsPrefix
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型对应的字典数据信息
|
|
||||||
//
|
|
||||||
// PATH /dictDataManage
|
|
||||||
type SysDictDataApi struct {
|
|
||||||
// 字典数据服务
|
|
||||||
sysDictDataService *sysDictDataService.ServiceSysDictData
|
|
||||||
// 字典类型服务
|
|
||||||
sysDictTypeService *sysDictTypeService.ServiceSysDictType
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典数据列表
|
|
||||||
//
|
|
||||||
// GET /list
|
|
||||||
func (s *SysDictDataApi) List(w http.ResponseWriter, r *http.Request) {
|
|
||||||
querys := ctx.QueryMap(r)
|
|
||||||
data := s.sysDictDataService.SelectDictDataPage(querys)
|
|
||||||
ctx.JSON(w, 200, result.Ok(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典数据详情
|
|
||||||
//
|
|
||||||
// GET /:dictCode
|
|
||||||
func (s *SysDictDataApi) Info(w http.ResponseWriter, r *http.Request) {
|
|
||||||
dictCode := ctx.Param(r, "dictCode")
|
|
||||||
if dictCode == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data := s.sysDictDataService.SelectDictDataByCode(dictCode)
|
|
||||||
if data.DictCode == dictCode {
|
|
||||||
ctx.JSON(w, 200, result.OkData(data))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典数据新增
|
|
||||||
//
|
|
||||||
// POST /
|
|
||||||
func (s *SysDictDataApi) Add(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body model.SysDictData
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.DictCode != "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典类型是否存在
|
|
||||||
sysDictType := s.sysDictTypeService.SelectDictTypeByType(body.DictType)
|
|
||||||
if sysDictType.DictType != body.DictType {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary type data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典标签唯一
|
|
||||||
uniqueDictLabel := s.sysDictDataService.CheckUniqueDictLabel(body.DictType, body.DictLabel, "")
|
|
||||||
if !uniqueDictLabel {
|
|
||||||
msg := fmt.Sprintf("[%s] The subscript signature of this dictionary type already exists", body.DictLabel)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典键值唯一
|
|
||||||
uniqueDictValue := s.sysDictDataService.CheckUniqueDictValue(body.DictType, body.DictValue, "")
|
|
||||||
if !uniqueDictValue {
|
|
||||||
msg := fmt.Sprintf("[%s] The label value under this dictionary type already exists", body.DictValue)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body.CreateBy = ctx.LoginUserToUserName(r)
|
|
||||||
insertId := s.sysDictDataService.InsertDictData(body)
|
|
||||||
if insertId != "" {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型修改
|
|
||||||
//
|
|
||||||
// PUT /
|
|
||||||
func (s *SysDictDataApi) Edit(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body model.SysDictData
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.DictCode == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典类型是否存在
|
|
||||||
sysDictType := s.sysDictTypeService.SelectDictTypeByType(body.DictType)
|
|
||||||
if sysDictType.DictType != body.DictType {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary type data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典编码是否存在
|
|
||||||
SysDictDataApi := s.sysDictDataService.SelectDictDataByCode(body.DictCode)
|
|
||||||
if SysDictDataApi.DictCode != body.DictCode {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary encoding data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典标签唯一
|
|
||||||
uniqueDictLabel := s.sysDictDataService.CheckUniqueDictLabel(body.DictType, body.DictLabel, body.DictCode)
|
|
||||||
if !uniqueDictLabel {
|
|
||||||
msg := fmt.Sprintf("Data modification failed for [%s], the dictionary type subscript signature already exists", body.DictLabel)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典键值唯一
|
|
||||||
uniqueDictValue := s.sysDictDataService.CheckUniqueDictValue(body.DictType, body.DictValue, body.DictCode)
|
|
||||||
if !uniqueDictValue {
|
|
||||||
msg := fmt.Sprintf("Data modification failed for [%s], label value already exists under this dictionary type", body.DictValue)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body.UpdateBy = ctx.LoginUserToUserName(r)
|
|
||||||
rows := s.sysDictDataService.UpdateDictData(body)
|
|
||||||
if rows > 0 {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典数据删除
|
|
||||||
//
|
|
||||||
// DELETE /:dictCodes
|
|
||||||
func (s *SysDictDataApi) Remove(w http.ResponseWriter, r *http.Request) {
|
|
||||||
dictCodes := ctx.Param(r, "dictCodes")
|
|
||||||
if dictCodes == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 处理字符转id数组后去重
|
|
||||||
ids := strings.Split(dictCodes, ",")
|
|
||||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
|
||||||
if len(uniqueIDs) <= 0 {
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rows, err := s.sysDictDataService.DeleteDictDataByCodes(uniqueIDs)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
msg := fmt.Sprintf("Successfully deleted: %d", rows)
|
|
||||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典数据列表(指定字典类型)
|
|
||||||
//
|
|
||||||
// GET /type/:dictType
|
|
||||||
func (s *SysDictDataApi) DictType(w http.ResponseWriter, r *http.Request) {
|
|
||||||
dictType := ctx.Param(r, "dictType")
|
|
||||||
if dictType == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
data := s.sysDictDataService.SelectDictDataByType(dictType)
|
|
||||||
ctx.JSON(w, 200, result.OkData(data))
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
// SysDictData 字典数据对象 sys_dict_data
|
|
||||||
type SysDictData struct {
|
|
||||||
// 字典编码
|
|
||||||
DictCode string `json:"dictCode"`
|
|
||||||
// 字典排序
|
|
||||||
DictSort int `json:"dictSort"`
|
|
||||||
// 字典标签
|
|
||||||
DictLabel string `json:"dictLabel" binding:"required"`
|
|
||||||
// 字典键值
|
|
||||||
DictValue string `json:"dictValue" binding:"required"`
|
|
||||||
// 字典类型
|
|
||||||
DictType string `json:"dictType" binding:"required"`
|
|
||||||
// 样式属性(样式扩展)
|
|
||||||
TagClass string `json:"tagClass"`
|
|
||||||
// 标签类型(预设颜色)
|
|
||||||
TagType string `json:"tagType"`
|
|
||||||
// 状态(0停用 1正常)
|
|
||||||
Status string `json:"status"`
|
|
||||||
// 创建者
|
|
||||||
CreateBy string `json:"createBy"`
|
|
||||||
// 创建时间
|
|
||||||
CreateTime int64 `json:"createTime"`
|
|
||||||
// 更新者
|
|
||||||
UpdateBy string `json:"updateBy"`
|
|
||||||
// 更新时间
|
|
||||||
UpdateTime int64 `json:"updateTime"`
|
|
||||||
// 备注
|
|
||||||
Remark string `json:"remark"`
|
|
||||||
}
|
|
||||||
@@ -1,369 +0,0 @@
|
|||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/features/sys_dict_data/model"
|
|
||||||
"be.ems/lib/core/datasource"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 RepoSysDictData 结构体
|
|
||||||
var NewRepoSysDictData = &RepoSysDictData{
|
|
||||||
selectSql: `select
|
|
||||||
dict_code, dict_sort, dict_label, dict_value, dict_type, tag_class, tag_type, status, create_by, create_time, remark
|
|
||||||
from sys_dict_data`,
|
|
||||||
|
|
||||||
resultMap: map[string]string{
|
|
||||||
"dict_code": "DictCode",
|
|
||||||
"dict_sort": "DictSort",
|
|
||||||
"dict_label": "DictLabel",
|
|
||||||
"dict_value": "DictValue",
|
|
||||||
"dict_type": "DictType",
|
|
||||||
"tag_class": "TagClass",
|
|
||||||
"tag_type": "TagType",
|
|
||||||
"status": "Status",
|
|
||||||
"remark": "Remark",
|
|
||||||
"create_by": "CreateBy",
|
|
||||||
"create_time": "CreateTime",
|
|
||||||
"update_by": "UpdateBy",
|
|
||||||
"update_time": "UpdateTime",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepoSysDictData 字典类型数据表 数据层处理
|
|
||||||
type RepoSysDictData struct {
|
|
||||||
// 查询视图对象SQL
|
|
||||||
selectSql string
|
|
||||||
// 结果字段与实体映射
|
|
||||||
resultMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
|
||||||
func (r *RepoSysDictData) convertResultRows(rows []map[string]any) []model.SysDictData {
|
|
||||||
arr := make([]model.SysDictData, 0)
|
|
||||||
for _, row := range rows {
|
|
||||||
sysDictData := model.SysDictData{}
|
|
||||||
for key, value := range row {
|
|
||||||
if keyMapper, ok := r.resultMap[key]; ok {
|
|
||||||
datasource.SetFieldValue(&sysDictData, keyMapper, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr = append(arr, sysDictData)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictDataPage 根据条件分页查询字典数据
|
|
||||||
func (r *RepoSysDictData) SelectDictDataPage(query map[string]any) map[string]any {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if v, ok := query["dictType"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "dict_type = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["dictLabel"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "dict_label like concat(?, '%')")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["status"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "status = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
totalSql := "select count(1) as 'total' from sys_dict_data"
|
|
||||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("total err => %v", err)
|
|
||||||
}
|
|
||||||
total := parse.Number(totalRows[0]["total"])
|
|
||||||
if total == 0 {
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": []model.SysDictData{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
|
||||||
pageSql := " order by dict_sort asc limit ?,? "
|
|
||||||
params = append(params, pageNum*pageSize)
|
|
||||||
params = append(params, pageSize)
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + pageSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
rows := r.convertResultRows(results)
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": rows,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictDataList 根据条件查询字典数据
|
|
||||||
func (r *RepoSysDictData) SelectDictDataList(sysDictData model.SysDictData) []model.SysDictData {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysDictData.DictLabel != "" {
|
|
||||||
conditions = append(conditions, "dict_label like concat(?, '%')")
|
|
||||||
params = append(params, sysDictData.DictLabel)
|
|
||||||
}
|
|
||||||
if sysDictData.DictType != "" {
|
|
||||||
conditions = append(conditions, "dict_type = ?")
|
|
||||||
params = append(params, sysDictData.DictType)
|
|
||||||
}
|
|
||||||
if sysDictData.Status != "" {
|
|
||||||
conditions = append(conditions, "status = ?")
|
|
||||||
params = append(params, sysDictData.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
orderSql := " order by dict_sort asc "
|
|
||||||
querySql := r.selectSql + whereSql + orderSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysDictData{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictDataByCodes 根据字典数据编码查询信息
|
|
||||||
func (r *RepoSysDictData) SelectDictDataByCodes(dictCodes []string) []model.SysDictData {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(dictCodes))
|
|
||||||
querySql := r.selectSql + " where dict_code in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(dictCodes)
|
|
||||||
results, err := datasource.RawDB("", querySql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysDictData{}
|
|
||||||
}
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CountDictDataByType 查询字典数据
|
|
||||||
func (r *RepoSysDictData) CountDictDataByType(dictType string) int64 {
|
|
||||||
querySql := "select count(1) as 'total' from sys_dict_data where dict_type = ?"
|
|
||||||
results, err := datasource.RawDB("", querySql, []any{dictType})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return parse.Number(results[0]["total"])
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueDictData 校验字典数据是否唯一
|
|
||||||
func (r *RepoSysDictData) CheckUniqueDictData(sysDictData model.SysDictData) string {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysDictData.DictType != "" {
|
|
||||||
conditions = append(conditions, "dict_type = ?")
|
|
||||||
params = append(params, sysDictData.DictType)
|
|
||||||
}
|
|
||||||
if sysDictData.DictLabel != "" {
|
|
||||||
conditions = append(conditions, "dict_label = ?")
|
|
||||||
params = append(params, sysDictData.DictLabel)
|
|
||||||
}
|
|
||||||
if sysDictData.DictValue != "" {
|
|
||||||
conditions = append(conditions, "dict_value = ?")
|
|
||||||
params = append(params, sysDictData.DictValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
} else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := "select dict_code as 'str' from sys_dict_data " + whereSql + " limit 1"
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err %v", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return fmt.Sprint(results[0]["str"])
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteDictDataByCodes 批量删除字典数据信息
|
|
||||||
func (r *RepoSysDictData) DeleteDictDataByCodes(dictCodes []string) int64 {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(dictCodes))
|
|
||||||
sql := "delete from sys_dict_data where dict_code in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(dictCodes)
|
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertDictData 新增字典数据信息
|
|
||||||
func (r *RepoSysDictData) InsertDictData(sysDictData model.SysDictData) string {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysDictData.DictSort > 0 {
|
|
||||||
params["dict_sort"] = sysDictData.DictSort
|
|
||||||
}
|
|
||||||
if sysDictData.DictLabel != "" {
|
|
||||||
params["dict_label"] = sysDictData.DictLabel
|
|
||||||
}
|
|
||||||
if sysDictData.DictValue != "" {
|
|
||||||
params["dict_value"] = sysDictData.DictValue
|
|
||||||
}
|
|
||||||
if sysDictData.DictType != "" {
|
|
||||||
params["dict_type"] = sysDictData.DictType
|
|
||||||
}
|
|
||||||
if sysDictData.TagClass != "" {
|
|
||||||
params["tag_class"] = sysDictData.TagClass
|
|
||||||
}
|
|
||||||
if sysDictData.TagType != "" {
|
|
||||||
params["tag_type"] = sysDictData.TagType
|
|
||||||
}
|
|
||||||
if sysDictData.Status != "" {
|
|
||||||
params["status"] = sysDictData.Status
|
|
||||||
}
|
|
||||||
if sysDictData.Remark != "" {
|
|
||||||
params["remark"] = sysDictData.Remark
|
|
||||||
}
|
|
||||||
if sysDictData.CreateBy != "" {
|
|
||||||
params["create_by"] = sysDictData.CreateBy
|
|
||||||
params["create_time"] = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
|
||||||
sql := "insert into sys_dict_data (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
|
||||||
|
|
||||||
// 执行插入
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
insertId, err := results.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return fmt.Sprint(insertId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateDictData 修改字典数据信息
|
|
||||||
func (r *RepoSysDictData) UpdateDictData(sysDictData model.SysDictData) int64 {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysDictData.DictSort > 0 {
|
|
||||||
params["dict_sort"] = sysDictData.DictSort
|
|
||||||
}
|
|
||||||
if sysDictData.DictLabel != "" {
|
|
||||||
params["dict_label"] = sysDictData.DictLabel
|
|
||||||
}
|
|
||||||
if sysDictData.DictValue != "" {
|
|
||||||
params["dict_value"] = sysDictData.DictValue
|
|
||||||
}
|
|
||||||
if sysDictData.DictType != "" {
|
|
||||||
params["dict_type"] = sysDictData.DictType
|
|
||||||
}
|
|
||||||
if sysDictData.TagClass != "" {
|
|
||||||
params["tag_class"] = sysDictData.TagClass
|
|
||||||
}
|
|
||||||
if sysDictData.TagType != "" {
|
|
||||||
params["tag_type"] = sysDictData.TagType
|
|
||||||
}
|
|
||||||
if sysDictData.Status != "" {
|
|
||||||
params["status"] = sysDictData.Status
|
|
||||||
}
|
|
||||||
if sysDictData.Remark != "" {
|
|
||||||
params["remark"] = sysDictData.Remark
|
|
||||||
}
|
|
||||||
if sysDictData.UpdateBy != "" {
|
|
||||||
params["update_by"] = sysDictData.UpdateBy
|
|
||||||
params["update_time"] = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, values := datasource.KeyValueByUpdate(params)
|
|
||||||
sql := "update sys_dict_data set " + strings.Join(keys, ",") + " where dict_code = ?"
|
|
||||||
|
|
||||||
// 执行更新
|
|
||||||
values = append(values, sysDictData.DictCode)
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update row : %v", err.Error())
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateDictDataType 同步修改字典类型
|
|
||||||
func (r *RepoSysDictData) UpdateDictDataType(oldDictType string, newDictType string) int64 {
|
|
||||||
// 参数拼接
|
|
||||||
params := make([]any, 0)
|
|
||||||
if oldDictType == "" || newDictType == "" {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
params = append(params, newDictType)
|
|
||||||
params = append(params, oldDictType)
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
sql := "update sys_dict_data set dict_type = ? where dict_type = ?"
|
|
||||||
|
|
||||||
// 执行更新
|
|
||||||
results, err := datasource.ExecDB("", sql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update row : %v", err.Error())
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"be.ems/features/sys_dict_data/model"
|
|
||||||
"be.ems/features/sys_dict_data/repo"
|
|
||||||
sysDictTypeService "be.ems/features/sys_dict_type/service"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 ServiceSysDictData 结构体
|
|
||||||
var NewServiceSysDictData = &ServiceSysDictData{
|
|
||||||
sysDictDataRepository: *repo.NewRepoSysDictData,
|
|
||||||
sysDictTypeService: *sysDictTypeService.NewServiceSysDictType,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceSysDictData 字典类型数据 服务层处理
|
|
||||||
type ServiceSysDictData struct {
|
|
||||||
// 字典数据服务
|
|
||||||
sysDictDataRepository repo.RepoSysDictData
|
|
||||||
// 字典类型服务
|
|
||||||
sysDictTypeService sysDictTypeService.ServiceSysDictType
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictDataPage 根据条件分页查询字典数据
|
|
||||||
func (r *ServiceSysDictData) SelectDictDataPage(query map[string]any) map[string]any {
|
|
||||||
return r.sysDictDataRepository.SelectDictDataPage(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictDataList 根据条件查询字典数据
|
|
||||||
func (r *ServiceSysDictData) SelectDictDataList(sysDictData model.SysDictData) []model.SysDictData {
|
|
||||||
return r.sysDictDataRepository.SelectDictDataList(sysDictData)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictDataByCode 根据字典数据编码查询信息
|
|
||||||
func (r *ServiceSysDictData) SelectDictDataByCode(dictCode string) model.SysDictData {
|
|
||||||
if dictCode == "" {
|
|
||||||
return model.SysDictData{}
|
|
||||||
}
|
|
||||||
dictCodes := r.sysDictDataRepository.SelectDictDataByCodes([]string{dictCode})
|
|
||||||
if len(dictCodes) > 0 {
|
|
||||||
return dictCodes[0]
|
|
||||||
}
|
|
||||||
return model.SysDictData{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictDataByType 根据字典类型查询信息
|
|
||||||
func (r *ServiceSysDictData) SelectDictDataByType(dictType string) []model.SysDictData {
|
|
||||||
return r.sysDictTypeService.DictDataCache(dictType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueDictLabel 校验字典标签是否唯一
|
|
||||||
func (r *ServiceSysDictData) CheckUniqueDictLabel(dictType, dictLabel, dictCode string) bool {
|
|
||||||
uniqueId := r.sysDictDataRepository.CheckUniqueDictData(model.SysDictData{
|
|
||||||
DictType: dictType,
|
|
||||||
DictLabel: dictLabel,
|
|
||||||
})
|
|
||||||
if uniqueId == dictCode {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueDictValue 校验字典键值是否唯一
|
|
||||||
func (r *ServiceSysDictData) CheckUniqueDictValue(dictType, dictValue, dictCode string) bool {
|
|
||||||
uniqueId := r.sysDictDataRepository.CheckUniqueDictData(model.SysDictData{
|
|
||||||
DictType: dictType,
|
|
||||||
DictValue: dictValue,
|
|
||||||
})
|
|
||||||
if uniqueId == dictCode {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteDictDataByCodes 批量删除字典数据信息
|
|
||||||
func (r *ServiceSysDictData) DeleteDictDataByCodes(dictCodes []string) (int64, error) {
|
|
||||||
// 检查是否存在
|
|
||||||
dictDatas := r.sysDictDataRepository.SelectDictDataByCodes(dictCodes)
|
|
||||||
if len(dictDatas) <= 0 {
|
|
||||||
return 0, errors.New("does not have permission to access dictionary-encoded data")
|
|
||||||
}
|
|
||||||
if len(dictDatas) == len(dictCodes) {
|
|
||||||
for _, v := range dictDatas {
|
|
||||||
// 刷新缓存
|
|
||||||
r.sysDictTypeService.ClearDictCache(v.DictType)
|
|
||||||
r.sysDictTypeService.LoadingDictCache(v.DictType)
|
|
||||||
}
|
|
||||||
rows := r.sysDictDataRepository.DeleteDictDataByCodes(dictCodes)
|
|
||||||
return rows, nil
|
|
||||||
}
|
|
||||||
return 0, errors.New("failed to delete dictionary data information")
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertDictData 新增字典数据信息
|
|
||||||
func (r *ServiceSysDictData) InsertDictData(sysDictData model.SysDictData) string {
|
|
||||||
insertId := r.sysDictDataRepository.InsertDictData(sysDictData)
|
|
||||||
if insertId != "" {
|
|
||||||
r.sysDictTypeService.LoadingDictCache(sysDictData.DictType)
|
|
||||||
}
|
|
||||||
return insertId
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateDictData 修改字典数据信息
|
|
||||||
func (r *ServiceSysDictData) UpdateDictData(sysDictData model.SysDictData) int64 {
|
|
||||||
rows := r.sysDictDataRepository.UpdateDictData(sysDictData)
|
|
||||||
if rows > 0 {
|
|
||||||
r.sysDictTypeService.LoadingDictCache(sysDictData.DictType)
|
|
||||||
}
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
@@ -1,253 +0,0 @@
|
|||||||
package sysdicttype
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/features/sys_dict_type/model"
|
|
||||||
sysDictTypeService "be.ems/features/sys_dict_type/service"
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/core/vo/result"
|
|
||||||
"be.ems/lib/midware"
|
|
||||||
"be.ems/lib/services"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 字典类型信息接口添加到路由
|
|
||||||
func Routers() []services.RouterItem {
|
|
||||||
// 实例化控制层 SysDictTypeApi 结构体
|
|
||||||
var apis = &SysDictTypeApi{
|
|
||||||
sysDictTypeService: *sysDictTypeService.NewServiceSysDictType,
|
|
||||||
}
|
|
||||||
|
|
||||||
rs := [...]services.RouterItem{
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/dictTypes",
|
|
||||||
Handler: apis.List,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/dictType/{dictId}",
|
|
||||||
Handler: apis.Info,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "POST",
|
|
||||||
Pattern: "/dictType",
|
|
||||||
Handler: apis.Add,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "PUT",
|
|
||||||
Pattern: "/dictType",
|
|
||||||
Handler: apis.Edit,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "DELETE",
|
|
||||||
Pattern: "/dictType/{dictIds}",
|
|
||||||
Handler: apis.Remove,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "PUT",
|
|
||||||
Pattern: "/dictType/refreshCache",
|
|
||||||
Handler: apis.RefreshCache,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/dictTypes/optionselect",
|
|
||||||
Handler: apis.DictOptionselect,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
// 添加更多的 Router 对象...
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成两组前缀路由
|
|
||||||
rsPrefix := []services.RouterItem{}
|
|
||||||
for _, v := range rs {
|
|
||||||
path := "/dictTypegManage/{apiVersion}" + v.Pattern
|
|
||||||
// 固定前缀
|
|
||||||
v.Pattern = config.DefaultUriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
// 可配置
|
|
||||||
v.Pattern = config.UriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
}
|
|
||||||
return rsPrefix
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型信息
|
|
||||||
//
|
|
||||||
// PATH /dictTypegManage
|
|
||||||
type SysDictTypeApi struct {
|
|
||||||
// 字典类型服务
|
|
||||||
sysDictTypeService sysDictTypeService.ServiceSysDictType
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型列表
|
|
||||||
//
|
|
||||||
// GET /list
|
|
||||||
func (s *SysDictTypeApi) List(w http.ResponseWriter, r *http.Request) {
|
|
||||||
querys := ctx.QueryMap(r)
|
|
||||||
data := s.sysDictTypeService.SelectDictTypePage(querys)
|
|
||||||
ctx.JSON(w, 200, result.Ok(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型信息
|
|
||||||
//
|
|
||||||
// GET /:dictId
|
|
||||||
func (s *SysDictTypeApi) Info(w http.ResponseWriter, r *http.Request) {
|
|
||||||
dictId := ctx.Param(r, "dictId")
|
|
||||||
if dictId == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data := s.sysDictTypeService.SelectDictTypeByID(dictId)
|
|
||||||
if data.DictID == dictId {
|
|
||||||
ctx.JSON(w, 200, result.OkData(data))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型新增
|
|
||||||
//
|
|
||||||
// POST /
|
|
||||||
func (s *SysDictTypeApi) Add(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body model.SysDictType
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.DictID != "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典名称唯一
|
|
||||||
uniqueDictName := s.sysDictTypeService.CheckUniqueDictName(body.DictName, "")
|
|
||||||
if !uniqueDictName {
|
|
||||||
msg := fmt.Sprintf("Failed to add dictionary '%s', dictionary name already exists", body.DictName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典类型唯一
|
|
||||||
uniqueDictType := s.sysDictTypeService.CheckUniqueDictType(body.DictType, "")
|
|
||||||
if !uniqueDictType {
|
|
||||||
msg := fmt.Sprintf("Failed to add dictionary '%s', dictionary type already exists", body.DictType)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body.CreateBy = ctx.LoginUserToUserName(r)
|
|
||||||
insertId := s.sysDictTypeService.InsertDictType(body)
|
|
||||||
if insertId != "" {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型修改
|
|
||||||
//
|
|
||||||
// PUT /
|
|
||||||
func (s *SysDictTypeApi) Edit(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body model.SysDictType
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.DictID == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查数据是否存在
|
|
||||||
dictInfo := s.sysDictTypeService.SelectDictTypeByID(body.DictID)
|
|
||||||
if dictInfo.DictID != body.DictID {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary type data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典名称唯一
|
|
||||||
uniqueDictName := s.sysDictTypeService.CheckUniqueDictName(body.DictName, body.DictID)
|
|
||||||
if !uniqueDictName {
|
|
||||||
msg := fmt.Sprintf("Dictionary modification failed for [%s], dictionary name already exists", body.DictName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查字典类型唯一
|
|
||||||
uniqueDictType := s.sysDictTypeService.CheckUniqueDictType(body.DictType, body.DictID)
|
|
||||||
if !uniqueDictType {
|
|
||||||
msg := fmt.Sprintf("Dictionary modification failed for [%s], dictionary type already exists", body.DictType)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body.UpdateBy = ctx.LoginUserToUserName(r)
|
|
||||||
rows := s.sysDictTypeService.UpdateDictType(body)
|
|
||||||
if rows > 0 {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型删除
|
|
||||||
//
|
|
||||||
// DELETE /:dictIds
|
|
||||||
func (s *SysDictTypeApi) Remove(w http.ResponseWriter, r *http.Request) {
|
|
||||||
dictIds := ctx.Param(r, "dictIds")
|
|
||||||
if dictIds == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 处理字符转id数组后去重
|
|
||||||
ids := strings.Split(dictIds, ",")
|
|
||||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
|
||||||
if len(uniqueIDs) <= 0 {
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rows, err := s.sysDictTypeService.DeleteDictTypeByIDs(uniqueIDs)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
msg := fmt.Sprintf("Successfully deleted: %d", rows)
|
|
||||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型刷新缓存
|
|
||||||
//
|
|
||||||
// PUT /refreshCache
|
|
||||||
func (s *SysDictTypeApi) RefreshCache(w http.ResponseWriter, r *http.Request) {
|
|
||||||
s.sysDictTypeService.ResetDictCache()
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型选择框列表
|
|
||||||
//
|
|
||||||
// GET /getDictOptionselect
|
|
||||||
func (s *SysDictTypeApi) DictOptionselect(w http.ResponseWriter, r *http.Request) {
|
|
||||||
data := s.sysDictTypeService.SelectDictTypeList(model.SysDictType{
|
|
||||||
Status: "1",
|
|
||||||
})
|
|
||||||
|
|
||||||
type labelValue struct {
|
|
||||||
Label string `json:"label"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数据组
|
|
||||||
arr := []labelValue{}
|
|
||||||
for _, v := range data {
|
|
||||||
arr = append(arr, labelValue{
|
|
||||||
Label: v.DictName,
|
|
||||||
Value: v.DictType,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.OkData(arr))
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
// SysDictType 字典类型对象 sys_dict_type
|
|
||||||
type SysDictType struct {
|
|
||||||
// 字典主键
|
|
||||||
DictID string `json:"dictId"`
|
|
||||||
// 字典名称
|
|
||||||
DictName string `json:"dictName" binding:"required"`
|
|
||||||
// 字典类型
|
|
||||||
DictType string `json:"dictType" binding:"required"`
|
|
||||||
// 状态(0停用 1正常)
|
|
||||||
Status string `json:"status"`
|
|
||||||
// 创建者
|
|
||||||
CreateBy string `json:"createBy"`
|
|
||||||
// 创建时间
|
|
||||||
CreateTime int64 `json:"createTime"`
|
|
||||||
// 更新者
|
|
||||||
UpdateBy string `json:"updateBy"`
|
|
||||||
// 更新时间
|
|
||||||
UpdateTime int64 `json:"updateTime"`
|
|
||||||
// 备注
|
|
||||||
Remark string `json:"remark"`
|
|
||||||
}
|
|
||||||
@@ -1,330 +0,0 @@
|
|||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/features/sys_dict_type/model"
|
|
||||||
"be.ems/lib/core/datasource"
|
|
||||||
"be.ems/lib/core/utils/date"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 RepoSysDictType 结构体
|
|
||||||
var NewRepoSysDictType = &RepoSysDictType{
|
|
||||||
selectSql: `select
|
|
||||||
dict_id, dict_name, dict_type, status, create_by, create_time, remark
|
|
||||||
from sys_dict_type`,
|
|
||||||
|
|
||||||
resultMap: map[string]string{
|
|
||||||
"dict_id": "DictID",
|
|
||||||
"dict_name": "DictName",
|
|
||||||
"dict_type": "DictType",
|
|
||||||
"remark": "Remark",
|
|
||||||
"status": "Status",
|
|
||||||
"create_by": "CreateBy",
|
|
||||||
"create_time": "CreateTime",
|
|
||||||
"update_by": "UpdateBy",
|
|
||||||
"update_time": "UpdateTime",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepoSysDictType 字典类型表 数据层处理
|
|
||||||
type RepoSysDictType struct {
|
|
||||||
// 查询视图对象SQL
|
|
||||||
selectSql string
|
|
||||||
// 结果字段与实体映射
|
|
||||||
resultMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
|
||||||
func (r *RepoSysDictType) convertResultRows(rows []map[string]any) []model.SysDictType {
|
|
||||||
arr := make([]model.SysDictType, 0)
|
|
||||||
for _, row := range rows {
|
|
||||||
sysDictType := model.SysDictType{}
|
|
||||||
for key, value := range row {
|
|
||||||
if keyMapper, ok := r.resultMap[key]; ok {
|
|
||||||
datasource.SetFieldValue(&sysDictType, keyMapper, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr = append(arr, sysDictType)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictTypePage 根据条件分页查询字典类型
|
|
||||||
func (r *RepoSysDictType) SelectDictTypePage(query map[string]any) map[string]any {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if v, ok := query["dictName"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "dict_name like concat(?, '%')")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["dictType"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "dict_type like concat(?, '%')")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["status"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "status = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
beginTime, ok := query["beginTime"]
|
|
||||||
if !ok {
|
|
||||||
beginTime, ok = query["params[beginTime]"]
|
|
||||||
}
|
|
||||||
if ok && beginTime != "" {
|
|
||||||
conditions = append(conditions, "create_time >= ?")
|
|
||||||
beginDate := date.ParseStrToDate(beginTime.(string), date.YYYY_MM_DD)
|
|
||||||
params = append(params, beginDate.UnixMilli())
|
|
||||||
}
|
|
||||||
endTime, ok := query["endTime"]
|
|
||||||
if !ok {
|
|
||||||
endTime, ok = query["params[endTime]"]
|
|
||||||
}
|
|
||||||
if ok && endTime != "" {
|
|
||||||
conditions = append(conditions, "create_time <= ?")
|
|
||||||
endDate := date.ParseStrToDate(endTime.(string), date.YYYY_MM_DD)
|
|
||||||
params = append(params, endDate.UnixMilli())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
totalSql := "select count(1) as 'total' from sys_dict_type"
|
|
||||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("total err => %v", err)
|
|
||||||
}
|
|
||||||
total := parse.Number(totalRows[0]["total"])
|
|
||||||
if total == 0 {
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": []model.SysDictType{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
|
||||||
pageSql := " limit ?,? "
|
|
||||||
params = append(params, pageNum*pageSize)
|
|
||||||
params = append(params, pageSize)
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + pageSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
rows := r.convertResultRows(results)
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": rows,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictTypeList 根据条件查询字典类型
|
|
||||||
func (r *RepoSysDictType) SelectDictTypeList(sysDictType model.SysDictType) []model.SysDictType {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysDictType.DictName != "" {
|
|
||||||
conditions = append(conditions, "dict_name like concat(?, '%')")
|
|
||||||
params = append(params, sysDictType.DictName)
|
|
||||||
}
|
|
||||||
if sysDictType.DictType != "" {
|
|
||||||
conditions = append(conditions, "dict_type like concat(?, '%')")
|
|
||||||
params = append(params, sysDictType.DictType)
|
|
||||||
}
|
|
||||||
if sysDictType.Status != "" {
|
|
||||||
conditions = append(conditions, "status = ?")
|
|
||||||
params = append(params, sysDictType.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysDictType{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictTypeByIDs 根据字典类型ID查询信息
|
|
||||||
func (r *RepoSysDictType) SelectDictTypeByIDs(dictIDs []string) []model.SysDictType {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(dictIDs))
|
|
||||||
querySql := r.selectSql + " where dict_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(dictIDs)
|
|
||||||
results, err := datasource.RawDB("", querySql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysDictType{}
|
|
||||||
}
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictTypeByType 根据字典类型查询信息
|
|
||||||
func (r *RepoSysDictType) SelectDictTypeByType(dictType string) model.SysDictType {
|
|
||||||
querySql := r.selectSql + " where dict_type = ?"
|
|
||||||
results, err := datasource.RawDB("", querySql, []any{dictType})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return model.SysDictType{}
|
|
||||||
}
|
|
||||||
// 转换实体
|
|
||||||
rows := r.convertResultRows(results)
|
|
||||||
if len(rows) > 0 {
|
|
||||||
return rows[0]
|
|
||||||
}
|
|
||||||
return model.SysDictType{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueDictType 校验字典是否唯一
|
|
||||||
func (r *RepoSysDictType) CheckUniqueDictType(sysDictType model.SysDictType) string {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysDictType.DictName != "" {
|
|
||||||
conditions = append(conditions, "dict_name = ?")
|
|
||||||
params = append(params, sysDictType.DictName)
|
|
||||||
}
|
|
||||||
if sysDictType.DictType != "" {
|
|
||||||
conditions = append(conditions, "dict_type = ?")
|
|
||||||
params = append(params, sysDictType.DictType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
} else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := "select dict_id as 'str' from sys_dict_type " + whereSql + " limit 1"
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err %v", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return fmt.Sprint(results[0]["str"])
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertDictType 新增字典类型信息
|
|
||||||
func (r *RepoSysDictType) InsertDictType(sysDictType model.SysDictType) string {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysDictType.DictName != "" {
|
|
||||||
params["dict_name"] = sysDictType.DictName
|
|
||||||
}
|
|
||||||
if sysDictType.DictType != "" {
|
|
||||||
params["dict_type"] = sysDictType.DictType
|
|
||||||
}
|
|
||||||
if sysDictType.Status != "" {
|
|
||||||
params["status"] = sysDictType.Status
|
|
||||||
}
|
|
||||||
if sysDictType.Remark != "" {
|
|
||||||
params["remark"] = sysDictType.Remark
|
|
||||||
}
|
|
||||||
if sysDictType.CreateBy != "" {
|
|
||||||
params["create_by"] = sysDictType.CreateBy
|
|
||||||
params["create_time"] = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
|
||||||
sql := "insert into sys_dict_type (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
|
||||||
|
|
||||||
// 执行插入
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
insertId, err := results.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return fmt.Sprint(insertId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateDictType 修改字典类型信息
|
|
||||||
func (r *RepoSysDictType) UpdateDictType(sysDictType model.SysDictType) int64 {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysDictType.DictName != "" {
|
|
||||||
params["dict_name"] = sysDictType.DictName
|
|
||||||
}
|
|
||||||
if sysDictType.DictType != "" {
|
|
||||||
params["dict_type"] = sysDictType.DictType
|
|
||||||
}
|
|
||||||
if sysDictType.Status != "" {
|
|
||||||
params["status"] = sysDictType.Status
|
|
||||||
}
|
|
||||||
if sysDictType.Remark != "" {
|
|
||||||
params["remark"] = sysDictType.Remark
|
|
||||||
}
|
|
||||||
if sysDictType.UpdateBy != "" {
|
|
||||||
params["update_by"] = sysDictType.UpdateBy
|
|
||||||
params["update_time"] = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, values := datasource.KeyValueByUpdate(params)
|
|
||||||
sql := "update sys_dict_type set " + strings.Join(keys, ",") + " where dict_id = ?"
|
|
||||||
|
|
||||||
// 执行更新
|
|
||||||
values = append(values, sysDictType.DictID)
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update row : %v", err.Error())
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteDictTypeByIDs 批量删除字典类型信息
|
|
||||||
func (r *RepoSysDictType) DeleteDictTypeByIDs(dictIDs []string) int64 {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(dictIDs))
|
|
||||||
sql := "delete from sys_dict_type where dict_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(dictIDs)
|
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
@@ -1,211 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
sysDictDataModel "be.ems/features/sys_dict_data/model"
|
|
||||||
sysDictDataRepo "be.ems/features/sys_dict_data/repo"
|
|
||||||
sysDictTypeModel "be.ems/features/sys_dict_type/model"
|
|
||||||
"be.ems/features/sys_dict_type/repo"
|
|
||||||
"be.ems/lib/core/cache"
|
|
||||||
"be.ems/lib/core/constants/cachekey"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 ServiceSysDictType 结构体
|
|
||||||
var NewServiceSysDictType = &ServiceSysDictType{
|
|
||||||
sysDictTypeRepository: *repo.NewRepoSysDictType,
|
|
||||||
sysDictDataRepository: *sysDictDataRepo.NewRepoSysDictData,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceSysDictType 字典类型 服务层处理
|
|
||||||
type ServiceSysDictType struct {
|
|
||||||
// 字典类型服务
|
|
||||||
sysDictTypeRepository repo.RepoSysDictType
|
|
||||||
// 字典数据服务
|
|
||||||
sysDictDataRepository sysDictDataRepo.RepoSysDictData
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictTypePage 根据条件分页查询字典类型
|
|
||||||
func (r *ServiceSysDictType) SelectDictTypePage(query map[string]any) map[string]any {
|
|
||||||
return r.sysDictTypeRepository.SelectDictTypePage(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictTypeList 根据条件查询字典类型
|
|
||||||
func (r *ServiceSysDictType) SelectDictTypeList(sysDictType sysDictTypeModel.SysDictType) []sysDictTypeModel.SysDictType {
|
|
||||||
return r.sysDictTypeRepository.SelectDictTypeList(sysDictType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictTypeByID 根据字典类型ID查询信息
|
|
||||||
func (r *ServiceSysDictType) SelectDictTypeByID(dictID string) sysDictTypeModel.SysDictType {
|
|
||||||
if dictID == "" {
|
|
||||||
return sysDictTypeModel.SysDictType{}
|
|
||||||
}
|
|
||||||
dictTypes := r.sysDictTypeRepository.SelectDictTypeByIDs([]string{dictID})
|
|
||||||
if len(dictTypes) > 0 {
|
|
||||||
return dictTypes[0]
|
|
||||||
}
|
|
||||||
return sysDictTypeModel.SysDictType{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectDictTypeByType 根据字典类型查询信息
|
|
||||||
func (r *ServiceSysDictType) SelectDictTypeByType(dictType string) sysDictTypeModel.SysDictType {
|
|
||||||
return r.sysDictTypeRepository.SelectDictTypeByType(dictType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueDictName 校验字典名称是否唯一
|
|
||||||
func (r *ServiceSysDictType) CheckUniqueDictName(dictName, dictID string) bool {
|
|
||||||
uniqueId := r.sysDictTypeRepository.CheckUniqueDictType(sysDictTypeModel.SysDictType{
|
|
||||||
DictName: dictName,
|
|
||||||
})
|
|
||||||
if uniqueId == dictID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueDictType 校验字典类型是否唯一
|
|
||||||
func (r *ServiceSysDictType) CheckUniqueDictType(dictType, dictID string) bool {
|
|
||||||
uniqueId := r.sysDictTypeRepository.CheckUniqueDictType(sysDictTypeModel.SysDictType{
|
|
||||||
DictType: dictType,
|
|
||||||
})
|
|
||||||
if uniqueId == dictID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertDictType 新增字典类型信息
|
|
||||||
func (r *ServiceSysDictType) InsertDictType(sysDictType sysDictTypeModel.SysDictType) string {
|
|
||||||
insertId := r.sysDictTypeRepository.InsertDictType(sysDictType)
|
|
||||||
if insertId != "" {
|
|
||||||
r.LoadingDictCache(sysDictType.DictType)
|
|
||||||
}
|
|
||||||
return insertId
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateDictType 修改字典类型信息
|
|
||||||
func (r *ServiceSysDictType) UpdateDictType(sysDictType sysDictTypeModel.SysDictType) int64 {
|
|
||||||
data := r.sysDictTypeRepository.SelectDictTypeByIDs([]string{sysDictType.DictID})
|
|
||||||
if len(data) == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
// 修改字典类型key时同步更新其字典数据的类型key
|
|
||||||
oldDictType := data[0].DictType
|
|
||||||
rows := r.sysDictTypeRepository.UpdateDictType(sysDictType)
|
|
||||||
if rows > 0 && oldDictType != "" && oldDictType != sysDictType.DictType {
|
|
||||||
r.sysDictDataRepository.UpdateDictDataType(oldDictType, sysDictType.DictType)
|
|
||||||
}
|
|
||||||
// 刷新缓存
|
|
||||||
r.ClearDictCache(oldDictType)
|
|
||||||
r.LoadingDictCache(sysDictType.DictType)
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteDictTypeByIDs 批量删除字典类型信息
|
|
||||||
func (r *ServiceSysDictType) DeleteDictTypeByIDs(dictIDs []string) (int64, error) {
|
|
||||||
// 检查是否存在
|
|
||||||
dictTypes := r.sysDictTypeRepository.SelectDictTypeByIDs(dictIDs)
|
|
||||||
if len(dictTypes) <= 0 {
|
|
||||||
return 0, errors.New("no permission to access dictionary type data")
|
|
||||||
}
|
|
||||||
for _, v := range dictTypes {
|
|
||||||
// 字典类型下级含有数据
|
|
||||||
useCount := r.sysDictDataRepository.CountDictDataByType(v.DictType)
|
|
||||||
if useCount > 0 {
|
|
||||||
msg := fmt.Sprintf("[%s] Dictionary data exists and cannot be deleted. ", v.DictName)
|
|
||||||
return 0, errors.New(msg)
|
|
||||||
}
|
|
||||||
// 清除缓存
|
|
||||||
r.ClearDictCache(v.DictType)
|
|
||||||
}
|
|
||||||
if len(dictTypes) == len(dictIDs) {
|
|
||||||
rows := r.sysDictTypeRepository.DeleteDictTypeByIDs(dictIDs)
|
|
||||||
return rows, nil
|
|
||||||
}
|
|
||||||
return 0, errors.New("failed to delete dictionary data information")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResetDictCache 重置字典缓存数据
|
|
||||||
func (r *ServiceSysDictType) ResetDictCache() {
|
|
||||||
r.ClearDictCache("*")
|
|
||||||
r.LoadingDictCache("")
|
|
||||||
}
|
|
||||||
|
|
||||||
// getCacheKey 组装缓存key
|
|
||||||
func (r *ServiceSysDictType) getDictCache(dictType string) string {
|
|
||||||
return cachekey.SYS_DICT_KEY + dictType
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadingDictCache 加载字典缓存数据
|
|
||||||
func (r *ServiceSysDictType) LoadingDictCache(dictType string) {
|
|
||||||
sysDictData := sysDictDataModel.SysDictData{
|
|
||||||
Status: "1",
|
|
||||||
}
|
|
||||||
|
|
||||||
// 指定字典类型
|
|
||||||
if dictType != "" {
|
|
||||||
sysDictData.DictType = dictType
|
|
||||||
// 删除缓存
|
|
||||||
key := r.getDictCache(dictType)
|
|
||||||
cache.DeleteLocal(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
sysDictDataList := r.sysDictDataRepository.SelectDictDataList(sysDictData)
|
|
||||||
if len(sysDictDataList) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将字典数据按类型分组
|
|
||||||
m := make(map[string][]sysDictDataModel.SysDictData, 0)
|
|
||||||
for _, v := range sysDictDataList {
|
|
||||||
key := v.DictType
|
|
||||||
if item, ok := m[key]; ok {
|
|
||||||
m[key] = append(item, v)
|
|
||||||
} else {
|
|
||||||
m[key] = []sysDictDataModel.SysDictData{v}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 放入缓存
|
|
||||||
for k, v := range m {
|
|
||||||
key := r.getDictCache(k)
|
|
||||||
values, _ := json.Marshal(v)
|
|
||||||
cache.SetLocal(key, string(values))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearDictCache 清空字典缓存数据
|
|
||||||
func (r *ServiceSysDictType) ClearDictCache(dictType string) bool {
|
|
||||||
key := r.getDictCache(dictType)
|
|
||||||
keys := cache.GetLocalKeys(key)
|
|
||||||
for _, v := range keys {
|
|
||||||
cache.DeleteLocal(v)
|
|
||||||
}
|
|
||||||
return len(keys) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// DictDataCache 获取字典数据缓存数据
|
|
||||||
func (r *ServiceSysDictType) DictDataCache(dictType string) []sysDictDataModel.SysDictData {
|
|
||||||
data := []sysDictDataModel.SysDictData{}
|
|
||||||
key := r.getDictCache(dictType)
|
|
||||||
jsonAny, ok := cache.GetLocal(key)
|
|
||||||
if jsonAny != nil && ok {
|
|
||||||
err := json.Unmarshal([]byte(jsonAny.(string)), &data)
|
|
||||||
if err != nil {
|
|
||||||
data = []sysDictDataModel.SysDictData{}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
data = r.sysDictDataRepository.SelectDictDataList(sysDictDataModel.SysDictData{
|
|
||||||
Status: "1",
|
|
||||||
DictType: dictType,
|
|
||||||
})
|
|
||||||
if len(data) > 0 {
|
|
||||||
cache.DeleteLocal(key)
|
|
||||||
values, _ := json.Marshal(data)
|
|
||||||
cache.SetLocal(key, string(values))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
@@ -1,354 +0,0 @@
|
|||||||
package sysmenu
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"be.ems/features/sys_menu/consts"
|
|
||||||
"be.ems/features/sys_menu/model"
|
|
||||||
"be.ems/features/sys_menu/service"
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/core/utils/regular"
|
|
||||||
"be.ems/lib/core/vo/result"
|
|
||||||
"be.ems/lib/midware"
|
|
||||||
"be.ems/lib/services"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
srcConfig "be.ems/src/framework/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 菜单接口添加到路由
|
|
||||||
func Routers() []services.RouterItem {
|
|
||||||
// 实例化控制层 SysMenuApi 结构体
|
|
||||||
var apis = &SysMenuApi{
|
|
||||||
sysMenuService: service.NewServiceSysMenu,
|
|
||||||
}
|
|
||||||
|
|
||||||
rs := [...]services.RouterItem{
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/menus",
|
|
||||||
Handler: apis.List,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/menu/{menuId}",
|
|
||||||
Handler: apis.Info,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "POST",
|
|
||||||
Pattern: "/menu",
|
|
||||||
Handler: apis.Add,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "PUT",
|
|
||||||
Pattern: "/menu",
|
|
||||||
Handler: apis.Edit,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "DELETE",
|
|
||||||
Pattern: "/menu/{menuId}",
|
|
||||||
Handler: apis.Remove,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/menus/treeSelect",
|
|
||||||
Handler: apis.TreeSelect,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/menu/roleMenuTreeSelect/{roleId}",
|
|
||||||
Handler: apis.RoleMenuTreeSelect,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
// 添加更多的 Router 对象...
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成两组前缀路由
|
|
||||||
rsPrefix := []services.RouterItem{}
|
|
||||||
for _, v := range rs {
|
|
||||||
path := "/menuManage/{apiVersion}" + v.Pattern
|
|
||||||
// 固定前缀
|
|
||||||
v.Pattern = config.DefaultUriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
// 可配置
|
|
||||||
v.Pattern = config.UriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
}
|
|
||||||
return rsPrefix
|
|
||||||
}
|
|
||||||
|
|
||||||
// // 实例化控制层 SysMenuApi 结构体
|
|
||||||
// var NewSysMenu = &SysMenuApi{
|
|
||||||
// sysMenuService: NewServiceSysMenu,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 菜单信息
|
|
||||||
//
|
|
||||||
// PATH /menuManage
|
|
||||||
type SysMenuApi struct {
|
|
||||||
// 菜单服务
|
|
||||||
sysMenuService *service.ServiceSysMenu
|
|
||||||
}
|
|
||||||
|
|
||||||
// 菜单列表
|
|
||||||
//
|
|
||||||
// GET /list
|
|
||||||
func (s *SysMenuApi) List(w http.ResponseWriter, r *http.Request) {
|
|
||||||
query := model.SysMenu{}
|
|
||||||
if v := ctx.GetQuery(r, "menuName"); v != "" {
|
|
||||||
query.MenuName = v
|
|
||||||
}
|
|
||||||
if v := ctx.GetQuery(r, "status"); v != "" {
|
|
||||||
query.Status = v
|
|
||||||
}
|
|
||||||
|
|
||||||
userId := ctx.LoginUserToUserID(r)
|
|
||||||
if srcConfig.IsAdmin(userId) {
|
|
||||||
userId = "*"
|
|
||||||
}
|
|
||||||
data := s.sysMenuService.SelectMenuList(query, userId)
|
|
||||||
ctx.JSON(w, 200, result.OkData(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 菜单信息
|
|
||||||
//
|
|
||||||
// GET /:menuId
|
|
||||||
func (s *SysMenuApi) Info(w http.ResponseWriter, r *http.Request) {
|
|
||||||
menuId := ctx.Param(r, "menuId")
|
|
||||||
if menuId == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data := s.sysMenuService.SelectMenuById(menuId)
|
|
||||||
if data.MenuID == menuId {
|
|
||||||
ctx.JSON(w, 200, result.OkData(data))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 菜单新增
|
|
||||||
//
|
|
||||||
// POST /
|
|
||||||
func (s *SysMenuApi) Add(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body model.SysMenu
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.MenuID != "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 目录和菜单检查地址唯一
|
|
||||||
if consts.TYPE_DIR == body.MenuType || consts.TYPE_MENU == body.MenuType {
|
|
||||||
uniqueNenuPath := s.sysMenuService.CheckUniqueMenuPath(body.Path, "")
|
|
||||||
if !uniqueNenuPath {
|
|
||||||
msg := fmt.Sprintf("菜单新增【%s】失败,菜单路由地址已存在", body.MenuName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查名称唯一
|
|
||||||
uniqueNenuName := s.sysMenuService.CheckUniqueMenuName(body.MenuName, body.ParentID, "")
|
|
||||||
if !uniqueNenuName {
|
|
||||||
msg := fmt.Sprintf("菜单新增【%s】失败,菜单名称已存在", body.MenuName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 外链菜单需要符合网站http(s)开头
|
|
||||||
if body.IsFrame == "0" && !regular.ValidHttp(body.Path) {
|
|
||||||
msg := fmt.Sprintf("菜单新增【%s】失败,非内部地址必须以http(s)://开头", body.MenuName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body.CreateBy = ctx.LoginUserToUserName(r)
|
|
||||||
insertId := s.sysMenuService.InsertMenu(body)
|
|
||||||
if insertId != "" {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 菜单修改
|
|
||||||
//
|
|
||||||
// PUT /
|
|
||||||
func (s *SysMenuApi) Edit(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body model.SysMenu
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.MenuID == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上级菜单不能选自己
|
|
||||||
if body.MenuID == body.ParentID {
|
|
||||||
msg := fmt.Sprintf("Menu modification failed for [%s], parent menu cannot select itself", body.MenuName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查数据是否存在
|
|
||||||
menuInfo := s.sysMenuService.SelectMenuById(body.MenuID)
|
|
||||||
if menuInfo.MenuID != body.MenuID {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access menu data"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 父级ID不为0是要检查
|
|
||||||
if body.ParentID != "0" {
|
|
||||||
menuParent := s.sysMenuService.SelectMenuById(body.ParentID)
|
|
||||||
if menuParent.MenuID != body.ParentID {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access menu data"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 禁用菜单时检查父菜单是否使用
|
|
||||||
if body.Status == "1" && menuParent.Status == "0" {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("Parent menu not enabled!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 目录和菜单检查地址唯一
|
|
||||||
if consts.TYPE_DIR == body.MenuType || consts.TYPE_MENU == body.MenuType {
|
|
||||||
uniqueNenuPath := s.sysMenuService.CheckUniqueMenuPath(body.Path, body.MenuID)
|
|
||||||
if !uniqueNenuPath {
|
|
||||||
msg := fmt.Sprintf("菜单修改【%s】失败,菜单路由地址已存在", body.MenuName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查名称唯一
|
|
||||||
uniqueNenuName := s.sysMenuService.CheckUniqueMenuName(body.MenuName, body.ParentID, body.MenuID)
|
|
||||||
if !uniqueNenuName {
|
|
||||||
msg := fmt.Sprintf("菜单修改【%s】失败,菜单名称已存在", body.MenuName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 外链菜单需要符合网站http(s)开头
|
|
||||||
if body.IsFrame == "0" && !regular.ValidHttp(body.Path) {
|
|
||||||
msg := fmt.Sprintf("菜单修改【%s】失败,非内部地址必须以http(s)://开头", body.MenuName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 禁用菜单时检查子菜单是否使用
|
|
||||||
if body.Status == "0" {
|
|
||||||
hasStatus := s.sysMenuService.HasChildByMenuIdAndStatus(body.MenuID, "1")
|
|
||||||
if hasStatus > 0 {
|
|
||||||
msg := fmt.Sprintf("不允许禁用,存在使用子菜单数:%d", hasStatus)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body.UpdateBy = ctx.LoginUserToUserName(r)
|
|
||||||
rows := s.sysMenuService.UpdateMenu(body)
|
|
||||||
if rows > 0 {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 菜单删除
|
|
||||||
//
|
|
||||||
// DELETE /:menuId
|
|
||||||
func (s *SysMenuApi) Remove(w http.ResponseWriter, r *http.Request) {
|
|
||||||
menuId := ctx.Param(r, "menuId")
|
|
||||||
if menuId == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查数据是否存在
|
|
||||||
menu := s.sysMenuService.SelectMenuById(menuId)
|
|
||||||
if menu.MenuID != menuId {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access menu data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否存在子菜单
|
|
||||||
hasChild := s.sysMenuService.HasChildByMenuIdAndStatus(menuId, "")
|
|
||||||
if hasChild > 0 {
|
|
||||||
msg := fmt.Sprintf("Deletion not allowed, there are sub orders: %d", hasChild)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否分配给角色
|
|
||||||
existRole := s.sysMenuService.CheckMenuExistRole(menuId)
|
|
||||||
if existRole > 0 {
|
|
||||||
msg := fmt.Sprintf("Deletion not allowed, menu already assigned to roles: %d", existRole)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rows := s.sysMenuService.DeleteMenuById(menuId)
|
|
||||||
if rows > 0 {
|
|
||||||
msg := fmt.Sprintf("Successfully deleted: %d", rows)
|
|
||||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 菜单树结构列表
|
|
||||||
//
|
|
||||||
// GET /treeSelect
|
|
||||||
func (s *SysMenuApi) TreeSelect(w http.ResponseWriter, r *http.Request) {
|
|
||||||
query := model.SysMenu{}
|
|
||||||
if v := ctx.GetQuery(r, "menuName"); v != "" {
|
|
||||||
query.MenuName = v
|
|
||||||
}
|
|
||||||
if v := ctx.GetQuery(r, "status"); v != "" {
|
|
||||||
query.Status = v
|
|
||||||
}
|
|
||||||
|
|
||||||
userId := ctx.LoginUserToUserID(r)
|
|
||||||
if srcConfig.IsAdmin(userId) {
|
|
||||||
userId = "*"
|
|
||||||
}
|
|
||||||
data := s.sysMenuService.SelectMenuTreeSelectByUserId(query, userId)
|
|
||||||
ctx.JSON(w, 200, result.OkData(data))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 菜单树结构列表(指定角色)
|
|
||||||
//
|
|
||||||
// GET /roleMenuTreeSelect/:roleId
|
|
||||||
func (s *SysMenuApi) RoleMenuTreeSelect(w http.ResponseWriter, r *http.Request) {
|
|
||||||
roleId := ctx.Param(r, "roleId")
|
|
||||||
if roleId == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
query := model.SysMenu{}
|
|
||||||
if v := ctx.GetQuery(r, "menuName"); v != "" {
|
|
||||||
query.MenuName = v
|
|
||||||
}
|
|
||||||
if v := ctx.GetQuery(r, "status"); v != "" {
|
|
||||||
query.Status = v
|
|
||||||
}
|
|
||||||
|
|
||||||
userId := ctx.LoginUserToUserID(r)
|
|
||||||
if srcConfig.IsAdmin(userId) {
|
|
||||||
userId = "*"
|
|
||||||
}
|
|
||||||
menuTreeSelect := s.sysMenuService.SelectMenuTreeSelectByUserId(query, userId)
|
|
||||||
checkedKeys := s.sysMenuService.SelectMenuListByRoleId(roleId)
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"menus": menuTreeSelect,
|
|
||||||
"checkedKeys": checkedKeys,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package consts
|
|
||||||
|
|
||||||
// 系统菜单常量信息
|
|
||||||
|
|
||||||
const (
|
|
||||||
// 组件布局类型-基础布局组件标识
|
|
||||||
COMPONENT_LAYOUT_BASIC = "BasicLayout"
|
|
||||||
// 组件布局类型-空白布局组件标识
|
|
||||||
COMPONENT_LAYOUT_BLANK = "BlankLayout"
|
|
||||||
// 组件布局类型-内链接布局组件标识
|
|
||||||
COMPONENT_LAYOUT_LINK = "LinkLayout"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// 菜单类型-目录
|
|
||||||
TYPE_DIR = "D"
|
|
||||||
// 菜单类型-菜单
|
|
||||||
TYPE_MENU = "M"
|
|
||||||
// 菜单类型-按钮
|
|
||||||
TYPE_BUTTON = "B"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 菜单内嵌地址标识-带/前缀
|
|
||||||
const PATH_INLINE = "/inline"
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
// SysMenu 菜单权限对象 sys_menu
|
|
||||||
type SysMenu struct {
|
|
||||||
// 菜单ID
|
|
||||||
MenuID string `json:"menuId"`
|
|
||||||
// 菜单名称
|
|
||||||
MenuName string `json:"menuName" binding:"required"`
|
|
||||||
// 父菜单ID 默认0
|
|
||||||
ParentID string `json:"parentId" binding:"required"`
|
|
||||||
// 显示顺序
|
|
||||||
MenuSort int `json:"menuSort"`
|
|
||||||
// 路由地址
|
|
||||||
Path string `json:"path"`
|
|
||||||
// 组件路径
|
|
||||||
Component string `json:"component"`
|
|
||||||
// 是否内部跳转(0否 1是)
|
|
||||||
IsFrame string `json:"isFrame"`
|
|
||||||
// 是否缓存(0不缓存 1缓存)
|
|
||||||
IsCache string `json:"isCache"`
|
|
||||||
// 菜单类型(D目录 M菜单 B按钮)
|
|
||||||
MenuType string `json:"menuType" binding:"required"`
|
|
||||||
// 是否显示(0隐藏 1显示)
|
|
||||||
Visible string `json:"visible"`
|
|
||||||
// 菜单状态(0停用 1正常)
|
|
||||||
Status string `json:"status"`
|
|
||||||
// 权限标识
|
|
||||||
Perms string `json:"perms"`
|
|
||||||
// 菜单图标(#无图标)
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
// 创建者
|
|
||||||
CreateBy string `json:"createBy"`
|
|
||||||
// 创建时间
|
|
||||||
CreateTime int64 `json:"createTime"`
|
|
||||||
// 更新者
|
|
||||||
UpdateBy string `json:"updateBy"`
|
|
||||||
// 更新时间
|
|
||||||
UpdateTime int64 `json:"updateTime"`
|
|
||||||
// 备注
|
|
||||||
Remark string `json:"remark"`
|
|
||||||
|
|
||||||
// ====== 非数据库字段属性 ======
|
|
||||||
|
|
||||||
// 子菜单
|
|
||||||
Children []SysMenu `json:"children,omitempty"`
|
|
||||||
}
|
|
||||||
@@ -1,475 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/features/sys_menu/consts"
|
|
||||||
"be.ems/features/sys_menu/model"
|
|
||||||
"be.ems/lib/core/datasource"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 RepoSysMenu 结构体
|
|
||||||
var NewRepoSysMenu = &RepoSysMenu{
|
|
||||||
selectSql: `select
|
|
||||||
m.menu_id, m.menu_name, m.parent_id, m.menu_sort, m.path, m.component, m.is_frame, m.is_cache, m.menu_type, m.visible, m.status, ifnull(m.perms,'') as perms, m.icon, m.create_time, m.remark
|
|
||||||
from sys_menu m`,
|
|
||||||
|
|
||||||
selectSqlByUser: `select distinct
|
|
||||||
m.menu_id, m.menu_name, m.parent_id, m.menu_sort, m.path, m.component, m.is_frame, m.is_cache, m.menu_type, m.visible, m.status, ifnull(m.perms,'') as perms, m.icon, m.create_time, m.remark
|
|
||||||
from sys_menu m
|
|
||||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
|
||||||
left join sys_user_role ur on rm.role_id = ur.role_id
|
|
||||||
left join sys_role ro on ur.role_id = ro.role_id`,
|
|
||||||
|
|
||||||
resultMap: map[string]string{
|
|
||||||
"menu_id": "MenuID",
|
|
||||||
"menu_name": "MenuName",
|
|
||||||
"parent_name": "ParentName",
|
|
||||||
"parent_id": "ParentID",
|
|
||||||
"path": "Path",
|
|
||||||
"menu_sort": "MenuSort",
|
|
||||||
"component": "Component",
|
|
||||||
"is_frame": "IsFrame",
|
|
||||||
"is_cache": "IsCache",
|
|
||||||
"menu_type": "MenuType",
|
|
||||||
"visible": "Visible",
|
|
||||||
"status": "Status",
|
|
||||||
"perms": "Perms",
|
|
||||||
"icon": "Icon",
|
|
||||||
"create_by": "CreateBy",
|
|
||||||
"create_time": "CreateTime",
|
|
||||||
"update_by": "UpdateBy",
|
|
||||||
"update_time": "UpdateTime",
|
|
||||||
"remark": "Remark",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepoSysMenu 菜单表 数据层处理
|
|
||||||
type RepoSysMenu struct {
|
|
||||||
// 查询视图对象SQL
|
|
||||||
selectSql string
|
|
||||||
// 查询视图用户对象SQL
|
|
||||||
selectSqlByUser string
|
|
||||||
// 结果字段与实体映射
|
|
||||||
resultMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
|
||||||
func (r *RepoSysMenu) convertResultRows(rows []map[string]any) []model.SysMenu {
|
|
||||||
arr := make([]model.SysMenu, 0)
|
|
||||||
for _, row := range rows {
|
|
||||||
sysMenu := model.SysMenu{}
|
|
||||||
for key, value := range row {
|
|
||||||
if keyMapper, ok := r.resultMap[key]; ok {
|
|
||||||
datasource.SetFieldValue(&sysMenu, keyMapper, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr = append(arr, sysMenu)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuList 查询系统菜单列表
|
|
||||||
func (r *RepoSysMenu) SelectMenuList(sysMenu model.SysMenu, userId string) []model.SysMenu {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysMenu.MenuName != "" {
|
|
||||||
conditions = append(conditions, "m.menu_name like concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, sysMenu.MenuName)
|
|
||||||
}
|
|
||||||
if sysMenu.Visible != "" {
|
|
||||||
conditions = append(conditions, "m.visible = ?")
|
|
||||||
params = append(params, sysMenu.Visible)
|
|
||||||
}
|
|
||||||
if sysMenu.Status != "" {
|
|
||||||
conditions = append(conditions, "m.status = ?")
|
|
||||||
params = append(params, sysMenu.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
fromSql := r.selectSql
|
|
||||||
|
|
||||||
// 个人菜单
|
|
||||||
if userId != "*" {
|
|
||||||
fromSql = r.selectSqlByUser
|
|
||||||
conditions = append(conditions, "ur.user_id = ?")
|
|
||||||
params = append(params, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
orderSql := " order by m.parent_id, m.menu_sort"
|
|
||||||
querySql := fromSql + whereSql + orderSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysMenu{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuPermsByUserId 根据用户ID查询权限
|
|
||||||
func (r *RepoSysMenu) SelectMenuPermsByUserId(userId string) []string {
|
|
||||||
querySql := `select distinct m.perms as 'str' from sys_menu m
|
|
||||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
|
||||||
left join sys_user_role ur on rm.role_id = ur.role_id
|
|
||||||
left join sys_role r on r.role_id = ur.role_id
|
|
||||||
where m.status = '1' and m.perms != '' and r.status = '1' and ur.user_id = ? `
|
|
||||||
|
|
||||||
// 查询结果
|
|
||||||
results, err := datasource.RawDB("", querySql, []any{userId})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取结果
|
|
||||||
rows := make([]string, 0)
|
|
||||||
for _, m := range results {
|
|
||||||
rows = append(rows, fmt.Sprintf("%v", m["str"]))
|
|
||||||
}
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuTreeByUserId 根据用户ID查询菜单
|
|
||||||
func (r *RepoSysMenu) SelectMenuTreeByUserId(userId string) []model.SysMenu {
|
|
||||||
var params []any
|
|
||||||
var querySql string
|
|
||||||
|
|
||||||
if userId == "*" {
|
|
||||||
// 管理员全部菜单
|
|
||||||
querySql = r.selectSql + ` where
|
|
||||||
m.menu_type in (?,?) and m.status = '1'
|
|
||||||
order by m.parent_id, m.menu_sort`
|
|
||||||
params = append(params, consts.TYPE_DIR)
|
|
||||||
params = append(params, consts.TYPE_MENU)
|
|
||||||
} else {
|
|
||||||
// 用户ID权限
|
|
||||||
querySql = r.selectSqlByUser + ` where
|
|
||||||
m.menu_type in (?, ?) and m.status = '1'
|
|
||||||
and ur.user_id = ? and ro.status = '1'
|
|
||||||
order by m.parent_id, m.menu_sort`
|
|
||||||
params = append(params, consts.TYPE_DIR)
|
|
||||||
params = append(params, consts.TYPE_MENU)
|
|
||||||
params = append(params, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询结果
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysMenu{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuListByRoleId 根据角色ID查询菜单树信息
|
|
||||||
func (r *RepoSysMenu) SelectMenuListByRoleId(roleId string, menuCheckStrictly bool) []string {
|
|
||||||
querySql := `select m.menu_id as 'str' from sys_menu m
|
|
||||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
|
||||||
where rm.role_id = ? `
|
|
||||||
var params []any
|
|
||||||
params = append(params, roleId)
|
|
||||||
// 展开
|
|
||||||
if menuCheckStrictly {
|
|
||||||
querySql += ` and m.menu_id not in
|
|
||||||
(select m.parent_id from sys_menu m
|
|
||||||
inner join sys_role_menu rm on m.menu_id = rm.menu_id
|
|
||||||
and rm.role_id = ?) `
|
|
||||||
params = append(params, roleId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询结果
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(results) > 0 {
|
|
||||||
ids := make([]string, 0)
|
|
||||||
for _, v := range results {
|
|
||||||
ids = append(ids, fmt.Sprintf("%v", v["str"]))
|
|
||||||
}
|
|
||||||
return ids
|
|
||||||
}
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuByIds 根据菜单ID查询信息
|
|
||||||
func (r *RepoSysMenu) SelectMenuByIds(menuIds []string) []model.SysMenu {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(menuIds))
|
|
||||||
querySql := r.selectSql + " where m.menu_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(menuIds)
|
|
||||||
results, err := datasource.RawDB("", querySql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysMenu{}
|
|
||||||
}
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasChildByMenuIdAndStatus 存在菜单子节点数量与状态
|
|
||||||
func (r *RepoSysMenu) HasChildByMenuIdAndStatus(menuId, status string) int64 {
|
|
||||||
querySql := "select count(1) as 'total' from sys_menu where parent_id = ?"
|
|
||||||
params := []any{menuId}
|
|
||||||
|
|
||||||
// 菜单状态
|
|
||||||
if status != "" {
|
|
||||||
querySql += " and status = ?"
|
|
||||||
params = append(params, status)
|
|
||||||
}
|
|
||||||
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return parse.Number(results[0]["total"])
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertMenu 新增菜单信息
|
|
||||||
func (r *RepoSysMenu) InsertMenu(sysMenu model.SysMenu) string {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysMenu.MenuID != "" {
|
|
||||||
params["menu_id"] = sysMenu.MenuID
|
|
||||||
}
|
|
||||||
if sysMenu.ParentID != "" {
|
|
||||||
params["parent_id"] = sysMenu.ParentID
|
|
||||||
}
|
|
||||||
if sysMenu.MenuName != "" {
|
|
||||||
params["menu_name"] = sysMenu.MenuName
|
|
||||||
}
|
|
||||||
if sysMenu.MenuSort > 0 {
|
|
||||||
params["menu_sort"] = sysMenu.MenuSort
|
|
||||||
}
|
|
||||||
if sysMenu.Path != "" {
|
|
||||||
params["path"] = sysMenu.Path
|
|
||||||
}
|
|
||||||
if sysMenu.Component != "" {
|
|
||||||
params["component"] = sysMenu.Component
|
|
||||||
}
|
|
||||||
if sysMenu.IsFrame != "" {
|
|
||||||
params["is_frame"] = sysMenu.IsFrame
|
|
||||||
}
|
|
||||||
if sysMenu.IsCache != "" {
|
|
||||||
params["is_cache"] = sysMenu.IsCache
|
|
||||||
}
|
|
||||||
if sysMenu.MenuType != "" {
|
|
||||||
params["menu_type"] = sysMenu.MenuType
|
|
||||||
}
|
|
||||||
if sysMenu.Visible != "" {
|
|
||||||
params["visible"] = sysMenu.Visible
|
|
||||||
}
|
|
||||||
if sysMenu.Status != "" {
|
|
||||||
params["status"] = sysMenu.Status
|
|
||||||
}
|
|
||||||
if sysMenu.Perms != "" {
|
|
||||||
params["perms"] = sysMenu.Perms
|
|
||||||
}
|
|
||||||
if sysMenu.Icon != "" {
|
|
||||||
params["icon"] = sysMenu.Icon
|
|
||||||
} else {
|
|
||||||
params["icon"] = "#"
|
|
||||||
}
|
|
||||||
if sysMenu.Remark != "" {
|
|
||||||
params["remark"] = sysMenu.Remark
|
|
||||||
}
|
|
||||||
if sysMenu.CreateBy != "" {
|
|
||||||
params["create_by"] = sysMenu.CreateBy
|
|
||||||
params["create_time"] = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据菜单类型重置参数
|
|
||||||
if sysMenu.MenuType == consts.TYPE_BUTTON {
|
|
||||||
params["component"] = ""
|
|
||||||
params["path"] = ""
|
|
||||||
params["icon"] = "#"
|
|
||||||
params["is_cache"] = "1"
|
|
||||||
params["is_frame"] = "1"
|
|
||||||
params["visible"] = "1"
|
|
||||||
params["status"] = "1"
|
|
||||||
}
|
|
||||||
if sysMenu.MenuType == consts.TYPE_DIR {
|
|
||||||
params["component"] = ""
|
|
||||||
params["perms"] = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
|
||||||
sql := "insert into sys_menu (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
|
||||||
|
|
||||||
// 执行插入
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
insertId, err := results.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return fmt.Sprint(insertId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateMenu 修改菜单信息
|
|
||||||
func (r *RepoSysMenu) UpdateMenu(sysMenu model.SysMenu) int64 {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysMenu.MenuID != "" {
|
|
||||||
params["menu_id"] = sysMenu.MenuID
|
|
||||||
}
|
|
||||||
if sysMenu.ParentID != "" {
|
|
||||||
params["parent_id"] = sysMenu.ParentID
|
|
||||||
}
|
|
||||||
if sysMenu.MenuName != "" {
|
|
||||||
params["menu_name"] = sysMenu.MenuName
|
|
||||||
}
|
|
||||||
if sysMenu.MenuSort > 0 {
|
|
||||||
params["menu_sort"] = sysMenu.MenuSort
|
|
||||||
}
|
|
||||||
if sysMenu.Path != "" {
|
|
||||||
params["path"] = sysMenu.Path
|
|
||||||
}
|
|
||||||
if sysMenu.Component != "" {
|
|
||||||
params["component"] = sysMenu.Component
|
|
||||||
}
|
|
||||||
if sysMenu.IsFrame != "" {
|
|
||||||
params["is_frame"] = sysMenu.IsFrame
|
|
||||||
}
|
|
||||||
if sysMenu.IsCache != "" {
|
|
||||||
params["is_cache"] = sysMenu.IsCache
|
|
||||||
}
|
|
||||||
if sysMenu.MenuType != "" {
|
|
||||||
params["menu_type"] = sysMenu.MenuType
|
|
||||||
}
|
|
||||||
if sysMenu.Visible != "" {
|
|
||||||
params["visible"] = sysMenu.Visible
|
|
||||||
}
|
|
||||||
if sysMenu.Status != "" {
|
|
||||||
params["status"] = sysMenu.Status
|
|
||||||
}
|
|
||||||
if sysMenu.Perms != "" {
|
|
||||||
params["perms"] = sysMenu.Perms
|
|
||||||
}
|
|
||||||
if sysMenu.Icon != "" {
|
|
||||||
params["icon"] = sysMenu.Icon
|
|
||||||
} else {
|
|
||||||
params["icon"] = "#"
|
|
||||||
}
|
|
||||||
if sysMenu.Remark != "" {
|
|
||||||
params["remark"] = sysMenu.Remark
|
|
||||||
}
|
|
||||||
if sysMenu.UpdateBy != "" {
|
|
||||||
params["update_by"] = sysMenu.UpdateBy
|
|
||||||
params["update_time"] = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据菜单类型重置参数
|
|
||||||
if sysMenu.MenuType == consts.TYPE_BUTTON {
|
|
||||||
params["component"] = ""
|
|
||||||
params["path"] = ""
|
|
||||||
params["icon"] = "#"
|
|
||||||
params["is_cache"] = "1"
|
|
||||||
params["is_frame"] = "1"
|
|
||||||
params["visible"] = "1"
|
|
||||||
params["status"] = "1"
|
|
||||||
}
|
|
||||||
if sysMenu.MenuType == consts.TYPE_DIR {
|
|
||||||
params["component"] = ""
|
|
||||||
params["perms"] = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, values := datasource.KeyValueByUpdate(params)
|
|
||||||
sql := "update sys_menu set " + strings.Join(keys, ",") + " where menu_id = ?"
|
|
||||||
|
|
||||||
// 执行更新
|
|
||||||
values = append(values, sysMenu.MenuID)
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update row : %v", err.Error())
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteMenuById 删除菜单管理信息
|
|
||||||
func (r *RepoSysMenu) DeleteMenuById(menuId string) int64 {
|
|
||||||
sql := "delete from sys_menu where menu_id = ?"
|
|
||||||
results, err := datasource.ExecDB("", sql, []any{menuId})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueMenu 校验菜单是否唯一
|
|
||||||
func (r *RepoSysMenu) CheckUniqueMenu(sysMenu model.SysMenu) string {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysMenu.MenuName != "" {
|
|
||||||
conditions = append(conditions, "menu_name = ?")
|
|
||||||
params = append(params, sysMenu.MenuName)
|
|
||||||
}
|
|
||||||
if sysMenu.ParentID != "" {
|
|
||||||
conditions = append(conditions, "parent_id = ?")
|
|
||||||
params = append(params, sysMenu.ParentID)
|
|
||||||
}
|
|
||||||
if sysMenu.Path != "" {
|
|
||||||
conditions = append(conditions, "path = ?")
|
|
||||||
params = append(params, sysMenu.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
if whereSql == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := "select menu_id as 'str' from sys_menu " + whereSql + " limit 1"
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err %v", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return fmt.Sprint(results[0]["str"])
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
@@ -1,408 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/base64"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/features/sys_menu/consts"
|
|
||||||
"be.ems/features/sys_menu/model"
|
|
||||||
sysRoleService "be.ems/features/sys_role/service"
|
|
||||||
sysrolemenu "be.ems/features/sys_role_menu"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/core/utils/regular"
|
|
||||||
"be.ems/lib/core/vo"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 ServiceSysMenu 结构体
|
|
||||||
var NewServiceSysMenu = &ServiceSysMenu{
|
|
||||||
sysMenuRepository: NewRepoSysMenu,
|
|
||||||
sysRoleMenuRepository: sysrolemenu.NewRepoSysRoleMenu,
|
|
||||||
sysRoleRepository: sysRoleService.NewRepoSysRole,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceSysMenu 菜单 服务层处理
|
|
||||||
type ServiceSysMenu struct {
|
|
||||||
// 菜单服务
|
|
||||||
sysMenuRepository *RepoSysMenu
|
|
||||||
// 角色与菜单关联服务
|
|
||||||
sysRoleMenuRepository *sysrolemenu.RepoSysRoleMenu
|
|
||||||
// 角色服务
|
|
||||||
sysRoleRepository *sysRoleService.RepoSysRole
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuList 查询系统菜单列表
|
|
||||||
func (r *ServiceSysMenu) SelectMenuList(sysMenu model.SysMenu, userId string) []model.SysMenu {
|
|
||||||
return r.sysMenuRepository.SelectMenuList(sysMenu, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuPermsByUserId 根据用户ID查询权限
|
|
||||||
func (r *ServiceSysMenu) SelectMenuPermsByUserId(userId string) []string {
|
|
||||||
return r.sysMenuRepository.SelectMenuPermsByUserId(userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuTreeByUserId 根据用户ID查询菜单
|
|
||||||
func (r *ServiceSysMenu) SelectMenuTreeByUserId(userId string) []model.SysMenu {
|
|
||||||
sysMenus := r.sysMenuRepository.SelectMenuTreeByUserId(userId)
|
|
||||||
return r.parseDataToTree(sysMenus)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuTreeSelectByUserId 根据用户ID查询菜单树结构信息
|
|
||||||
func (r *ServiceSysMenu) SelectMenuTreeSelectByUserId(sysMenu model.SysMenu, userId string) []vo.TreeSelect {
|
|
||||||
sysMenus := r.sysMenuRepository.SelectMenuList(sysMenu, userId)
|
|
||||||
|
|
||||||
// 过滤旧前端菜单
|
|
||||||
sysMenusF := []model.SysMenu{}
|
|
||||||
for _, v := range sysMenus {
|
|
||||||
if v.Perms != "page" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sysMenusF = append(sysMenusF, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
menus := r.parseDataToTree(sysMenusF)
|
|
||||||
tree := make([]vo.TreeSelect, 0)
|
|
||||||
for _, menu := range menus {
|
|
||||||
tree = append(tree, sysMenuTreeSelect(menu))
|
|
||||||
}
|
|
||||||
return tree
|
|
||||||
}
|
|
||||||
|
|
||||||
// sysMenuTreeSelect 使用给定的 SysMenu 对象解析为 TreeSelect 对象
|
|
||||||
func sysMenuTreeSelect(sysMenu model.SysMenu) vo.TreeSelect {
|
|
||||||
t := vo.TreeSelect{}
|
|
||||||
t.ID = sysMenu.MenuID
|
|
||||||
t.Label = sysMenu.MenuName
|
|
||||||
t.Title = sysMenu.MenuName
|
|
||||||
|
|
||||||
if len(sysMenu.Children) > 0 {
|
|
||||||
for _, menu := range sysMenu.Children {
|
|
||||||
child := sysMenuTreeSelect(menu)
|
|
||||||
t.Children = append(t.Children, child)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Children = []vo.TreeSelect{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuListByRoleId 根据角色ID查询菜单树信息 TODO
|
|
||||||
func (r *ServiceSysMenu) SelectMenuListByRoleId(roleId string) []string {
|
|
||||||
roles := r.sysRoleRepository.SelectRoleByIds([]string{roleId})
|
|
||||||
if len(roles) > 0 {
|
|
||||||
role := roles[0]
|
|
||||||
if role.RoleID == roleId {
|
|
||||||
return r.sysMenuRepository.SelectMenuListByRoleId(
|
|
||||||
role.RoleID,
|
|
||||||
role.MenuCheckStrictly == "1",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectMenuById 根据菜单ID查询信息
|
|
||||||
func (r *ServiceSysMenu) SelectMenuById(menuId string) model.SysMenu {
|
|
||||||
if menuId == "" {
|
|
||||||
return model.SysMenu{}
|
|
||||||
}
|
|
||||||
menus := r.sysMenuRepository.SelectMenuByIds([]string{menuId})
|
|
||||||
if len(menus) > 0 {
|
|
||||||
return menus[0]
|
|
||||||
}
|
|
||||||
return model.SysMenu{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasChildByMenuIdAndStatus 存在菜单子节点数量与状态
|
|
||||||
func (r *ServiceSysMenu) HasChildByMenuIdAndStatus(menuId, status string) int64 {
|
|
||||||
return r.sysMenuRepository.HasChildByMenuIdAndStatus(menuId, status)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckMenuExistRole 查询菜单是否存在角色
|
|
||||||
func (r *ServiceSysMenu) CheckMenuExistRole(menuId string) int64 {
|
|
||||||
return r.sysRoleMenuRepository.CheckMenuExistRole(menuId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertMenu 新增菜单信息
|
|
||||||
func (r *ServiceSysMenu) InsertMenu(sysMenu model.SysMenu) string {
|
|
||||||
return r.sysMenuRepository.InsertMenu(sysMenu)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateMenu 修改菜单信息
|
|
||||||
func (r *ServiceSysMenu) UpdateMenu(sysMenu model.SysMenu) int64 {
|
|
||||||
return r.sysMenuRepository.UpdateMenu(sysMenu)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteMenuById 删除菜单管理信息
|
|
||||||
func (r *ServiceSysMenu) DeleteMenuById(menuId string) int64 {
|
|
||||||
// 删除菜单与角色关联
|
|
||||||
r.sysRoleMenuRepository.DeleteMenuRole([]string{menuId})
|
|
||||||
return r.sysMenuRepository.DeleteMenuById(menuId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueMenuName 校验菜单名称是否唯一
|
|
||||||
func (r *ServiceSysMenu) CheckUniqueMenuName(menuName, parentId, menuId string) bool {
|
|
||||||
uniqueId := r.sysMenuRepository.CheckUniqueMenu(model.SysMenu{
|
|
||||||
MenuName: menuName,
|
|
||||||
ParentID: parentId,
|
|
||||||
})
|
|
||||||
if uniqueId == menuId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueMenuPath 校验路由地址是否唯一(针对目录和菜单)
|
|
||||||
func (r *ServiceSysMenu) CheckUniqueMenuPath(path, menuId string) bool {
|
|
||||||
uniqueId := r.sysMenuRepository.CheckUniqueMenu(model.SysMenu{
|
|
||||||
Path: path,
|
|
||||||
})
|
|
||||||
if uniqueId == menuId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildRouteMenus 构建前端路由所需要的菜单
|
|
||||||
func (r *ServiceSysMenu) BuildRouteMenus(sysMenus []model.SysMenu, prefix string) []vo.Router {
|
|
||||||
routers := []vo.Router{}
|
|
||||||
for _, item := range sysMenus {
|
|
||||||
router := vo.Router{}
|
|
||||||
router.Name = r.getRouteName(item)
|
|
||||||
router.Path = r.getRouterPath(item)
|
|
||||||
router.Component = r.getComponent(item)
|
|
||||||
router.Meta = r.getRouteMeta(item)
|
|
||||||
|
|
||||||
// 子项菜单 目录类型 非路径链接
|
|
||||||
cMenus := item.Children
|
|
||||||
if len(cMenus) > 0 && item.MenuType == consts.TYPE_DIR && !regular.ValidHttp(item.Path) {
|
|
||||||
// 获取重定向地址
|
|
||||||
redirectPrefix, redirectPath := r.getRouteRedirect(
|
|
||||||
cMenus,
|
|
||||||
router.Path,
|
|
||||||
prefix,
|
|
||||||
)
|
|
||||||
router.Redirect = redirectPath
|
|
||||||
// 子菜单进入递归
|
|
||||||
router.Children = r.BuildRouteMenus(cMenus, redirectPrefix)
|
|
||||||
} else if item.ParentID == "0" && item.IsFrame == "1" && item.MenuType == consts.TYPE_MENU {
|
|
||||||
// 父菜单 内部跳转 菜单类型
|
|
||||||
menuPath := "/" + item.MenuID
|
|
||||||
childPath := menuPath + r.getRouterPath(item)
|
|
||||||
children := vo.Router{
|
|
||||||
Name: r.getRouteName(item),
|
|
||||||
Path: childPath,
|
|
||||||
Component: item.Component,
|
|
||||||
Meta: r.getRouteMeta(item),
|
|
||||||
}
|
|
||||||
router.Meta.HideChildInMenu = true
|
|
||||||
router.Children = append(router.Children, children)
|
|
||||||
router.Name = item.MenuID
|
|
||||||
router.Path = menuPath
|
|
||||||
router.Redirect = childPath
|
|
||||||
router.Component = consts.COMPONENT_LAYOUT_BASIC
|
|
||||||
} else if item.ParentID == "0" && item.IsFrame == "1" && regular.ValidHttp(item.Path) {
|
|
||||||
// 父菜单 内部跳转 路径链接
|
|
||||||
menuPath := "/" + item.MenuID
|
|
||||||
childPath := menuPath + r.getRouterPath(item)
|
|
||||||
children := vo.Router{
|
|
||||||
Name: r.getRouteName(item),
|
|
||||||
Path: childPath,
|
|
||||||
Component: consts.COMPONENT_LAYOUT_LINK,
|
|
||||||
Meta: r.getRouteMeta(item),
|
|
||||||
}
|
|
||||||
router.Meta.HideChildInMenu = true
|
|
||||||
router.Children = append(router.Children, children)
|
|
||||||
router.Name = item.MenuID
|
|
||||||
router.Path = menuPath
|
|
||||||
router.Redirect = childPath
|
|
||||||
router.Component = consts.COMPONENT_LAYOUT_BASIC
|
|
||||||
}
|
|
||||||
|
|
||||||
routers = append(routers, router)
|
|
||||||
}
|
|
||||||
return routers
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRouteName 获取路由名称 路径英文首字母大写
|
|
||||||
func (r *ServiceSysMenu) getRouteName(sysMenu model.SysMenu) string {
|
|
||||||
routerName := parse.FirstUpper(sysMenu.Path)
|
|
||||||
// 路径链接
|
|
||||||
if regular.ValidHttp(sysMenu.Path) {
|
|
||||||
return routerName[:5] + "Link" + sysMenu.MenuID
|
|
||||||
}
|
|
||||||
return routerName
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRouterPath 获取路由地址
|
|
||||||
func (r *ServiceSysMenu) getRouterPath(sysMenu model.SysMenu) string {
|
|
||||||
routerPath := sysMenu.Path
|
|
||||||
|
|
||||||
// 显式路径
|
|
||||||
if routerPath == "" || strings.HasPrefix(routerPath, "/") {
|
|
||||||
return routerPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// 路径链接 内部跳转
|
|
||||||
if regular.ValidHttp(routerPath) && sysMenu.IsFrame == "1" {
|
|
||||||
routerPath = regular.Replace(routerPath, `/^http(s)?:\/\/+/`, "")
|
|
||||||
routerPath = base64.StdEncoding.EncodeToString([]byte(routerPath))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 父菜单 内部跳转
|
|
||||||
if sysMenu.ParentID == "0" && sysMenu.IsFrame == "1" {
|
|
||||||
routerPath = "/" + routerPath
|
|
||||||
}
|
|
||||||
|
|
||||||
return routerPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// getComponent 获取组件信息
|
|
||||||
func (r *ServiceSysMenu) getComponent(sysMenu model.SysMenu) string {
|
|
||||||
// 内部跳转 路径链接
|
|
||||||
if sysMenu.IsFrame == "1" && regular.ValidHttp(sysMenu.Path) {
|
|
||||||
return consts.COMPONENT_LAYOUT_LINK
|
|
||||||
}
|
|
||||||
|
|
||||||
// 非父菜单 目录类型
|
|
||||||
if sysMenu.ParentID != "0" && sysMenu.MenuType == consts.TYPE_DIR {
|
|
||||||
return consts.COMPONENT_LAYOUT_BLANK
|
|
||||||
}
|
|
||||||
|
|
||||||
// 组件路径 内部跳转 菜单类型
|
|
||||||
if sysMenu.Component != "" && sysMenu.IsFrame == "1" && sysMenu.MenuType == consts.TYPE_MENU {
|
|
||||||
// 父菜单套外层布局
|
|
||||||
if sysMenu.ParentID == "0" {
|
|
||||||
return consts.COMPONENT_LAYOUT_BASIC
|
|
||||||
}
|
|
||||||
return sysMenu.Component
|
|
||||||
}
|
|
||||||
|
|
||||||
return consts.COMPONENT_LAYOUT_BASIC
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRouteMeta 获取路由元信息
|
|
||||||
func (r *ServiceSysMenu) getRouteMeta(sysMenu model.SysMenu) vo.RouterMeta {
|
|
||||||
meta := vo.RouterMeta{}
|
|
||||||
if sysMenu.Icon == "#" {
|
|
||||||
meta.Icon = ""
|
|
||||||
} else {
|
|
||||||
meta.Icon = sysMenu.Icon
|
|
||||||
}
|
|
||||||
meta.Title = sysMenu.MenuName
|
|
||||||
meta.HideChildInMenu = false
|
|
||||||
meta.HideInMenu = sysMenu.Visible == "0"
|
|
||||||
meta.Cache = sysMenu.IsCache == "1"
|
|
||||||
meta.Target = ""
|
|
||||||
|
|
||||||
// 路径链接 非内部跳转
|
|
||||||
if regular.ValidHttp(sysMenu.Path) && sysMenu.IsFrame == "0" {
|
|
||||||
meta.Target = "_blank"
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRouteRedirect 获取路由重定向地址(针对目录)
|
|
||||||
//
|
|
||||||
// cMenus 子菜单数组
|
|
||||||
// routerPath 当前菜单路径
|
|
||||||
// prefix 菜单重定向路径前缀
|
|
||||||
func (r *ServiceSysMenu) getRouteRedirect(cMenus []model.SysMenu, routerPath string, prefix string) (string, string) {
|
|
||||||
redirectPath := ""
|
|
||||||
|
|
||||||
// 重定向为首个显示并启用的子菜单
|
|
||||||
var firstChild *model.SysMenu
|
|
||||||
for _, item := range cMenus {
|
|
||||||
if item.IsFrame == "1" && item.Visible == "1" {
|
|
||||||
firstChild = &item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查内嵌隐藏菜单是否可做重定向
|
|
||||||
if firstChild == nil {
|
|
||||||
for _, item := range cMenus {
|
|
||||||
if item.IsFrame == "1" && item.Visible == "1" && strings.Contains(item.Path, consts.PATH_INLINE) {
|
|
||||||
firstChild = &item
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if firstChild != nil {
|
|
||||||
firstChildPath := r.getRouterPath(*firstChild)
|
|
||||||
if strings.HasPrefix(firstChildPath, "/") {
|
|
||||||
redirectPath = firstChildPath
|
|
||||||
} else {
|
|
||||||
// 拼接追加路径
|
|
||||||
if !strings.HasPrefix(routerPath, "/") {
|
|
||||||
prefix += "/"
|
|
||||||
}
|
|
||||||
prefix = prefix + routerPath
|
|
||||||
redirectPath = prefix + "/" + firstChildPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return prefix, redirectPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseDataToTree 将数据解析为树结构,构建前端所需要下拉树结构
|
|
||||||
func (r *ServiceSysMenu) parseDataToTree(sysMenus []model.SysMenu) []model.SysMenu {
|
|
||||||
// 节点分组
|
|
||||||
nodesMap := make(map[string][]model.SysMenu)
|
|
||||||
// 节点id
|
|
||||||
treeIds := []string{}
|
|
||||||
// 树节点
|
|
||||||
tree := []model.SysMenu{}
|
|
||||||
|
|
||||||
for _, item := range sysMenus {
|
|
||||||
parentID := item.ParentID
|
|
||||||
// 分组
|
|
||||||
mapItem, ok := nodesMap[parentID]
|
|
||||||
if !ok {
|
|
||||||
mapItem = []model.SysMenu{}
|
|
||||||
}
|
|
||||||
mapItem = append(mapItem, item)
|
|
||||||
nodesMap[parentID] = mapItem
|
|
||||||
// 记录节点ID
|
|
||||||
treeIds = append(treeIds, item.MenuID)
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, value := range nodesMap {
|
|
||||||
// 选择不是节点ID的作为树节点
|
|
||||||
found := false
|
|
||||||
for _, id := range treeIds {
|
|
||||||
if id == key {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
tree = append(tree, value...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, node := range tree {
|
|
||||||
iN := r.parseDataToTreeComponet(node, &nodesMap)
|
|
||||||
tree[i] = iN
|
|
||||||
}
|
|
||||||
|
|
||||||
return tree
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseDataToTreeComponet 递归函数处理子节点
|
|
||||||
func (r *ServiceSysMenu) parseDataToTreeComponet(node model.SysMenu, nodesMap *map[string][]model.SysMenu) model.SysMenu {
|
|
||||||
id := node.MenuID
|
|
||||||
children, ok := (*nodesMap)[id]
|
|
||||||
if ok {
|
|
||||||
node.Children = children
|
|
||||||
}
|
|
||||||
if len(node.Children) > 0 {
|
|
||||||
for i, child := range node.Children {
|
|
||||||
icN := r.parseDataToTreeComponet(child, nodesMap)
|
|
||||||
node.Children[i] = icN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
@@ -1,368 +0,0 @@
|
|||||||
package sysrole
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/features/sys_role/model"
|
|
||||||
"be.ems/features/sys_role/service"
|
|
||||||
userService "be.ems/features/sys_user/service"
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/core/vo/result"
|
|
||||||
"be.ems/lib/midware"
|
|
||||||
"be.ems/lib/services"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 角色接口添加到路由
|
|
||||||
func Routers() []services.RouterItem {
|
|
||||||
// 实例化控制层 SysRoleApi 结构体
|
|
||||||
var apis = &SysRoleApi{
|
|
||||||
sysRoleService: service.NewServiceSysRole,
|
|
||||||
sysUserService: userService.NewServiceSysUser,
|
|
||||||
}
|
|
||||||
|
|
||||||
rs := [...]services.RouterItem{
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/roles",
|
|
||||||
Handler: apis.List,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/role/{roleId}",
|
|
||||||
Handler: apis.Info,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "POST",
|
|
||||||
Pattern: "/role",
|
|
||||||
Handler: apis.Add,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "PUT",
|
|
||||||
Pattern: "/role",
|
|
||||||
Handler: apis.Edit,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "DELETE",
|
|
||||||
Pattern: "/role/{roleIds}",
|
|
||||||
Handler: apis.Remove,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "PUT",
|
|
||||||
Pattern: "/role/changeStatus",
|
|
||||||
Handler: apis.Status,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/role/authUser/allocatedList",
|
|
||||||
Handler: apis.AuthUserAllocatedList,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "PUT",
|
|
||||||
Pattern: "/role/authUser/checked",
|
|
||||||
Handler: apis.AuthUserChecked,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
// 添加更多的 Router 对象...
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成两组前缀路由
|
|
||||||
rsPrefix := []services.RouterItem{}
|
|
||||||
for _, v := range rs {
|
|
||||||
path := "/roleManage/{apiVersion}" + v.Pattern
|
|
||||||
// 固定前缀
|
|
||||||
v.Pattern = config.DefaultUriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
// 可配置
|
|
||||||
v.Pattern = config.UriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
}
|
|
||||||
return rsPrefix
|
|
||||||
}
|
|
||||||
|
|
||||||
// // 实例化控制层 SysRoleApi 结构体
|
|
||||||
// var NewSysRole = &SysRoleApi{
|
|
||||||
// sysRoleService: sysrole.NewServiceSysRole,
|
|
||||||
// sysUserService: sysuser.NewServiceSysUser,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 角色信息
|
|
||||||
//
|
|
||||||
// PATH /roleManage
|
|
||||||
type SysRoleApi struct {
|
|
||||||
// 角色服务
|
|
||||||
sysRoleService *service.ServiceSysRole
|
|
||||||
// 用户服务
|
|
||||||
sysUserService *userService.ServiceSysUser
|
|
||||||
}
|
|
||||||
|
|
||||||
// 角色列表
|
|
||||||
//
|
|
||||||
// GET /list
|
|
||||||
func (s *SysRoleApi) List(w http.ResponseWriter, r *http.Request) {
|
|
||||||
querys := ctx.QueryMap(r)
|
|
||||||
data := s.sysRoleService.SelectRolePage(querys)
|
|
||||||
ctx.JSON(w, 200, result.Ok(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 角色信息详情
|
|
||||||
//
|
|
||||||
// GET /:roleId
|
|
||||||
func (s *SysRoleApi) Info(w http.ResponseWriter, r *http.Request) {
|
|
||||||
roleId := ctx.Param(r, "roleId")
|
|
||||||
if roleId == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data := s.sysRoleService.SelectRoleById(roleId)
|
|
||||||
if data.RoleID == roleId {
|
|
||||||
ctx.JSON(w, 200, result.OkData(data))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 角色信息新增
|
|
||||||
//
|
|
||||||
// POST /
|
|
||||||
func (s *SysRoleApi) Add(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body model.SysRole
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.RoleID != "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断角色名称是否唯一
|
|
||||||
uniqueRoleName := s.sysRoleService.CheckUniqueRoleName(body.RoleName, "")
|
|
||||||
if !uniqueRoleName {
|
|
||||||
msg := fmt.Sprintf("[%s] Role name already exists", body.RoleName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断角色键值是否唯一
|
|
||||||
uniqueRoleKey := s.sysRoleService.CheckUniqueRoleKey(body.RoleKey, "")
|
|
||||||
if !uniqueRoleKey {
|
|
||||||
msg := fmt.Sprintf("[%s] The role key value already exists", body.RoleName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body.CreateBy = ctx.LoginUserToUserName(r)
|
|
||||||
insertId := s.sysRoleService.InsertRole(body)
|
|
||||||
if insertId != "" {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 角色信息修改
|
|
||||||
//
|
|
||||||
// PUT /
|
|
||||||
func (s *SysRoleApi) Edit(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body model.SysRole
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.RoleID == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否管理员角色
|
|
||||||
if body.RoleID == "1" {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("Operation of administrator role is not allowed"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否存在
|
|
||||||
role := s.sysRoleService.SelectRoleById(body.RoleID)
|
|
||||||
if role.RoleID != body.RoleID {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access role data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断角色名称是否唯一
|
|
||||||
uniqueRoleName := s.sysRoleService.CheckUniqueRoleName(body.RoleName, body.RoleID)
|
|
||||||
if !uniqueRoleName {
|
|
||||||
msg := fmt.Sprintf("[%s] Role name already exists", body.RoleName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断角色键值是否唯一
|
|
||||||
uniqueRoleKey := s.sysRoleService.CheckUniqueRoleKey(body.RoleKey, body.RoleID)
|
|
||||||
if !uniqueRoleKey {
|
|
||||||
msg := fmt.Sprintf("[%s] The role key value already exists", body.RoleName)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body.UpdateBy = ctx.LoginUserToUserName(r)
|
|
||||||
rows := s.sysRoleService.UpdateRole(body)
|
|
||||||
if rows > 0 {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 角色信息删除
|
|
||||||
//
|
|
||||||
// DELETE /:roleIds
|
|
||||||
func (s *SysRoleApi) Remove(w http.ResponseWriter, r *http.Request) {
|
|
||||||
roleIds := ctx.Param(r, "roleIds")
|
|
||||||
if roleIds == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 处理字符转id数组后去重
|
|
||||||
ids := strings.Split(roleIds, ",")
|
|
||||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
|
||||||
if len(uniqueIDs) <= 0 {
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 检查是否管理员角色
|
|
||||||
for _, id := range uniqueIDs {
|
|
||||||
if id == "1" {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("Operation of administrator role is not allowed"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rows, err := s.sysRoleService.DeleteRoleByIds(uniqueIDs)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
msg := fmt.Sprintf("Successfully deleted: %d", rows)
|
|
||||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 角色状态变更
|
|
||||||
//
|
|
||||||
// PUT /changeStatus
|
|
||||||
func (s *SysRoleApi) Status(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body struct {
|
|
||||||
// 角色ID
|
|
||||||
RoleID string `json:"roleId" binding:"required"`
|
|
||||||
// 状态
|
|
||||||
Status string `json:"status" binding:"required"`
|
|
||||||
}
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否管理员角色
|
|
||||||
if body.RoleID == "1" {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("Operation of administrator role is not allowed"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否存在
|
|
||||||
role := s.sysRoleService.SelectRoleById(body.RoleID)
|
|
||||||
if role.RoleID != body.RoleID {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access role data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 与旧值相等不变更
|
|
||||||
if role.Status == body.Status {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("Change status equals old value!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新状态不刷新缓存
|
|
||||||
userName := ctx.LoginUserToUserName(r)
|
|
||||||
SysRoleApi := model.SysRole{
|
|
||||||
RoleID: body.RoleID,
|
|
||||||
Status: body.Status,
|
|
||||||
UpdateBy: userName,
|
|
||||||
}
|
|
||||||
rows := s.sysRoleService.UpdateRole(SysRoleApi)
|
|
||||||
if rows > 0 {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 角色分配用户列表
|
|
||||||
//
|
|
||||||
// GET /authUser/allocatedList
|
|
||||||
func (s *SysRoleApi) AuthUserAllocatedList(w http.ResponseWriter, r *http.Request) {
|
|
||||||
querys := ctx.QueryMap(r)
|
|
||||||
roleId, ok := querys["roleId"]
|
|
||||||
if !ok || roleId == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否存在
|
|
||||||
role := s.sysRoleService.SelectRoleById(roleId.(string))
|
|
||||||
if role.RoleID != roleId {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access role data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
data := s.sysUserService.SelectAllocatedPage(querys)
|
|
||||||
ctx.JSON(w, 200, result.Ok(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 角色分配选择授权
|
|
||||||
//
|
|
||||||
// PUT /authUser/checked
|
|
||||||
func (s *SysRoleApi) AuthUserChecked(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body struct {
|
|
||||||
// 角色ID
|
|
||||||
RoleID string `json:"roleId" binding:"required"`
|
|
||||||
// 用户ID组
|
|
||||||
UserIDs string `json:"userIds" binding:"required"`
|
|
||||||
// 选择操作 添加true 取消false
|
|
||||||
Checked bool `json:"checked"`
|
|
||||||
}
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理字符转id数组后去重
|
|
||||||
ids := strings.Split(body.UserIDs, ",")
|
|
||||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
|
||||||
if len(uniqueIDs) <= 0 {
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否存在
|
|
||||||
role := s.sysRoleService.SelectRoleById(body.RoleID)
|
|
||||||
if role.RoleID != body.RoleID {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access role data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var rows int64
|
|
||||||
if body.Checked {
|
|
||||||
rows = s.sysRoleService.InsertAuthUsers(body.RoleID, uniqueIDs)
|
|
||||||
} else {
|
|
||||||
rows = s.sysRoleService.DeleteAuthUsers(body.RoleID, uniqueIDs)
|
|
||||||
}
|
|
||||||
if rows > 0 {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
// SysRole 角色对象 sys_role
|
|
||||||
type SysRole struct {
|
|
||||||
// 角色ID
|
|
||||||
RoleID string `json:"roleId"`
|
|
||||||
// 角色名称
|
|
||||||
RoleName string `json:"roleName" binding:"required"`
|
|
||||||
// 角色键值
|
|
||||||
RoleKey string `json:"roleKey" binding:"required"`
|
|
||||||
// 显示顺序
|
|
||||||
RoleSort int `json:"roleSort"`
|
|
||||||
// 菜单树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示)
|
|
||||||
MenuCheckStrictly string `json:"menuCheckStrictly"`
|
|
||||||
// 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示)
|
|
||||||
DeptCheckStrictly string `json:"deptCheckStrictly"`
|
|
||||||
// 角色状态(0停用 1正常)
|
|
||||||
Status string `json:"status"`
|
|
||||||
// 删除标志(0代表存在 1代表删除)
|
|
||||||
DelFlag string `json:"delFlag"`
|
|
||||||
// 创建者
|
|
||||||
CreateBy string `json:"createBy"`
|
|
||||||
// 创建时间
|
|
||||||
CreateTime int64 `json:"createTime"`
|
|
||||||
// 更新者
|
|
||||||
UpdateBy string `json:"updateBy"`
|
|
||||||
// 更新时间
|
|
||||||
UpdateTime int64 `json:"updateTime"`
|
|
||||||
// 备注
|
|
||||||
Remark string `json:"remark"`
|
|
||||||
|
|
||||||
// ====== 非数据库字段属性 ======
|
|
||||||
|
|
||||||
// 菜单组
|
|
||||||
MenuIds []string `json:"menuIds,omitempty"`
|
|
||||||
// 部门组(数据权限)
|
|
||||||
DeptIds []string `json:"deptIds,omitempty"`
|
|
||||||
}
|
|
||||||
@@ -1,362 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/features/sys_role/model"
|
|
||||||
"be.ems/lib/core/datasource"
|
|
||||||
"be.ems/lib/core/utils/date"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 RepoSysRole 结构体
|
|
||||||
var NewRepoSysRole = &RepoSysRole{
|
|
||||||
selectSql: `select distinct
|
|
||||||
r.role_id, r.role_name, r.role_key, r.role_sort, r.menu_check_strictly,
|
|
||||||
r.dept_check_strictly, r.status, r.del_flag, r.create_time, r.remark
|
|
||||||
from sys_role r
|
|
||||||
left join sys_user_role ur on ur.role_id = r.role_id
|
|
||||||
left join user u on u.id = ur.user_id`,
|
|
||||||
|
|
||||||
resultMap: map[string]string{
|
|
||||||
"role_id": "RoleID",
|
|
||||||
"role_name": "RoleName",
|
|
||||||
"role_key": "RoleKey",
|
|
||||||
"role_sort": "RoleSort",
|
|
||||||
"menu_check_strictly": "MenuCheckStrictly",
|
|
||||||
"dept_check_strictly": "DeptCheckStrictly",
|
|
||||||
"status": "Status",
|
|
||||||
"del_flag": "DelFlag",
|
|
||||||
"create_by": "CreateBy",
|
|
||||||
"create_time": "CreateTime",
|
|
||||||
"update_by": "UpdateBy",
|
|
||||||
"update_time": "UpdateTime",
|
|
||||||
"remark": "Remark",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepoSysRole 角色表 数据层处理
|
|
||||||
type RepoSysRole struct {
|
|
||||||
// 查询视图对象SQL
|
|
||||||
selectSql string
|
|
||||||
// 结果字段与实体映射
|
|
||||||
resultMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
|
||||||
func (r *RepoSysRole) convertResultRows(rows []map[string]any) []model.SysRole {
|
|
||||||
arr := make([]model.SysRole, 0)
|
|
||||||
for _, row := range rows {
|
|
||||||
sysRole := model.SysRole{}
|
|
||||||
for key, value := range row {
|
|
||||||
if keyMapper, ok := r.resultMap[key]; ok {
|
|
||||||
datasource.SetFieldValue(&sysRole, keyMapper, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr = append(arr, sysRole)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectRolePage 根据条件分页查询角色数据
|
|
||||||
func (r *RepoSysRole) SelectRolePage(query map[string]any) map[string]any {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if v, ok := query["roleId"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "r.role_id = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["roleName"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "r.role_name like concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["roleKey"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "r.role_key like concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["status"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "r.status = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
beginTime, ok := query["beginTime"]
|
|
||||||
if !ok {
|
|
||||||
beginTime, ok = query["params[beginTime]"]
|
|
||||||
}
|
|
||||||
if ok && beginTime != "" {
|
|
||||||
conditions = append(conditions, "r.create_time >= ?")
|
|
||||||
beginDate := date.ParseStrToDate(beginTime.(string), date.YYYY_MM_DD)
|
|
||||||
params = append(params, beginDate.UnixMilli())
|
|
||||||
}
|
|
||||||
endTime, ok := query["endTime"]
|
|
||||||
if !ok {
|
|
||||||
endTime, ok = query["params[endTime]"]
|
|
||||||
}
|
|
||||||
if ok && endTime != "" {
|
|
||||||
conditions = append(conditions, "r.create_time <= ?")
|
|
||||||
endDate := date.ParseStrToDate(endTime.(string), date.YYYY_MM_DD)
|
|
||||||
params = append(params, endDate.UnixMilli())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := " where r.del_flag = '0' "
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " and " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
totalSql := `select count(distinct r.role_id) as 'total' from sys_role r
|
|
||||||
left join sys_user_role ur on ur.role_id = r.role_id
|
|
||||||
left join user u on u.id = ur.user_id`
|
|
||||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("total err => %v", err)
|
|
||||||
}
|
|
||||||
total := parse.Number(totalRows[0]["total"])
|
|
||||||
if total == 0 {
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": []model.SysRole{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
|
||||||
pageSql := " order by r.role_sort asc limit ?,? "
|
|
||||||
params = append(params, pageNum*pageSize)
|
|
||||||
params = append(params, pageSize)
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + pageSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
rows := r.convertResultRows(results)
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": rows,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectRoleList 根据条件查询角色数据
|
|
||||||
func (r *RepoSysRole) SelectRoleList(sysRole model.SysRole) []model.SysRole {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysRole.RoleID != "" {
|
|
||||||
conditions = append(conditions, "r.role_id = ?")
|
|
||||||
params = append(params, sysRole.RoleID)
|
|
||||||
}
|
|
||||||
if sysRole.RoleKey != "" {
|
|
||||||
conditions = append(conditions, "r.role_key like concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, sysRole.RoleKey)
|
|
||||||
}
|
|
||||||
if sysRole.RoleName != "" {
|
|
||||||
conditions = append(conditions, "r.role_name like concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, sysRole.RoleName)
|
|
||||||
}
|
|
||||||
if sysRole.Status != "" {
|
|
||||||
conditions = append(conditions, "r.status = ?")
|
|
||||||
params = append(params, sysRole.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := " where r.del_flag = '0' "
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " and " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
orderSql := " order by r.role_sort"
|
|
||||||
querySql := r.selectSql + whereSql + orderSql
|
|
||||||
rows, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysRole{}
|
|
||||||
}
|
|
||||||
return r.convertResultRows(rows)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectRoleListByUserId 根据用户ID获取角色选择框列表
|
|
||||||
func (r *RepoSysRole) SelectRoleListByUserId(userId string) []model.SysRole {
|
|
||||||
querySql := r.selectSql + " where r.del_flag = '0' and ur.user_id = ?"
|
|
||||||
results, err := datasource.RawDB("", querySql, []any{userId})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysRole{}
|
|
||||||
}
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectRoleByIds 通过角色ID查询角色
|
|
||||||
func (r *RepoSysRole) SelectRoleByIds(roleIds []string) []model.SysRole {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(roleIds))
|
|
||||||
querySql := r.selectSql + " where r.role_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(roleIds)
|
|
||||||
results, err := datasource.RawDB("", querySql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []model.SysRole{}
|
|
||||||
}
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateRole 修改角色信息
|
|
||||||
func (r *RepoSysRole) UpdateRole(sysRole model.SysRole) int64 {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysRole.RoleName != "" {
|
|
||||||
params["role_name"] = sysRole.RoleName
|
|
||||||
}
|
|
||||||
if sysRole.RoleKey != "" {
|
|
||||||
params["role_key"] = sysRole.RoleKey
|
|
||||||
}
|
|
||||||
if sysRole.RoleSort > 0 {
|
|
||||||
params["role_sort"] = sysRole.RoleSort
|
|
||||||
}
|
|
||||||
if sysRole.MenuCheckStrictly != "" {
|
|
||||||
params["menu_check_strictly"] = sysRole.MenuCheckStrictly
|
|
||||||
}
|
|
||||||
if sysRole.DeptCheckStrictly != "" {
|
|
||||||
params["dept_check_strictly"] = sysRole.DeptCheckStrictly
|
|
||||||
}
|
|
||||||
if sysRole.Status != "" {
|
|
||||||
params["status"] = sysRole.Status
|
|
||||||
}
|
|
||||||
if sysRole.Remark != "" {
|
|
||||||
params["remark"] = sysRole.Remark
|
|
||||||
}
|
|
||||||
if sysRole.UpdateBy != "" {
|
|
||||||
params["update_by"] = sysRole.UpdateBy
|
|
||||||
params["update_time"] = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, values := datasource.KeyValueByUpdate(params)
|
|
||||||
sql := "update sys_role set " + strings.Join(keys, ",") + " where role_id = ?"
|
|
||||||
|
|
||||||
// 执行更新
|
|
||||||
values = append(values, sysRole.RoleID)
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update row : %v", err.Error())
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertRole 新增角色信息
|
|
||||||
func (r *RepoSysRole) InsertRole(sysRole model.SysRole) string {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysRole.RoleID != "" {
|
|
||||||
params["role_id"] = sysRole.RoleID
|
|
||||||
}
|
|
||||||
if sysRole.RoleName != "" {
|
|
||||||
params["role_name"] = sysRole.RoleName
|
|
||||||
}
|
|
||||||
if sysRole.RoleKey != "" {
|
|
||||||
params["role_key"] = sysRole.RoleKey
|
|
||||||
}
|
|
||||||
if sysRole.RoleSort > 0 {
|
|
||||||
params["role_sort"] = sysRole.RoleSort
|
|
||||||
}
|
|
||||||
if sysRole.MenuCheckStrictly != "" {
|
|
||||||
params["menu_check_strictly"] = sysRole.MenuCheckStrictly
|
|
||||||
}
|
|
||||||
if sysRole.DeptCheckStrictly != "" {
|
|
||||||
params["dept_check_strictly"] = sysRole.DeptCheckStrictly
|
|
||||||
}
|
|
||||||
if sysRole.Status != "" {
|
|
||||||
params["status"] = sysRole.Status
|
|
||||||
}
|
|
||||||
if sysRole.Remark != "" {
|
|
||||||
params["remark"] = sysRole.Remark
|
|
||||||
}
|
|
||||||
if sysRole.CreateBy != "" {
|
|
||||||
params["create_by"] = sysRole.CreateBy
|
|
||||||
params["create_time"] = time.Now().UnixMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
|
||||||
sql := "insert into sys_role (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
|
||||||
|
|
||||||
// 执行插入
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
insertId, err := results.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return fmt.Sprint(insertId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRoleByIds 批量删除角色信息
|
|
||||||
func (r *RepoSysRole) DeleteRoleByIds(roleIds []string) int64 {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(roleIds))
|
|
||||||
sql := "update sys_role set del_flag = '1' where role_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(roleIds)
|
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueRole 校验角色是否唯一
|
|
||||||
func (r *RepoSysRole) CheckUniqueRole(sysRole model.SysRole) string {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysRole.RoleName != "" {
|
|
||||||
conditions = append(conditions, "r.role_name = ?")
|
|
||||||
params = append(params, sysRole.RoleName)
|
|
||||||
}
|
|
||||||
if sysRole.RoleKey != "" {
|
|
||||||
conditions = append(conditions, "r.role_key = ?")
|
|
||||||
params = append(params, sysRole.RoleKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
} else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := "select role_id as 'str' from sys_role r " + whereSql + " and r.del_flag = '0' limit 1"
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err %v", err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return fmt.Sprint(results[0]["str"])
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"be.ems/features/sys_role/model"
|
|
||||||
sysrolemenu "be.ems/features/sys_role_menu"
|
|
||||||
sysuserrole "be.ems/features/sys_user_role"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 ServiceSysRole 结构体
|
|
||||||
var NewServiceSysRole = &ServiceSysRole{
|
|
||||||
sysRoleRepository: NewRepoSysRole,
|
|
||||||
sysUserRoleRepository: sysuserrole.NewRepoSysUserRole,
|
|
||||||
sysRoleMenuRepository: sysrolemenu.NewRepoSysRoleMenu,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceSysRole 角色 服务层处理
|
|
||||||
type ServiceSysRole struct {
|
|
||||||
// 角色服务
|
|
||||||
sysRoleRepository *RepoSysRole
|
|
||||||
// 用户与角色关联服务
|
|
||||||
sysUserRoleRepository *sysuserrole.RepoSysUserRole
|
|
||||||
// 角色与菜单关联服务
|
|
||||||
sysRoleMenuRepository *sysrolemenu.RepoSysRoleMenu
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectRolePage 根据条件分页查询角色数据
|
|
||||||
func (r *ServiceSysRole) SelectRolePage(query map[string]any) map[string]any {
|
|
||||||
return r.sysRoleRepository.SelectRolePage(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectRoleList 根据条件查询角色数据
|
|
||||||
func (r *ServiceSysRole) SelectRoleList(sysRole model.SysRole) []model.SysRole {
|
|
||||||
return r.sysRoleRepository.SelectRoleList(sysRole)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectRoleListByUserId 根据用户ID获取角色选择框列表
|
|
||||||
func (r *ServiceSysRole) SelectRoleListByUserId(userId string) []model.SysRole {
|
|
||||||
return r.sysRoleRepository.SelectRoleListByUserId(userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectRoleById 通过角色ID查询角色
|
|
||||||
func (r *ServiceSysRole) SelectRoleById(roleId string) model.SysRole {
|
|
||||||
if roleId == "" {
|
|
||||||
return model.SysRole{}
|
|
||||||
}
|
|
||||||
posts := r.sysRoleRepository.SelectRoleByIds([]string{roleId})
|
|
||||||
if len(posts) > 0 {
|
|
||||||
return posts[0]
|
|
||||||
}
|
|
||||||
return model.SysRole{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateRole 修改角色信息
|
|
||||||
func (r *ServiceSysRole) UpdateRole(sysRole model.SysRole) int64 {
|
|
||||||
rows := r.sysRoleRepository.UpdateRole(sysRole)
|
|
||||||
if rows > 0 {
|
|
||||||
// 删除角色与菜单关联
|
|
||||||
r.sysRoleMenuRepository.DeleteRoleMenu([]string{sysRole.RoleID})
|
|
||||||
if len(sysRole.MenuIds) > 0 {
|
|
||||||
r.insertRoleMenu(sysRole.RoleID, sysRole.MenuIds)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertRole 新增角色信息
|
|
||||||
func (r *ServiceSysRole) InsertRole(sysRole model.SysRole) string {
|
|
||||||
insertId := r.sysRoleRepository.InsertRole(sysRole)
|
|
||||||
if insertId != "" && len(sysRole.MenuIds) > 0 {
|
|
||||||
r.insertRoleMenu(insertId, sysRole.MenuIds)
|
|
||||||
}
|
|
||||||
return insertId
|
|
||||||
}
|
|
||||||
|
|
||||||
// insertRoleMenu 新增角色菜单信息
|
|
||||||
func (r *ServiceSysRole) insertRoleMenu(roleId string, menuIds []string) int64 {
|
|
||||||
if roleId == "" || len(menuIds) <= 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
sysRoleMenus := []sysrolemenu.SysRoleMenu{}
|
|
||||||
for _, menuId := range menuIds {
|
|
||||||
if menuId == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sysRoleMenus = append(sysRoleMenus, sysrolemenu.NewSysRoleMenu(roleId, menuId))
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.sysRoleMenuRepository.BatchRoleMenu(sysRoleMenus)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRoleByIds 批量删除角色信息
|
|
||||||
func (r *ServiceSysRole) DeleteRoleByIds(roleIds []string) (int64, error) {
|
|
||||||
// 检查是否存在
|
|
||||||
roles := r.sysRoleRepository.SelectRoleByIds(roleIds)
|
|
||||||
if len(roles) <= 0 {
|
|
||||||
return 0, errors.New("no permission to access role data")
|
|
||||||
}
|
|
||||||
for _, role := range roles {
|
|
||||||
// 检查是否为已删除
|
|
||||||
if role.DelFlag == "1" {
|
|
||||||
return 0, errors.New(role.RoleID + " The character information has been deleted")
|
|
||||||
}
|
|
||||||
// 检查分配用户
|
|
||||||
userCount := r.sysUserRoleRepository.CountUserRoleByRoleId(role.RoleID)
|
|
||||||
if userCount > 0 {
|
|
||||||
msg := fmt.Sprintf("[%s] has been assigned to a user and cannot be deleted", role.RoleName)
|
|
||||||
return 0, errors.New(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(roles) == len(roleIds) {
|
|
||||||
// 删除角色与菜单关联
|
|
||||||
r.sysRoleMenuRepository.DeleteRoleMenu(roleIds)
|
|
||||||
rows := r.sysRoleRepository.DeleteRoleByIds(roleIds)
|
|
||||||
return rows, nil
|
|
||||||
}
|
|
||||||
return 0, errors.New("failed to delete role information")
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueRoleName 校验角色名称是否唯一
|
|
||||||
func (r *ServiceSysRole) CheckUniqueRoleName(roleName, roleId string) bool {
|
|
||||||
uniqueId := r.sysRoleRepository.CheckUniqueRole(model.SysRole{
|
|
||||||
RoleName: roleName,
|
|
||||||
})
|
|
||||||
if uniqueId == roleId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueRoleKey 校验角色权限是否唯一
|
|
||||||
func (r *ServiceSysRole) CheckUniqueRoleKey(roleKey, roleId string) bool {
|
|
||||||
uniqueId := r.sysRoleRepository.CheckUniqueRole(model.SysRole{
|
|
||||||
RoleKey: roleKey,
|
|
||||||
})
|
|
||||||
if uniqueId == roleId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteAuthUsers 批量取消授权用户角色
|
|
||||||
func (r *ServiceSysRole) DeleteAuthUsers(roleId string, userIds []string) int64 {
|
|
||||||
return r.sysUserRoleRepository.DeleteUserRoleByRoleId(roleId, userIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertAuthUsers 批量新增授权用户角色
|
|
||||||
func (r *ServiceSysRole) InsertAuthUsers(roleId string, userIds []string) int64 {
|
|
||||||
if roleId == "" || len(userIds) <= 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
sysUserRoles := []sysuserrole.SysUserRole{}
|
|
||||||
for _, userId := range userIds {
|
|
||||||
if userId == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sysUserRoles = append(sysUserRoles, sysuserrole.NewSysUserRole(userId, roleId))
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.sysUserRoleRepository.BatchUserRole(sysUserRoles)
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package sysrolemenu
|
|
||||||
|
|
||||||
// SysRoleMenu 角色和菜单关联对象 sys_role_menu
|
|
||||||
type SysRoleMenu struct {
|
|
||||||
RoleID string `json:"roleId"` // 角色ID
|
|
||||||
MenuID string `json:"menuId"` // 菜单ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSysRoleMenu 创建角色和菜单关联对象的构造函数
|
|
||||||
func NewSysRoleMenu(roleID string, menuID string) SysRoleMenu {
|
|
||||||
return SysRoleMenu{
|
|
||||||
RoleID: roleID,
|
|
||||||
MenuID: menuID,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
package sysrolemenu
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/lib/core/datasource"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 RepoSysRoleMenu 结构体
|
|
||||||
var NewRepoSysRoleMenu = &RepoSysRoleMenu{}
|
|
||||||
|
|
||||||
// RepoSysRoleMenu 角色与菜单关联表 数据层处理
|
|
||||||
type RepoSysRoleMenu struct{}
|
|
||||||
|
|
||||||
// CheckMenuExistRole 查询菜单分配给角色使用数量
|
|
||||||
func (r *RepoSysRoleMenu) CheckMenuExistRole(menuId string) int64 {
|
|
||||||
querySql := "select count(1) as 'total' from sys_role_menu where menu_id = ?"
|
|
||||||
results, err := datasource.RawDB("", querySql, []any{menuId})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return parse.Number(results[0]["total"])
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRoleMenu 批量删除角色和菜单关联
|
|
||||||
func (r *RepoSysRoleMenu) DeleteRoleMenu(roleIds []string) int64 {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(roleIds))
|
|
||||||
sql := "delete from sys_role_menu where role_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(roleIds)
|
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteMenuRole 批量删除菜单和角色关联
|
|
||||||
func (r *RepoSysRoleMenu) DeleteMenuRole(menuIds []string) int64 {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(menuIds))
|
|
||||||
sql := "delete from sys_role_menu where menu_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(menuIds)
|
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchRoleMenu 批量新增角色菜单信息
|
|
||||||
func (r *RepoSysRoleMenu) BatchRoleMenu(sysRoleMenus []SysRoleMenu) int64 {
|
|
||||||
keyValues := make([]string, 0)
|
|
||||||
for _, item := range sysRoleMenus {
|
|
||||||
keyValues = append(keyValues, fmt.Sprintf("(%s,%s)", item.RoleID, item.MenuID))
|
|
||||||
}
|
|
||||||
sql := "insert into sys_role_menu(role_id, menu_id) values " + strings.Join(keyValues, ",")
|
|
||||||
results, err := datasource.ExecDB("", sql, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
insertId, err := results.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return insertId
|
|
||||||
}
|
|
||||||
@@ -1,323 +0,0 @@
|
|||||||
package sysuser
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
sysRoleModel "be.ems/features/sys_role/model"
|
|
||||||
sysRoleService "be.ems/features/sys_role/service"
|
|
||||||
sysUserModel "be.ems/features/sys_user/model"
|
|
||||||
"be.ems/features/sys_user/service"
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/core/vo/result"
|
|
||||||
"be.ems/lib/midware"
|
|
||||||
"be.ems/lib/services"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
srcConfig "be.ems/src/framework/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 用户接口添加到路由
|
|
||||||
func Routers() []services.RouterItem {
|
|
||||||
// 实例化控制层 SysUserApi 结构体
|
|
||||||
var apis = &SysUserApi{
|
|
||||||
sysUserService: service.NewServiceSysUser,
|
|
||||||
sysRoleService: sysRoleService.NewServiceSysRole,
|
|
||||||
}
|
|
||||||
|
|
||||||
rs := [...]services.RouterItem{
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/users",
|
|
||||||
Handler: apis.List,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "GET",
|
|
||||||
Pattern: "/user/{userId}",
|
|
||||||
Handler: apis.Info,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "POST",
|
|
||||||
Pattern: "/user",
|
|
||||||
Handler: apis.Add,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "PUT",
|
|
||||||
Pattern: "/user",
|
|
||||||
Handler: apis.Edit,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Method: "DELETE",
|
|
||||||
Pattern: "/user/{userIds}",
|
|
||||||
Handler: apis.Remove,
|
|
||||||
Middleware: midware.Authorize(nil),
|
|
||||||
},
|
|
||||||
// 添加更多的 Router 对象...
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成两组前缀路由
|
|
||||||
rsPrefix := []services.RouterItem{}
|
|
||||||
for _, v := range rs {
|
|
||||||
path := "/userManage/{apiVersion}" + v.Pattern
|
|
||||||
// 固定前缀
|
|
||||||
v.Pattern = config.DefaultUriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
// 可配置
|
|
||||||
v.Pattern = config.UriPrefix + path
|
|
||||||
rsPrefix = append(rsPrefix, v)
|
|
||||||
}
|
|
||||||
return rsPrefix
|
|
||||||
}
|
|
||||||
|
|
||||||
// // 实例化控制层 SysUserApi 结构体
|
|
||||||
// var NewSysUser = &SysUserApi{
|
|
||||||
// sysUserService: service.NewSysUserImpl,
|
|
||||||
// sysRoleService: service.NewSysRoleImpl,
|
|
||||||
// sysPostService: service.NewSysPostImpl,
|
|
||||||
// sysDictDataService: service.NewSysDictDataImpl,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 用户信息
|
|
||||||
//
|
|
||||||
// PATH /system/user
|
|
||||||
type SysUserApi struct {
|
|
||||||
// 用户服务
|
|
||||||
sysUserService *service.ServiceSysUser
|
|
||||||
// 角色服务
|
|
||||||
sysRoleService *sysRoleService.ServiceSysRole
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户信息列表
|
|
||||||
//
|
|
||||||
// GET /list
|
|
||||||
func (s *SysUserApi) List(w http.ResponseWriter, r *http.Request) {
|
|
||||||
querys := ctx.QueryMap(r)
|
|
||||||
data := s.sysUserService.SelectUserPage(querys)
|
|
||||||
ctx.JSON(w, 200, result.Ok(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户信息详情
|
|
||||||
//
|
|
||||||
// GET /:userId
|
|
||||||
func (s *SysUserApi) Info(w http.ResponseWriter, r *http.Request) {
|
|
||||||
userId := ctx.Param(r, "userId")
|
|
||||||
if userId == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 查询系统角色列表
|
|
||||||
roles := s.sysRoleService.SelectRoleList(sysRoleModel.SysRole{})
|
|
||||||
|
|
||||||
// 不是系统指定管理员需要排除其角色
|
|
||||||
if !srcConfig.IsAdmin(userId) {
|
|
||||||
rolesFilter := make([]sysRoleModel.SysRole, 0)
|
|
||||||
for _, r := range roles {
|
|
||||||
if r.RoleID != "1" {
|
|
||||||
rolesFilter = append(rolesFilter, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roles = rolesFilter
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增用户时,用户ID为0
|
|
||||||
if userId == "0" {
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"user": map[string]any{},
|
|
||||||
"roleIds": []string{},
|
|
||||||
"roles": roles,
|
|
||||||
}))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查用户是否存在
|
|
||||||
user := s.sysUserService.SelectUserById(userId)
|
|
||||||
if user.Id != userId {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access user data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 角色ID组
|
|
||||||
roleIds := make([]string, 0)
|
|
||||||
for _, r := range user.Roles {
|
|
||||||
roleIds = append(roleIds, r.RoleID)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"user": user,
|
|
||||||
"roleIds": roleIds,
|
|
||||||
"roles": roles,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户信息新增
|
|
||||||
//
|
|
||||||
// POST /
|
|
||||||
func (s *SysUserApi) Add(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body sysUserModel.SysUser
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.Id != "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查用户登录账号是否唯一
|
|
||||||
uniqueUserName := s.sysUserService.CheckUniqueUserName(body.AccountId, "")
|
|
||||||
if !uniqueUserName {
|
|
||||||
msg := fmt.Sprintf("[%s] Login account already exists", body.AccountId)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
insertId := s.sysUserService.InsertUser(body)
|
|
||||||
if insertId != "" {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户信息修改
|
|
||||||
//
|
|
||||||
// POST /
|
|
||||||
func (s *SysUserApi) Edit(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body sysUserModel.SysUser
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.Id == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否管理员用户
|
|
||||||
// if srcConfig.IsAdmin(body.Id) {
|
|
||||||
// ctx.JSON(w, 200, result.ErrMsg("不允许操作管理员用户"))
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
user := s.sysUserService.SelectUserById(body.Id)
|
|
||||||
if user.Id != body.Id {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access user data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查用户登录账号是否唯一
|
|
||||||
uniqueUserName := s.sysUserService.CheckUniqueUserName(body.AccountId, body.Id)
|
|
||||||
if !uniqueUserName {
|
|
||||||
msg := fmt.Sprintf("[%s] Login account already exists", body.AccountId)
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body.AccountId = "" // 忽略修改登录用户名称
|
|
||||||
// body.Password = "" // 忽略修改密码
|
|
||||||
rows := s.sysUserService.UpdateUserAndRolePost(body)
|
|
||||||
if rows > 0 {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户信息删除
|
|
||||||
//
|
|
||||||
// DELETE /:userIds
|
|
||||||
func (s *SysUserApi) Remove(w http.ResponseWriter, r *http.Request) {
|
|
||||||
userIds := ctx.Param(r, "userIds")
|
|
||||||
if userIds == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 处理字符转id数组后去重
|
|
||||||
ids := strings.Split(userIds, ",")
|
|
||||||
uniqueIDs := parse.RemoveDuplicates(ids)
|
|
||||||
if len(uniqueIDs) <= 0 {
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rows, err := s.sysUserService.DeleteUserByIds(uniqueIDs)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
msg := fmt.Sprintf("Successfully deleted: %d", rows)
|
|
||||||
ctx.JSON(w, 200, result.OkMsg(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户重置密码
|
|
||||||
//
|
|
||||||
// PUT /resetPwd
|
|
||||||
func (s *SysUserApi) ResetPwd(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body struct {
|
|
||||||
UserID string `json:"userId" binding:"required"`
|
|
||||||
Password string `json:"password" binding:"required"`
|
|
||||||
}
|
|
||||||
if err := ctx.ShouldBindJSON(r, &body); err != nil {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否管理员用户
|
|
||||||
if srcConfig.IsAdmin(body.UserID) {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access user data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user := s.sysUserService.SelectUserById(body.UserID)
|
|
||||||
if user.Id != body.UserID {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access user data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
SysUserApi := sysUserModel.SysUser{
|
|
||||||
Id: body.UserID,
|
|
||||||
Password: body.Password,
|
|
||||||
}
|
|
||||||
rows := s.sysUserService.UpdateUser(SysUserApi)
|
|
||||||
if rows > 0 {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户状态修改
|
|
||||||
//
|
|
||||||
// PUT /changeStatus
|
|
||||||
func (s *SysUserApi) Status(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body struct {
|
|
||||||
UserID string `json:"userId" binding:"required"`
|
|
||||||
Status string `json:"status" binding:"required"`
|
|
||||||
}
|
|
||||||
if err := ctx.ShouldBindJSON(r, &body); err != nil {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否存在
|
|
||||||
user := s.sysUserService.SelectUserById(body.UserID)
|
|
||||||
if user.Id != body.UserID {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("No permission to access user data!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 与旧值相等不变更
|
|
||||||
if user.Status == body.Status {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("Change status equals old value!"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
SysUserApi := sysUserModel.SysUser{
|
|
||||||
Id: body.UserID,
|
|
||||||
Status: body.Status,
|
|
||||||
}
|
|
||||||
rows := s.sysUserService.UpdateUser(SysUserApi)
|
|
||||||
if rows > 0 {
|
|
||||||
ctx.JSON(w, 200, result.Ok(nil))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.Err(nil))
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import "be.ems/features/sys_role/model"
|
|
||||||
|
|
||||||
type SysUser struct {
|
|
||||||
Id string `json:"id" xorm:"pk 'id' autoincr"`
|
|
||||||
AccountId string `json:"accountId" xorm:"account_id"`
|
|
||||||
Name string `json:"name" xorm:"name"`
|
|
||||||
Sn string `json:"sn"`
|
|
||||||
Gender string `json:"gender"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
TelephoneNumber string `json:"telephoneNumber" xorm:"telephone_number"`
|
|
||||||
Mobile string `json:"mobile"`
|
|
||||||
Email string `json:"email" xorm:"email"`
|
|
||||||
StartTime string `json:"startTime" xorm:"start_time"`
|
|
||||||
EndTime string `json:"endTime" xorm:"end_time"`
|
|
||||||
IdCardNumber string `json:"idCardNumber"`
|
|
||||||
EmployeeNumber string `json:"employeeNumber"`
|
|
||||||
Organize string `json:"organize"`
|
|
||||||
EmployeeType string `json:"employeeType"`
|
|
||||||
SupporterCorpName string `json:"supporterCorpName"`
|
|
||||||
RealName string `json:"realName" xorm:"real_name"`
|
|
||||||
Password string `json:"password" xorm:"-"`
|
|
||||||
PasswordSha512 string `json:"-" xorm:"-"`
|
|
||||||
ChangePasswordFlag int `json:"changePasswordFlag"`
|
|
||||||
PasswordExpiration string `json:"passwordExpiration" xorm:"password_expiration"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
UserExpiration string `json:"userExpiration" xorm:"user_expiration"`
|
|
||||||
GroupName string `json:"groupName" xorm:"group_name"`
|
|
||||||
Profile string `json:"-" xorm:"profile"`
|
|
||||||
Phone string `json:"phone" xorm:"phone"`
|
|
||||||
CreateTime string `json:"createTime" xorm:"create_time"`
|
|
||||||
UpdateTime string `json:"updateTime" xorm:"update_time"`
|
|
||||||
Unit string `json:"unit" xorm:"unit"`
|
|
||||||
|
|
||||||
// 角色对象组
|
|
||||||
Roles []model.SysRole `json:"roles"`
|
|
||||||
// 角色ID - 参数提交绑定
|
|
||||||
RoleID string `json:"roleId,omitempty"`
|
|
||||||
// 角色组 - 参数提交绑定
|
|
||||||
RoleIDs []string `json:"roleIds,omitempty"`
|
|
||||||
}
|
|
||||||
@@ -1,578 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
sysRoleModel "be.ems/features/sys_role/model"
|
|
||||||
sysUserModel "be.ems/features/sys_user/model"
|
|
||||||
"be.ems/lib/core/datasource"
|
|
||||||
"be.ems/lib/core/utils/date"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
"be.ems/src/framework/utils/crypto"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 RepoSysUser 结构体
|
|
||||||
var NewRepoSysUser = &RepoSysUser{
|
|
||||||
selectSql: `select u.id,
|
|
||||||
u.account_id, u.name, u.sn, u.gender, u.description, u.telephone_number, u.mobile, u.email,
|
|
||||||
u.start_time, u.end_time, u.id_card_number, u.employee_number,
|
|
||||||
u.organize, u.employee_type, u.supporter_corp_name, u.real_name, u.password, u.password_sha512,
|
|
||||||
u.change_password_flag,u.password_expiration, u.status, u.user_expiration, u.group_name,
|
|
||||||
u.profile, u.phone, u.create_time, u.update_time, u.unit,
|
|
||||||
r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
|
|
||||||
from user u
|
|
||||||
left join sys_user_role ur on u.id = ur.user_id
|
|
||||||
left join sys_role r on r.role_id = ur.role_id`,
|
|
||||||
|
|
||||||
sysUserMap: map[string]string{
|
|
||||||
"id": "Id",
|
|
||||||
"account_id": "AccountId",
|
|
||||||
"name": "Name",
|
|
||||||
"sn": "Sn",
|
|
||||||
"gender": "Gender",
|
|
||||||
"description": "Description",
|
|
||||||
"telephone_number": "TelephoneNumber",
|
|
||||||
"mobile": "Mobile",
|
|
||||||
"email": "Email",
|
|
||||||
"start_time": "StartTime",
|
|
||||||
"end_time": "EndTime",
|
|
||||||
"id_card_number": "IdCardNumber",
|
|
||||||
"employee_number": "EmployeeNumber",
|
|
||||||
"organize": "Organize",
|
|
||||||
"employee_type": "EmployeeType",
|
|
||||||
"supporter_corp_name": "SupporterCorpName",
|
|
||||||
"real_name": "RealName",
|
|
||||||
"password": "Password",
|
|
||||||
"password_sha512": "PasswordSha512",
|
|
||||||
"change_password_flag": "ChangePasswordFlag",
|
|
||||||
"password_expiration": "PasswordExpiration",
|
|
||||||
"status": "Status",
|
|
||||||
"user_expiration": "UserExpiration",
|
|
||||||
"group_name": "GroupName",
|
|
||||||
"profile": "Profile",
|
|
||||||
"phone": "Phone",
|
|
||||||
"create_time": "CreateTime",
|
|
||||||
"update_time": "UpdateTime",
|
|
||||||
"unit": "Unit",
|
|
||||||
},
|
|
||||||
|
|
||||||
sysRoleMap: map[string]string{
|
|
||||||
"role_id": "RoleID",
|
|
||||||
"role_name": "RoleName",
|
|
||||||
"role_key": "RoleKey",
|
|
||||||
"role_sort": "RoleSort",
|
|
||||||
"data_scope": "DataScope",
|
|
||||||
"role_status": "Status",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepoSysUser 用户表 数据层处理
|
|
||||||
type RepoSysUser struct {
|
|
||||||
// 查询视图对象SQL
|
|
||||||
selectSql string
|
|
||||||
// 用户信息实体映射
|
|
||||||
sysUserMap map[string]string
|
|
||||||
// 用户角色实体映射 一对多
|
|
||||||
sysRoleMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
|
||||||
func (r *RepoSysUser) convertResultRows(rows []map[string]any) []sysUserModel.SysUser {
|
|
||||||
arr := make([]sysUserModel.SysUser, 0)
|
|
||||||
|
|
||||||
for _, row := range rows {
|
|
||||||
sysUser := sysUserModel.SysUser{}
|
|
||||||
sysRole := sysRoleModel.SysRole{}
|
|
||||||
sysUser.Roles = []sysRoleModel.SysRole{}
|
|
||||||
|
|
||||||
for key, value := range row {
|
|
||||||
if keyMapper, ok := r.sysUserMap[key]; ok {
|
|
||||||
datasource.SetFieldValue(&sysUser, keyMapper, value)
|
|
||||||
}
|
|
||||||
if keyMapper, ok := r.sysRoleMap[key]; ok {
|
|
||||||
datasource.SetFieldValue(&sysRole, keyMapper, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if sysRole.RoleKey != "" {
|
|
||||||
sysUser.Roles = append(sysUser.Roles, sysRole)
|
|
||||||
}
|
|
||||||
|
|
||||||
one := true
|
|
||||||
for i, a := range arr {
|
|
||||||
if a.Id == sysUser.Id {
|
|
||||||
arrUser := &arr[i]
|
|
||||||
arrUser.Roles = append(arrUser.Roles, sysUser.Roles...)
|
|
||||||
one = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if one {
|
|
||||||
arr = append(arr, sysUser)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectUserPage 根据条件分页查询用户列表
|
|
||||||
func (r *RepoSysUser) SelectUserPage(query map[string]any) map[string]any {
|
|
||||||
selectUserSql := `select u.id,
|
|
||||||
u.account_id, u.name, u.sn, u.gender, u.description, u.telephone_number, u.mobile, u.email,
|
|
||||||
u.start_time, u.end_time, u.id_card_number, u.employee_number,
|
|
||||||
u.organize, u.employee_type, u.supporter_corp_name, u.real_name,
|
|
||||||
u.change_password_flag,u.password_expiration, u.status, u.user_expiration, u.group_name,
|
|
||||||
u.profile, u.phone, u.create_time, u.update_time, u.unit
|
|
||||||
from user u`
|
|
||||||
selectUserTotalSql := `select count(distinct u.id) as 'total' from user u`
|
|
||||||
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if v, ok := query["accountId"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "u.account_id = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["name"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "u.name concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["status"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "u.status = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["phonenumber"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "u.phonenumber like concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
beginTime, ok := query["beginTime"]
|
|
||||||
if !ok {
|
|
||||||
beginTime, ok = query["params[beginTime]"]
|
|
||||||
}
|
|
||||||
if ok && beginTime != "" {
|
|
||||||
conditions = append(conditions, "u.login_date >= ?")
|
|
||||||
beginDate := date.ParseStrToDate(beginTime.(string), date.YYYY_MM_DD)
|
|
||||||
params = append(params, beginDate.UnixMilli())
|
|
||||||
}
|
|
||||||
endTime, ok := query["endTime"]
|
|
||||||
if !ok {
|
|
||||||
endTime, ok = query["params[endTime]"]
|
|
||||||
}
|
|
||||||
if ok && endTime != "" {
|
|
||||||
conditions = append(conditions, "u.login_date <= ?")
|
|
||||||
endDate := date.ParseStrToDate(endTime.(string), date.YYYY_MM_DD)
|
|
||||||
params = append(params, endDate.UnixMilli())
|
|
||||||
}
|
|
||||||
if v, ok := query["deptId"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "(u.dept_id = ? or u.dept_id in ( select t.dept_id from sys_dept t where find_in_set(?, ancestors) ))")
|
|
||||||
params = append(params, v)
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
totalSql := selectUserTotalSql + whereSql
|
|
||||||
totalRows, err := datasource.RawDB("", totalSql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("total err => %v", err)
|
|
||||||
}
|
|
||||||
total := parse.Number(totalRows[0]["total"])
|
|
||||||
if total == 0 {
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": []sysUserModel.SysUser{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
|
||||||
pageSql := " limit ?,? "
|
|
||||||
params = append(params, pageNum*pageSize)
|
|
||||||
params = append(params, pageSize)
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := selectUserSql + whereSql + pageSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
rows := r.convertResultRows(results)
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": rows,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectAllocatedPage 根据条件分页查询分配用户角色列表
|
|
||||||
func (r *RepoSysUser) SelectAllocatedPage(query map[string]any) map[string]any {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if v, ok := query["name"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "u.name like concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["phone"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "u.phone like concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["status"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "u.status = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
// 分配角色用户
|
|
||||||
if allocated, ok := query["allocated"]; ok && allocated != "" {
|
|
||||||
if roleId, ok := query["roleId"]; ok && roleId != "" {
|
|
||||||
if parse.Boolean(allocated) {
|
|
||||||
conditions = append(conditions, "r.role_id = ?")
|
|
||||||
params = append(params, roleId)
|
|
||||||
} else {
|
|
||||||
conditions = append(conditions, `(r.role_id != ? or r.role_id IS NULL)
|
|
||||||
and u.id not in (
|
|
||||||
select u.id from user u
|
|
||||||
inner join sys_user_role ur on u.id = ur.user_id
|
|
||||||
and ur.role_id = ?
|
|
||||||
)`)
|
|
||||||
params = append(params, roleId)
|
|
||||||
params = append(params, roleId)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
totalSql := `select count(distinct u.id) as 'total' from user u
|
|
||||||
left join sys_user_role ur on u.id = ur.user_id
|
|
||||||
left join sys_role r on r.role_id = ur.role_id`
|
|
||||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("total err => %v", err)
|
|
||||||
}
|
|
||||||
total := parse.Number(totalRows[0]["total"])
|
|
||||||
if total == 0 {
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": []sysUserModel.SysUser{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
|
||||||
pageSql := " limit ?,? "
|
|
||||||
params = append(params, pageNum*pageSize)
|
|
||||||
params = append(params, pageSize)
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := `select distinct
|
|
||||||
u.id, u.account_id, u.name, u.gender, u.email,
|
|
||||||
u.phone, u.status, u.create_time, u.real_name
|
|
||||||
from user u
|
|
||||||
left join sys_user_role ur on u.id = ur.user_id
|
|
||||||
left join sys_role r on r.role_id = ur.role_id`
|
|
||||||
querySql = querySql + whereSql + pageSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
rows := r.convertResultRows(results)
|
|
||||||
return map[string]any{
|
|
||||||
"total": total,
|
|
||||||
"rows": rows,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectUserList 根据条件查询用户列表
|
|
||||||
func (r *RepoSysUser) SelectUserList(sysUser sysUserModel.SysUser, dataScopeSQL string) []sysUserModel.SysUser {
|
|
||||||
selectUserSql := `select
|
|
||||||
u.id, u.account_id, u.name, u.real_name, u.email, u.gender, u.phone, u.create_time, u.status, u.description
|
|
||||||
from user u`
|
|
||||||
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysUser.AccountId != "" {
|
|
||||||
conditions = append(conditions, "u.account_id = ?")
|
|
||||||
params = append(params, sysUser.AccountId)
|
|
||||||
}
|
|
||||||
if sysUser.Name != "" {
|
|
||||||
conditions = append(conditions, "u.name like concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, sysUser.Name)
|
|
||||||
}
|
|
||||||
if sysUser.Status != "" {
|
|
||||||
conditions = append(conditions, "u.status = ?")
|
|
||||||
params = append(params, sysUser.Status)
|
|
||||||
}
|
|
||||||
if sysUser.Phone != "" {
|
|
||||||
conditions = append(conditions, "u.phone like concat('%', concat(?, '%'))")
|
|
||||||
params = append(params, sysUser.Phone)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := selectUserSql + whereSql + dataScopeSQL
|
|
||||||
rows, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []sysUserModel.SysUser{}
|
|
||||||
}
|
|
||||||
return r.convertResultRows(rows)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectUserByIds 通过用户ID查询用户
|
|
||||||
func (r *RepoSysUser) SelectUserByIds(userIds []string) []sysUserModel.SysUser {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(userIds))
|
|
||||||
querySql := r.selectSql + " where u.id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(userIds)
|
|
||||||
results, err := datasource.RawDB("", querySql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return []sysUserModel.SysUser{}
|
|
||||||
}
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectUserByUserName 通过用户登录账号查询用户
|
|
||||||
func (r *RepoSysUser) SelectUserByUserName(userName string) sysUserModel.SysUser {
|
|
||||||
querySql := r.selectSql + " where u.name = ?"
|
|
||||||
results, err := datasource.RawDB("", querySql, []any{userName})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return sysUserModel.SysUser{}
|
|
||||||
}
|
|
||||||
// 转换实体
|
|
||||||
rows := r.convertResultRows(results)
|
|
||||||
if len(rows) > 0 {
|
|
||||||
return rows[0]
|
|
||||||
}
|
|
||||||
return sysUserModel.SysUser{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertUser 新增用户信息
|
|
||||||
func (r *RepoSysUser) InsertUser(sysUser sysUserModel.SysUser) string {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysUser.AccountId != "" {
|
|
||||||
params["account_id"] = sysUser.AccountId
|
|
||||||
}
|
|
||||||
if sysUser.Name != "" {
|
|
||||||
params["name"] = sysUser.Name
|
|
||||||
}
|
|
||||||
if sysUser.Sn != "" {
|
|
||||||
params["sn"] = sysUser.Sn
|
|
||||||
} else {
|
|
||||||
params["sn"] = ""
|
|
||||||
}
|
|
||||||
if sysUser.RealName != "" {
|
|
||||||
params["real_name"] = sysUser.RealName
|
|
||||||
} else {
|
|
||||||
params["real_name"] = ""
|
|
||||||
}
|
|
||||||
if sysUser.Gender != "" {
|
|
||||||
params["gender"] = sysUser.Gender
|
|
||||||
}
|
|
||||||
if sysUser.Email != "" {
|
|
||||||
params["email"] = sysUser.Email
|
|
||||||
} else {
|
|
||||||
params["email"] = ""
|
|
||||||
}
|
|
||||||
if sysUser.Phone != "" {
|
|
||||||
params["phone"] = sysUser.Phone
|
|
||||||
} else {
|
|
||||||
params["phone"] = ""
|
|
||||||
}
|
|
||||||
if sysUser.Unit != "" {
|
|
||||||
params["unit"] = sysUser.Unit
|
|
||||||
} else {
|
|
||||||
params["unit"] = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if sysUser.Organize != "" {
|
|
||||||
params["organize"] = sysUser.Organize
|
|
||||||
}
|
|
||||||
if sysUser.Password != "" {
|
|
||||||
password := crypto.BcryptHash(sysUser.Password)
|
|
||||||
params["password"] = password
|
|
||||||
}
|
|
||||||
if sysUser.Status != "" {
|
|
||||||
params["status"] = sysUser.Status
|
|
||||||
}
|
|
||||||
if sysUser.PasswordExpiration != "" {
|
|
||||||
params["password_expiration"] = sysUser.PasswordExpiration
|
|
||||||
}
|
|
||||||
if sysUser.UserExpiration != "" {
|
|
||||||
params["user_expiration"] = sysUser.UserExpiration
|
|
||||||
}
|
|
||||||
if sysUser.GroupName != "" {
|
|
||||||
params["group_name"] = sysUser.GroupName
|
|
||||||
}
|
|
||||||
params["create_time"] = time.Now()
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
|
||||||
sql := "insert into user (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
|
||||||
|
|
||||||
// 执行插入
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
insertId, err := results.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("insert row : %v", err.Error())
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return fmt.Sprint(insertId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateUser 修改用户信息
|
|
||||||
func (r *RepoSysUser) UpdateUser(sysUser sysUserModel.SysUser) int64 {
|
|
||||||
// 参数拼接
|
|
||||||
params := make(map[string]any)
|
|
||||||
if sysUser.Name != "" {
|
|
||||||
params["name"] = sysUser.Name
|
|
||||||
}
|
|
||||||
if sysUser.Sn != "" {
|
|
||||||
params["sn"] = sysUser.Sn
|
|
||||||
} else {
|
|
||||||
params["sn"] = ""
|
|
||||||
}
|
|
||||||
if sysUser.RealName != "" {
|
|
||||||
params["real_name"] = sysUser.RealName
|
|
||||||
} else {
|
|
||||||
params["real_name"] = ""
|
|
||||||
}
|
|
||||||
if sysUser.Gender != "" {
|
|
||||||
params["gender"] = sysUser.Gender
|
|
||||||
}
|
|
||||||
if sysUser.Email != "" {
|
|
||||||
params["email"] = sysUser.Email
|
|
||||||
} else {
|
|
||||||
params["email"] = ""
|
|
||||||
}
|
|
||||||
if sysUser.Phone != "" {
|
|
||||||
params["phone"] = sysUser.Phone
|
|
||||||
} else {
|
|
||||||
params["phone"] = ""
|
|
||||||
}
|
|
||||||
if sysUser.Unit != "" {
|
|
||||||
params["unit"] = sysUser.Unit
|
|
||||||
} else {
|
|
||||||
params["unit"] = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if sysUser.Organize != "" {
|
|
||||||
params["organize"] = sysUser.Organize
|
|
||||||
}
|
|
||||||
if sysUser.Password != "" {
|
|
||||||
password := crypto.BcryptHash(sysUser.Password)
|
|
||||||
params["password"] = password
|
|
||||||
}
|
|
||||||
if sysUser.Status != "" {
|
|
||||||
params["status"] = sysUser.Status
|
|
||||||
}
|
|
||||||
if sysUser.PasswordExpiration != "" {
|
|
||||||
params["password_expiration"] = sysUser.PasswordExpiration
|
|
||||||
}
|
|
||||||
if sysUser.UserExpiration != "" {
|
|
||||||
params["user_expiration"] = sysUser.UserExpiration
|
|
||||||
}
|
|
||||||
if sysUser.GroupName != "" {
|
|
||||||
params["group_name"] = sysUser.GroupName
|
|
||||||
}
|
|
||||||
params["update_time"] = time.Now()
|
|
||||||
|
|
||||||
// 构建执行语句
|
|
||||||
keys, values := datasource.KeyValueByUpdate(params)
|
|
||||||
sql := "update user set " + strings.Join(keys, ",") + " where id = ?"
|
|
||||||
|
|
||||||
// 执行更新
|
|
||||||
values = append(values, sysUser.Id)
|
|
||||||
results, err := datasource.ExecDB("", sql, values)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update row : %v", err.Error())
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("update err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteUserByIds 批量删除用户信息
|
|
||||||
func (r *RepoSysUser) DeleteUserByIds(userIds []string) int64 {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(userIds))
|
|
||||||
sql := "delete from user where id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(userIds)
|
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueUser 校验用户信息是否唯一
|
|
||||||
func (r *RepoSysUser) CheckUniqueUser(sysUser sysUserModel.SysUser) string {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if sysUser.Name != "" {
|
|
||||||
conditions = append(conditions, "name = ?")
|
|
||||||
params = append(params, sysUser.Name)
|
|
||||||
}
|
|
||||||
if sysUser.AccountId != "" {
|
|
||||||
conditions = append(conditions, "account_id = ?")
|
|
||||||
params = append(params, sysUser.AccountId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
} else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := "select id as 'str' from user " + whereSql + " limit 1"
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err %v", err)
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return fmt.Sprint(results[0]["str"])
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
sysUserModel "be.ems/features/sys_user/model"
|
|
||||||
sysuserrole "be.ems/features/sys_user_role"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 ServiceSysUser 结构体
|
|
||||||
var NewServiceSysUser = &ServiceSysUser{
|
|
||||||
sysUserRepository: NewRepoSysUser,
|
|
||||||
sysUserRoleRepository: sysuserrole.NewRepoSysUserRole,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceSysUser 用户 服务层处理
|
|
||||||
type ServiceSysUser struct {
|
|
||||||
// 用户服务
|
|
||||||
sysUserRepository *RepoSysUser
|
|
||||||
// 用户与角色服务
|
|
||||||
sysUserRoleRepository *sysuserrole.RepoSysUserRole
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectUserPage 根据条件分页查询用户列表
|
|
||||||
func (r *ServiceSysUser) SelectUserPage(query map[string]any) map[string]any {
|
|
||||||
return r.sysUserRepository.SelectUserPage(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectUserList 根据条件查询用户列表
|
|
||||||
func (r *ServiceSysUser) SelectUserList(sysUser sysUserModel.SysUser) []sysUserModel.SysUser {
|
|
||||||
return []sysUserModel.SysUser{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectAllocatedPage 根据条件分页查询分配用户角色列表
|
|
||||||
func (r *ServiceSysUser) SelectAllocatedPage(query map[string]any) map[string]any {
|
|
||||||
return r.sysUserRepository.SelectAllocatedPage(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectUserByUserName 通过用户名查询用户
|
|
||||||
func (r *ServiceSysUser) SelectUserByUserName(userName string) sysUserModel.SysUser {
|
|
||||||
return r.sysUserRepository.SelectUserByUserName(userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectUserById 通过用户ID查询用户
|
|
||||||
func (r *ServiceSysUser) SelectUserById(userId string) sysUserModel.SysUser {
|
|
||||||
if userId == "" {
|
|
||||||
return sysUserModel.SysUser{}
|
|
||||||
}
|
|
||||||
users := r.sysUserRepository.SelectUserByIds([]string{userId})
|
|
||||||
if len(users) > 0 {
|
|
||||||
return users[0]
|
|
||||||
}
|
|
||||||
return sysUserModel.SysUser{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertUser 新增用户信息
|
|
||||||
func (r *ServiceSysUser) InsertUser(sysUser sysUserModel.SysUser) string {
|
|
||||||
// 新增用户信息
|
|
||||||
insertId := r.sysUserRepository.InsertUser(sysUser)
|
|
||||||
if insertId != "" {
|
|
||||||
// 新增用户角色信息
|
|
||||||
r.insertUserRole(insertId, sysUser.RoleIDs)
|
|
||||||
}
|
|
||||||
return insertId
|
|
||||||
}
|
|
||||||
|
|
||||||
// insertUserRole 新增用户角色信息
|
|
||||||
func (r *ServiceSysUser) insertUserRole(userId string, roleIds []string) int64 {
|
|
||||||
if userId == "" || len(roleIds) <= 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
sysUserRoles := []sysuserrole.SysUserRole{}
|
|
||||||
for _, roleId := range roleIds {
|
|
||||||
// 管理员角色禁止操作,只能通过配置指定用户ID分配
|
|
||||||
if roleId == "" || roleId == "1" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sysUserRoles = append(sysUserRoles, sysuserrole.NewSysUserRole(userId, roleId))
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.sysUserRoleRepository.BatchUserRole(sysUserRoles)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateUser 修改用户信息
|
|
||||||
func (r *ServiceSysUser) UpdateUser(sysUser sysUserModel.SysUser) int64 {
|
|
||||||
return r.sysUserRepository.UpdateUser(sysUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateUserAndRolePost 修改用户信息同时更新角色和岗位
|
|
||||||
func (r *ServiceSysUser) UpdateUserAndRolePost(sysUser sysUserModel.SysUser) int64 {
|
|
||||||
userId := fmt.Sprint(sysUser.Id)
|
|
||||||
// 删除用户与角色关联
|
|
||||||
r.sysUserRoleRepository.DeleteUserRole([]string{userId})
|
|
||||||
// 新增用户角色信息
|
|
||||||
r.insertUserRole(userId, sysUser.RoleIDs)
|
|
||||||
return r.sysUserRepository.UpdateUser(sysUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteUserByIds 批量删除用户信息
|
|
||||||
func (r *ServiceSysUser) DeleteUserByIds(userIds []string) (int64, error) {
|
|
||||||
// 检查是否存在
|
|
||||||
users := r.sysUserRepository.SelectUserByIds(userIds)
|
|
||||||
if len(users) <= 0 {
|
|
||||||
return 0, errors.New("no permission to access user data")
|
|
||||||
}
|
|
||||||
if len(users) == len(userIds) {
|
|
||||||
// 删除用户与角色关联
|
|
||||||
r.sysUserRoleRepository.DeleteUserRole(userIds)
|
|
||||||
// ... 注意其他userId进行关联的表
|
|
||||||
// 删除用户
|
|
||||||
rows := r.sysUserRepository.DeleteUserByIds(userIds)
|
|
||||||
return rows, nil
|
|
||||||
}
|
|
||||||
return 0, errors.New("failed to delete user information")
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueUserName 校验用户名称是否唯一
|
|
||||||
func (r *ServiceSysUser) CheckUniqueUserName(accountId, userId string) bool {
|
|
||||||
uniqueId := r.sysUserRepository.CheckUniqueUser(sysUserModel.SysUser{
|
|
||||||
AccountId: accountId,
|
|
||||||
})
|
|
||||||
if uniqueId == userId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniquePhone 校验手机号码是否唯一
|
|
||||||
func (r *ServiceSysUser) CheckUniquePhone(phonenumber, userId string) bool {
|
|
||||||
uniqueId := r.sysUserRepository.CheckUniqueUser(sysUserModel.SysUser{
|
|
||||||
Phone: phonenumber,
|
|
||||||
})
|
|
||||||
if uniqueId == userId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckUniqueEmail 校验email是否唯一
|
|
||||||
func (r *ServiceSysUser) CheckUniqueEmail(email, userId string) bool {
|
|
||||||
uniqueId := r.sysUserRepository.CheckUniqueUser(sysUserModel.SysUser{
|
|
||||||
Email: email,
|
|
||||||
})
|
|
||||||
if uniqueId == userId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return uniqueId == ""
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package sysuserrole
|
|
||||||
|
|
||||||
// SysUserRole 用户和角色关联对象 sys_user_role
|
|
||||||
type SysUserRole struct {
|
|
||||||
UserID string `json:"userId"` // 用户ID
|
|
||||||
RoleID string `json:"roleId"` // 角色ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSysUserRole 创建用户和角色关联对象的构造函数
|
|
||||||
func NewSysUserRole(userID string, roleID string) SysUserRole {
|
|
||||||
return SysUserRole{
|
|
||||||
UserID: userID,
|
|
||||||
RoleID: roleID,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
package sysuserrole
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/lib/core/datasource"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 RepoSysUserRole 结构体
|
|
||||||
var NewRepoSysUserRole = &RepoSysUserRole{}
|
|
||||||
|
|
||||||
// RepoSysUserRole 用户与角色关联表 数据层处理
|
|
||||||
type RepoSysUserRole struct{}
|
|
||||||
|
|
||||||
// CountUserRoleByRoleId 通过角色ID查询角色使用数量
|
|
||||||
func (r *RepoSysUserRole) CountUserRoleByRoleId(roleId string) int64 {
|
|
||||||
querySql := "select count(1) as total from sys_user_role where role_id = ?"
|
|
||||||
results, err := datasource.RawDB("", querySql, []any{roleId})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if len(results) > 0 {
|
|
||||||
return parse.Number(results[0]["total"])
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// BatchUserRole 批量新增用户角色信息
|
|
||||||
func (r *RepoSysUserRole) BatchUserRole(sysUserRoles []SysUserRole) int64 {
|
|
||||||
keyValues := make([]string, 0)
|
|
||||||
for _, item := range sysUserRoles {
|
|
||||||
keyValues = append(keyValues, fmt.Sprintf("(%s,%s)", item.UserID, item.RoleID))
|
|
||||||
}
|
|
||||||
sql := "insert into sys_user_role(user_id, role_id) values " + strings.Join(keyValues, ",")
|
|
||||||
results, err := datasource.ExecDB("", sql, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteUserRole 批量删除用户和角色关联
|
|
||||||
func (r *RepoSysUserRole) DeleteUserRole(userIds []string) int64 {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(userIds))
|
|
||||||
sql := "delete from sys_user_role where user_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(userIds)
|
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteUserRoleByRoleId 批量取消授权用户角色
|
|
||||||
func (r *RepoSysUserRole) DeleteUserRoleByRoleId(roleId string, userIds []string) int64 {
|
|
||||||
placeholder := datasource.KeyPlaceholderByQuery(len(userIds))
|
|
||||||
sql := "delete from sys_user_role where role_id= ? and user_id in (" + placeholder + ")"
|
|
||||||
parameters := datasource.ConvertIdsSlice(userIds)
|
|
||||||
parameters = append([]any{roleId}, parameters...)
|
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
affected, err := results.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("delete err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return affected
|
|
||||||
}
|
|
||||||
@@ -1,339 +0,0 @@
|
|||||||
package trace
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/lib/core/conf"
|
|
||||||
"be.ems/lib/core/utils/ctx"
|
|
||||||
"be.ems/lib/core/vo/result"
|
|
||||||
"be.ems/lib/dborm"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
"be.ems/restagent/config"
|
|
||||||
"be.ems/src/framework/utils/cmd"
|
|
||||||
"be.ems/src/framework/utils/ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
UriTcpdumpTask = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeTask"
|
|
||||||
CustomUriTcpdumpTask = config.UriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeTask" // decode message api
|
|
||||||
|
|
||||||
UriTcpdumpPcapDownload = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/tcpdumpPcapDownload"
|
|
||||||
CustomUriTcpdumpPcapDownload = config.UriPrefix + "/traceManagement/{apiVersion}/tcpdumpPcapDownload" // decode message api
|
|
||||||
|
|
||||||
UriTcpdumpNeUPFTask = config.DefaultUriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeUPFTask"
|
|
||||||
CustomUriTcpdumpNeUPFTask = config.UriPrefix + "/traceManagement/{apiVersion}/tcpdumpNeUPFTask" // decode message api
|
|
||||||
)
|
|
||||||
|
|
||||||
// NeInfo 网元信息
|
|
||||||
func NeInfo(neType, neId string) (*dborm.NeInfo, error) {
|
|
||||||
neInfo, err := dborm.XormGetNeInfo(neType, neId)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("dborm.XormGetNeInfo is failed:", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if neInfo == nil || neInfo.Ip == "" {
|
|
||||||
return nil, fmt.Errorf("not ne_info or not IP")
|
|
||||||
}
|
|
||||||
return neInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TcpdumpNeTask 网元发送执行 pcap
|
|
||||||
func TcpdumpNeTask(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body struct {
|
|
||||||
NeType string `json:"neType"` // 网元类型
|
|
||||||
NeId string `json:"neId"` // 网元ID
|
|
||||||
Timeout int `json:"timeout"` // 超时时间
|
|
||||||
Cmd string `json:"cmd"` // 命令
|
|
||||||
}
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.NeType == "" || body.NeId == "" || body.Timeout < 5 || body.Cmd == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
neInfo, err := NeInfo(body.NeType, body.NeId)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
filePcapName := fmt.Sprintf("tmp_%s_%s_%d.pcap", body.NeType, body.NeId, time.Now().UnixMilli())
|
|
||||||
fileLogName := fmt.Sprintf("tmp_%s_%s_%d.log", body.NeType, body.NeId, time.Now().UnixMilli())
|
|
||||||
writeLog := fmt.Sprintf(" >> %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件,放置弹出code 127
|
|
||||||
cmdStr := fmt.Sprintf("cd /tmp \nsudo timeout %d tcpdump -i any %s -s0 -w %s", body.Timeout, body.Cmd, filePcapName)
|
|
||||||
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
|
|
||||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
|
|
||||||
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr+writeLog)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"cmd": cmdStr,
|
|
||||||
"msg": msg,
|
|
||||||
"fileName": filePcapName,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TcpdumpPcapDownload 网元抓包pcap文件下载
|
|
||||||
func TcpdumpPcapDownload(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body struct {
|
|
||||||
NeType string `json:"neType"` // 网元类型
|
|
||||||
NeId string `json:"neId"` // 网元ID
|
|
||||||
FileName string `json:"fileName"` // 文件名
|
|
||||||
}
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.NeType == "" || body.NeId == "" || body.FileName == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
neInfo, err := NeInfo(body.NeType, body.NeId)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
nePath := fmt.Sprintf("/tmp/%s", body.FileName)
|
|
||||||
localPath := fmt.Sprintf("%s/tcpdump/pcap/%s", conf.Get("ne.omcdir"), body.FileName)
|
|
||||||
err = ssh.FileSCPNeToLocal(neInfo.Ip, nePath, localPath)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.FileAttachment(w, r, localPath, body.FileName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TcpdumpNeUPFTask 网元UPF发送执行 pcap
|
|
||||||
func TcpdumpNeUPFTask(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body struct {
|
|
||||||
NeType string `json:"neType"` // 网元类型
|
|
||||||
NeId string `json:"neId"` // 网元ID
|
|
||||||
Cmd string `json:"cmd"` // 命令
|
|
||||||
RunType string `json:"runType"` // 执行开始start还是停止stop
|
|
||||||
}
|
|
||||||
err := ctx.ShouldBindJSON(r, &body)
|
|
||||||
if err != nil || body.NeType != "UPF" || body.NeId == "" || body.Cmd == "" {
|
|
||||||
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
neInfo, err := NeInfo(body.NeType, body.NeId)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始telnet
|
|
||||||
if body.RunType == "start_telnet" {
|
|
||||||
// 创建TCP连接
|
|
||||||
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", neInfo.Ip, 5002))
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
|
||||||
cmdStr := fmt.Sprintf("pcap dispatch trace on max 100000 file %s", filePcapName)
|
|
||||||
|
|
||||||
fmt.Fprintln(conn, cmdStr)
|
|
||||||
|
|
||||||
// 读取内容
|
|
||||||
time.Sleep(time.Duration(200) * time.Millisecond)
|
|
||||||
buf := make([]byte, 1024*8)
|
|
||||||
n, err := conn.Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
} else {
|
|
||||||
str := string(buf[0:n])
|
|
||||||
s := strings.Index(str, "pcap dispatch trace:")
|
|
||||||
if s != -1 {
|
|
||||||
e := strings.Index(str, "\r\nupfd1#")
|
|
||||||
str = str[s:e]
|
|
||||||
} else {
|
|
||||||
str = fmt.Sprintf("Executed, please stop before proceeding %d", n)
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"cmd": cmdStr,
|
|
||||||
"msg": str,
|
|
||||||
"fileName": filePcapName,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
conn.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 停止telnet
|
|
||||||
if body.RunType == "stop_telnet" {
|
|
||||||
// 创建TCP连接
|
|
||||||
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", neInfo.Ip, 5002))
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
|
||||||
cmdStr := "pcap dispatch trace off"
|
|
||||||
|
|
||||||
fmt.Fprintln(conn, cmdStr)
|
|
||||||
|
|
||||||
// 读取内容
|
|
||||||
time.Sleep(time.Duration(200) * time.Millisecond)
|
|
||||||
buf := make([]byte, 1024*8)
|
|
||||||
n, err := conn.Read(buf)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
} else {
|
|
||||||
str := string(buf[0:n])
|
|
||||||
s := strings.Index(str, "pcap dispatch trace:")
|
|
||||||
if s == -1 {
|
|
||||||
s = strings.Index(str, "Write ")
|
|
||||||
}
|
|
||||||
if s != -1 {
|
|
||||||
e := strings.Index(str, "\r\nupfd1#")
|
|
||||||
str = str[s:e]
|
|
||||||
} else {
|
|
||||||
str = "No stoppable found"
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"cmd": cmdStr,
|
|
||||||
"msg": str,
|
|
||||||
"fileName": filePcapName,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
conn.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始 -脚本
|
|
||||||
if body.RunType == "start2" {
|
|
||||||
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
|
|
||||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
|
||||||
// 复制文件到网元上
|
|
||||||
err := ssh.FileSCPLocalToNe(neInfo.Ip, "C:\\AMP\\Probject\\ems_backend\\restagent\\backup\\upf_pcap", "/tmp")
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
writeLog := fmt.Sprintf(" >> %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件,放置弹出code 127
|
|
||||||
cmdStr := fmt.Sprintf("cd /tmp \nchmod +x upf_pcap\n./upf_pcap '192.168.4.139' 'root' 'Admin123@pl' 'pcap dispatch trace on max 100000 file %s' %s ", fileLogName, writeLog)
|
|
||||||
|
|
||||||
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
|
|
||||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
|
|
||||||
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
} else {
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"cmd": cmdStr,
|
|
||||||
"msg": msg,
|
|
||||||
"fileName": filePcapName,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 停止 -脚本
|
|
||||||
if body.RunType == "stop2" {
|
|
||||||
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
|
|
||||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
|
||||||
// cmdStr := "cd /tmp \nexpect /tmp/cat.sh "
|
|
||||||
err := ssh.FileSCPLocalToNe(neInfo.Ip, "C:\\AMP\\Probject\\ems_backend\\restagent\\backup\\upf_pcap", "/tmp")
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
writeLog := fmt.Sprintf(" >> %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件,放置弹出code 127
|
|
||||||
cmdStr := fmt.Sprintf("cd /tmp \nchmod +x upf_pcap\n./upf_pcap '192.168.4.139' 'root' 'Admin123@pl' 'pcap dispatch trace off' %s ", writeLog)
|
|
||||||
|
|
||||||
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
|
|
||||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
|
|
||||||
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
} else {
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"cmd": cmdStr,
|
|
||||||
"msg": msg,
|
|
||||||
"fileName": filePcapName,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始-脚本字符串
|
|
||||||
if body.RunType == "start_str" {
|
|
||||||
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
|
|
||||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
|
||||||
scriptStr := "set capcmd [lindex $argv 0]\nspawn telnet localhost 5002\nexpect \"upfd1# \"\nsend \"$capcmd\\n\"\nexpect \"upfd1# \"\nsend \"quit\\n\"\nexpect \"eof\""
|
|
||||||
writeLog := fmt.Sprintf(" > %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件输出,避免弹出code 127
|
|
||||||
|
|
||||||
capCmdStr := fmt.Sprintf("%s file %s", body.Cmd, filePcapName)
|
|
||||||
|
|
||||||
cmdStr := fmt.Sprintf("cd /tmp\n\necho '%s' > cap.sh\n\nchmod +x cap.sh\n\nexpect ./cap.sh '%s'%s", scriptStr, capCmdStr, writeLog)
|
|
||||||
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
|
|
||||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
|
|
||||||
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
} else {
|
|
||||||
s := strings.Index(msg, "pcap dispatch trace:")
|
|
||||||
if s != -1 {
|
|
||||||
e := strings.Index(msg, "\r\nupfd1#")
|
|
||||||
msg = msg[s:e]
|
|
||||||
} else {
|
|
||||||
msg = "Executed, please stop before proceeding"
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"cmd": capCmdStr,
|
|
||||||
"msg": msg,
|
|
||||||
"fileName": filePcapName,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 停止-脚本字符串
|
|
||||||
if body.RunType == "stop_str" {
|
|
||||||
fileLogName := fmt.Sprintf("tmp_%s_%s.log", body.NeType, body.NeId)
|
|
||||||
filePcapName := fmt.Sprintf("tmp_%s_%s.pcap", body.NeType, body.NeId)
|
|
||||||
scriptStr := "set capcmd [lindex $argv 0]\nspawn telnet localhost 5002\nexpect \"upfd1# \"\nsend \"$capcmd\\n\"\nexpect \"upfd1# \"\nsend \"quit\\n\"\nexpect \"eof\""
|
|
||||||
writeLog := fmt.Sprintf(" > %s 2>&1 \ncat %s", fileLogName, fileLogName) // 执行信息写入日志文件输出,避免弹出code 127
|
|
||||||
|
|
||||||
capCmdStr := body.Cmd
|
|
||||||
|
|
||||||
cmdStr := fmt.Sprintf("cd /tmp\n\necho '%s' > cap.sh\n\nchmod +x cap.sh\n\nexpect ./cap.sh '%s'%s", scriptStr, capCmdStr, writeLog)
|
|
||||||
|
|
||||||
usernameNe := conf.Get("ne.user").(string) // 网元统一用户
|
|
||||||
sshHost := fmt.Sprintf("%s@%s", usernameNe, neInfo.Ip)
|
|
||||||
msg, err := cmd.ExecWithCheck("ssh", sshHost, cmdStr)
|
|
||||||
if err != nil {
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
|
|
||||||
} else {
|
|
||||||
s := strings.Index(msg, "pcap dispatch trace:")
|
|
||||||
if s == -1 {
|
|
||||||
s = strings.Index(msg, "Write ")
|
|
||||||
}
|
|
||||||
if s != -1 {
|
|
||||||
e := strings.Index(msg, "\r\nupfd1#")
|
|
||||||
msg = msg[s:e]
|
|
||||||
} else {
|
|
||||||
msg = "No stoppable found"
|
|
||||||
}
|
|
||||||
ctx.JSON(w, 200, result.OkData(map[string]any{
|
|
||||||
"cmd": capCmdStr,
|
|
||||||
"msg": msg,
|
|
||||||
"fileName": filePcapName,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.JSON(w, 200, result.ErrMsg("runType is start or stop"))
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
// UdmAuthUser UDM鉴权用户
|
|
||||||
type UdmAuthUser struct {
|
|
||||||
ID string `json:"id" xorm:"pk 'id' autoincr"`
|
|
||||||
Imsi string `json:"imsi" xorm:"imsi"` // SIM卡号
|
|
||||||
Amf string `json:"amf" xorm:"amf"` // ANF
|
|
||||||
Status string `json:"status" xorm:"status"` // 状态
|
|
||||||
Ki string `json:"ki" xorm:"ki"` // ki
|
|
||||||
AlgoIndex string `json:"algoIndex" xorm:"algo_index"` //
|
|
||||||
Opc string `json:"opc" xorm:"opc"`
|
|
||||||
NeID string `json:"neId" xorm:"ne_id"` // UDM网元标识-子系统
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
// UdmSubUser UDM签约用户
|
|
||||||
type UdmSubUser struct {
|
|
||||||
ID string `json:"id" xorm:"pk 'id' autoincr"`
|
|
||||||
Msisdn string `json:"msisdn" xorm:"msisdn"` // 相当手机号
|
|
||||||
Imsi string `json:"imsi" xorm:"imsi"` // SIM卡号
|
|
||||||
Ambr string `json:"ambr" xorm:"ambr"`
|
|
||||||
Nssai string `json:"nssai" xorm:"nssai"`
|
|
||||||
Rat string `json:"rat" xorm:"rat"`
|
|
||||||
Arfb string `json:"arfb" xorm:"arfb"`
|
|
||||||
Sar string `json:"sar" xorm:"sar"`
|
|
||||||
Cn string `json:"cn" xorm:"cn"`
|
|
||||||
SmData string `json:"smData" xorm:"sm_data"`
|
|
||||||
SmfSel string `json:"smfSel" xorm:"smf_sel"`
|
|
||||||
EpsDat string `json:"epsDat" xorm:"eps_dat"`
|
|
||||||
NeID string `json:"neId" xorm:"ne_id"` // UDM网元标识-子系统
|
|
||||||
|
|
||||||
EpsFlag string `json:"epsFlag" xorm:"eps_flag"`
|
|
||||||
EpsOdb string `json:"epsOdb" xorm:"eps_odb"`
|
|
||||||
HplmnOdb string `json:"hplmnOdb" xorm:"hplmn_odb"`
|
|
||||||
Ard string `json:"ard" xorm:"ard"`
|
|
||||||
Epstpl string `json:"epstpl" xorm:"epstpl"`
|
|
||||||
ContextId string `json:"contextId" xorm:"context_id"`
|
|
||||||
ApnContext string `json:"apnContext" xorm:"apn_context"`
|
|
||||||
StaticIp string `json:"staticIp" xorm:"static_ip"`
|
|
||||||
|
|
||||||
SubNum string `json:"subNum,omitempty" xorm:"-"` // 批量数
|
|
||||||
}
|
|
||||||
@@ -1,276 +0,0 @@
|
|||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/features/udm_user/model"
|
|
||||||
"be.ems/lib/core/datasource"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 RepoUdmAuthUser 结构体
|
|
||||||
var NewRepoUdmAuthUser = &RepoUdmAuthUser{
|
|
||||||
selectSql: `select
|
|
||||||
id, imsi, amf, status, ki, algo_index, opc, ne_id
|
|
||||||
from u_auth_user`,
|
|
||||||
|
|
||||||
resultMap: map[string]string{
|
|
||||||
"id": "ID",
|
|
||||||
"imsi": "Imsi",
|
|
||||||
"amf": "Amf",
|
|
||||||
"status": "Status",
|
|
||||||
"ki": "Ki",
|
|
||||||
"algo_index": "AlgoIndex",
|
|
||||||
"opc": "Opc",
|
|
||||||
"ne_id": "NeID",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepoUdmAuthUser UDM鉴权用户 数据层处理
|
|
||||||
type RepoUdmAuthUser struct {
|
|
||||||
// 查询视图对象SQL
|
|
||||||
selectSql string
|
|
||||||
// 结果字段与实体映射
|
|
||||||
resultMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
|
||||||
func (r *RepoUdmAuthUser) convertResultRows(rows []map[string]any) []model.UdmAuthUser {
|
|
||||||
arr := make([]model.UdmAuthUser, 0)
|
|
||||||
for _, row := range rows {
|
|
||||||
UdmUser := model.UdmAuthUser{}
|
|
||||||
for key, value := range row {
|
|
||||||
if keyMapper, ok := r.resultMap[key]; ok {
|
|
||||||
datasource.SetFieldValue(&UdmUser, keyMapper, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr = append(arr, UdmUser)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectPage 根据条件分页查询
|
|
||||||
func (r *RepoUdmAuthUser) SelectPage(query map[string]any) map[string]any {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if v, ok := query["imsi"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "imsi like concat(concat('%', ?), '%')")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["neId"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "ne_id = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
result := map[string]any{
|
|
||||||
"total": 0,
|
|
||||||
"rows": []model.UdmAuthUser{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
totalSql := "select count(1) as 'total' from u_auth_user"
|
|
||||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("total err => %v", err)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
total := parse.Number(totalRows[0]["total"])
|
|
||||||
if total == 0 {
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
result["total"] = total
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
|
||||||
pageSql := " limit ?,? "
|
|
||||||
params = append(params, pageNum*pageSize)
|
|
||||||
params = append(params, pageSize)
|
|
||||||
|
|
||||||
// 排序
|
|
||||||
sortSql := ""
|
|
||||||
if v, ok := query["sortField"]; ok && v != "" {
|
|
||||||
if v == "imsi" {
|
|
||||||
sortSql += " order by imsi "
|
|
||||||
}
|
|
||||||
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
|
|
||||||
if o == "desc" {
|
|
||||||
sortSql += " desc "
|
|
||||||
} else {
|
|
||||||
sortSql += " asc "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + sortSql + pageSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
result["rows"] = r.convertResultRows(results)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectList 根据实体查询
|
|
||||||
func (r *RepoUdmAuthUser) SelectList(auth model.UdmAuthUser) []model.UdmAuthUser {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if auth.Imsi != "" {
|
|
||||||
conditions = append(conditions, "imsi = ?")
|
|
||||||
params = append(params, auth.Imsi)
|
|
||||||
}
|
|
||||||
if auth.NeID != "" {
|
|
||||||
conditions = append(conditions, "ne_id = ?")
|
|
||||||
params = append(params, auth.NeID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + " order by imsi asc "
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearAndInsert 清空ne_id后新增实体
|
|
||||||
func (r *RepoUdmAuthUser) ClearAndInsert(neID string, authArr []model.UdmAuthUser) int64 {
|
|
||||||
var num int64 = 0
|
|
||||||
|
|
||||||
// 清空指定ne_id
|
|
||||||
_, err := datasource.ExecDB("", "TRUNCATE TABLE u_auth_user", nil)
|
|
||||||
// _, err := datasource.ExecDB("", "DELETE FROM u_auth_user WHERE ne_id = ?", []any{neID})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("TRUNCATE err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
n := len(authArr)
|
|
||||||
batchSize := 2000
|
|
||||||
for i := 0; i < n; i += batchSize {
|
|
||||||
end := i + batchSize
|
|
||||||
if end > n {
|
|
||||||
end = n
|
|
||||||
}
|
|
||||||
batch := authArr[i:end]
|
|
||||||
|
|
||||||
// 调用 InsertMulti 函数将批量数据插入数据库
|
|
||||||
results, err := datasource.DefaultDB().Table("u_auth_user").InsertMulti(batch)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("InsertMulti err => %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
num += results
|
|
||||||
}
|
|
||||||
return num
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert 新增实体
|
|
||||||
func (r *RepoUdmAuthUser) Insert(authUser model.UdmAuthUser) int64 {
|
|
||||||
results, err := datasource.DefaultDB().Table("u_auth_user").Insert(authUser)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Insert err => %v", err)
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert 批量添加
|
|
||||||
func (r *RepoUdmAuthUser) Inserts(authUsers []model.UdmAuthUser) int64 {
|
|
||||||
var num int64
|
|
||||||
n := len(authUsers)
|
|
||||||
batchSize := 2000
|
|
||||||
for i := 0; i < n; i += batchSize {
|
|
||||||
end := i + batchSize
|
|
||||||
if end > n {
|
|
||||||
end = n
|
|
||||||
}
|
|
||||||
batch := authUsers[i:end]
|
|
||||||
|
|
||||||
// 调用 InsertMulti 函数将批量数据插入数据库
|
|
||||||
results, err := datasource.DefaultDB().Table("u_auth_user").InsertMulti(batch)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Insert err => %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
num += results
|
|
||||||
}
|
|
||||||
return num
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update 修改更新
|
|
||||||
func (r *RepoUdmAuthUser) Update(neID string, authUser model.UdmAuthUser) int64 {
|
|
||||||
// 查询先
|
|
||||||
var user model.UdmAuthUser
|
|
||||||
has, err := datasource.DefaultDB().Table("u_auth_user").Where("imsi = ? and ne_id = ?", authUser.Imsi, neID).Get(&user)
|
|
||||||
if !has || err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if authUser.Ki != "" && authUser.Ki != user.Ki {
|
|
||||||
user.Ki = authUser.Ki
|
|
||||||
}
|
|
||||||
if authUser.Amf != "" && authUser.Amf != user.Amf {
|
|
||||||
user.Amf = authUser.Amf
|
|
||||||
}
|
|
||||||
if authUser.AlgoIndex != "" && authUser.AlgoIndex != user.AlgoIndex {
|
|
||||||
user.AlgoIndex = authUser.AlgoIndex
|
|
||||||
}
|
|
||||||
if authUser.Opc != "" && authUser.Opc != user.Opc {
|
|
||||||
user.Opc = authUser.Opc
|
|
||||||
}
|
|
||||||
|
|
||||||
results, err := datasource.DefaultDB().Table("u_auth_user").Where("imsi = ? and ne_id = ?", user.Imsi, user.NeID).Update(user)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete 删除实体
|
|
||||||
func (r *RepoUdmAuthUser) Delete(neID, imsi string) int64 {
|
|
||||||
results, err := datasource.DefaultDB().Table("u_auth_user").Where("imsi = ? and ne_id = ?", imsi, neID).Delete()
|
|
||||||
if err != nil {
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete 删除范围实体
|
|
||||||
func (r *RepoUdmAuthUser) Deletes(neID, imsi, num string) int64 {
|
|
||||||
imsiV, err := strconv.Atoi(imsi)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
numV, err := strconv.Atoi(num)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
results, err := datasource.DefaultDB().Table("u_auth_user").Where("imsi >= ? and imsi < ? and ne_id = ?", imsiV, imsiV+numV, neID).Delete()
|
|
||||||
if err != nil {
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
@@ -1,450 +0,0 @@
|
|||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/features/udm_user/model"
|
|
||||||
"be.ems/lib/core/datasource"
|
|
||||||
"be.ems/lib/core/utils/parse"
|
|
||||||
"be.ems/lib/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化数据层 RepoUdmSubUser 结构体
|
|
||||||
var NewRepoUdmSubUser = &RepoUdmSubUser{
|
|
||||||
selectSql: `select
|
|
||||||
id, msisdn, imsi, ambr, nssai, rat, arfb, sar, cn, sm_data, smf_sel, eps_dat, ne_id, eps_flag, eps_odb, hplmn_odb, ard, epstpl, context_id, apn_context, static_ip
|
|
||||||
from u_sub_user`,
|
|
||||||
|
|
||||||
resultMap: map[string]string{
|
|
||||||
"id": "ID",
|
|
||||||
"msisdn": "Msisdn",
|
|
||||||
"imsi": "Imsi",
|
|
||||||
"ambr": "Ambr",
|
|
||||||
"nssai": "Nssai",
|
|
||||||
"rat": "Rat",
|
|
||||||
"arfb": "Arfb",
|
|
||||||
"sar": "Sar",
|
|
||||||
"cn": "Cn",
|
|
||||||
"sm_data": "SmData",
|
|
||||||
"smf_sel": "SmfSel",
|
|
||||||
"eps_dat": "EpsDat",
|
|
||||||
"ne_id": "NeID",
|
|
||||||
"eps_flag": "EpsFlag",
|
|
||||||
"eps_odb": "EpsOdb",
|
|
||||||
"hplmn_odb": "HplmnOdb",
|
|
||||||
"ard": "Ard",
|
|
||||||
"epstpl": "Epstpl",
|
|
||||||
"context_id": "ContextId",
|
|
||||||
"apn_context": "ApnContext",
|
|
||||||
"static_ip": "StaticIp",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepoUdmSubUser UDM签约用户 数据层处理
|
|
||||||
type RepoUdmSubUser struct {
|
|
||||||
// 查询视图对象SQL
|
|
||||||
selectSql string
|
|
||||||
// 结果字段与实体映射
|
|
||||||
resultMap map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
|
||||||
func (r *RepoUdmSubUser) convertResultRows(rows []map[string]any) []model.UdmSubUser {
|
|
||||||
arr := make([]model.UdmSubUser, 0)
|
|
||||||
for _, row := range rows {
|
|
||||||
UdmUser := model.UdmSubUser{}
|
|
||||||
for key, value := range row {
|
|
||||||
if keyMapper, ok := r.resultMap[key]; ok {
|
|
||||||
datasource.SetFieldValue(&UdmUser, keyMapper, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr = append(arr, UdmUser)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectPage 根据条件分页查询字典类型
|
|
||||||
func (r *RepoUdmSubUser) SelectPage(query map[string]any) map[string]any {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if v, ok := query["msisdn"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "msisdn like concat(concat('%', ?), '%')")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["imsi"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "imsi like concat(concat('%', ?), '%')")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
if v, ok := query["neId"]; ok && v != "" {
|
|
||||||
conditions = append(conditions, "ne_id = ?")
|
|
||||||
params = append(params, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
result := map[string]any{
|
|
||||||
"total": 0,
|
|
||||||
"rows": []model.UdmAuthUser{},
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
|
||||||
totalSql := "select count(1) as 'total' from u_sub_user"
|
|
||||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("total err => %v", err)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
total := parse.Number(totalRows[0]["total"])
|
|
||||||
if total == 0 {
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
result["total"] = total
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
pageNum, pageSize := datasource.PageNumSize(query["pageNum"], query["pageSize"])
|
|
||||||
pageSql := " limit ?,? "
|
|
||||||
params = append(params, pageNum*pageSize)
|
|
||||||
params = append(params, pageSize)
|
|
||||||
|
|
||||||
// 排序
|
|
||||||
sortSql := ""
|
|
||||||
if v, ok := query["sortField"]; ok && v != "" {
|
|
||||||
if v == "imsi" {
|
|
||||||
sortSql += " order by imsi "
|
|
||||||
}
|
|
||||||
if v == "msisdn" {
|
|
||||||
sortSql += " order by msisdn "
|
|
||||||
}
|
|
||||||
if o, ok := query["sortOrder"]; ok && o != nil && v != "" {
|
|
||||||
if o == "desc" {
|
|
||||||
sortSql += " desc "
|
|
||||||
} else {
|
|
||||||
sortSql += " asc "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + sortSql + pageSql
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
result["rows"] = r.convertResultRows(results)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectList 根据实体查询
|
|
||||||
func (r *RepoUdmSubUser) SelectList(auth model.UdmSubUser) []model.UdmSubUser {
|
|
||||||
// 查询条件拼接
|
|
||||||
var conditions []string
|
|
||||||
var params []any
|
|
||||||
if auth.Imsi != "" {
|
|
||||||
conditions = append(conditions, "imsi = ?")
|
|
||||||
params = append(params, auth.Imsi)
|
|
||||||
}
|
|
||||||
if auth.NeID != "" {
|
|
||||||
conditions = append(conditions, "ne_id = ?")
|
|
||||||
params = append(params, auth.NeID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建查询条件语句
|
|
||||||
whereSql := ""
|
|
||||||
if len(conditions) > 0 {
|
|
||||||
whereSql += " where " + strings.Join(conditions, " and ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数据
|
|
||||||
querySql := r.selectSql + whereSql + " order by imsi asc "
|
|
||||||
results, err := datasource.RawDB("", querySql, params)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("query err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换实体
|
|
||||||
return r.convertResultRows(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearAndInsert 清空ne_id后新增实体
|
|
||||||
func (r *RepoUdmSubUser) ClearAndInsert(neID string, subArr []model.UdmSubUser) int64 {
|
|
||||||
var num int64 = 0
|
|
||||||
|
|
||||||
// 清空指定ne_id
|
|
||||||
_, err := datasource.ExecDB("", "TRUNCATE TABLE u_sub_user", nil)
|
|
||||||
// _, err := datasource.ExecDB("", "DELETE FROM u_sub_user WHERE ne_id = ?", []any{neID})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("TRUNCATE err => %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
n := len(subArr)
|
|
||||||
batchSize := 2000
|
|
||||||
for i := 0; i < n; i += batchSize {
|
|
||||||
end := i + batchSize
|
|
||||||
if end > n {
|
|
||||||
end = n
|
|
||||||
}
|
|
||||||
batch := subArr[i:end]
|
|
||||||
|
|
||||||
// 调用 InsertMulti 函数将批量数据插入数据库
|
|
||||||
results, err := datasource.DefaultDB().Table("u_sub_user").InsertMulti(batch)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("InsertMulti err => %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
num += results
|
|
||||||
}
|
|
||||||
|
|
||||||
// for _, u := range subArr {
|
|
||||||
// u.NeID = neID
|
|
||||||
// results, err := datasource.DefaultDB().Table("u_sub_user").Insert(u)
|
|
||||||
// if err != nil {
|
|
||||||
// return num
|
|
||||||
// }
|
|
||||||
// num += results
|
|
||||||
// }
|
|
||||||
return num
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert 新增实体
|
|
||||||
func (r *RepoUdmSubUser) Insert(subUser model.UdmSubUser) int64 {
|
|
||||||
results, err := datasource.DefaultDB().Table("u_sub_user").Insert(subUser)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Insert err => %v", err)
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert 批量添加
|
|
||||||
func (r *RepoUdmSubUser) Inserts(subUser []model.UdmSubUser) int64 {
|
|
||||||
var num int64
|
|
||||||
n := len(subUser)
|
|
||||||
batchSize := 2000
|
|
||||||
for i := 0; i < n; i += batchSize {
|
|
||||||
end := i + batchSize
|
|
||||||
if end > n {
|
|
||||||
end = n
|
|
||||||
}
|
|
||||||
batch := subUser[i:end]
|
|
||||||
|
|
||||||
// 调用 InsertMulti 函数将批量数据插入数据库
|
|
||||||
results, err := datasource.DefaultDB().Table("u_sub_user").InsertMulti(batch)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Insert err => %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
num += results
|
|
||||||
}
|
|
||||||
return num
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert4G 批量添加4G用户
|
|
||||||
func (r *RepoUdmSubUser) Insert4G(neID string, subUser model.UdmSubUser) int64 {
|
|
||||||
var insertNum int64
|
|
||||||
|
|
||||||
imsiV, err := strconv.Atoi(subUser.Imsi)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
numV, err := strconv.Atoi(subUser.SubNum)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
subUser.NeID = neID
|
|
||||||
for i := 0; i < numV; i++ {
|
|
||||||
subUser.Imsi = fmt.Sprint(imsiV + i)
|
|
||||||
|
|
||||||
results, err := datasource.DefaultDB().Table("u_sub_user").Insert(subUser)
|
|
||||||
if err == nil {
|
|
||||||
log.Errorf("Insert err => %v", err)
|
|
||||||
insertNum += results
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return insertNum
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update 修改更新
|
|
||||||
func (r *RepoUdmSubUser) Update(neID string, authUser model.UdmSubUser) int64 {
|
|
||||||
// 查询先
|
|
||||||
var user model.UdmSubUser
|
|
||||||
has, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", authUser.Imsi, neID).Get(&user)
|
|
||||||
if !has || err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if authUser.Msisdn != "" && authUser.Msisdn != user.Msisdn {
|
|
||||||
user.Msisdn = authUser.Msisdn
|
|
||||||
}
|
|
||||||
if authUser.Ambr != "" && authUser.Ambr != user.Ambr {
|
|
||||||
user.Ambr = authUser.Ambr
|
|
||||||
}
|
|
||||||
if authUser.Arfb != "" && authUser.Arfb != user.Arfb {
|
|
||||||
user.Arfb = authUser.Arfb
|
|
||||||
}
|
|
||||||
if authUser.Sar != "" && authUser.Sar != user.Sar {
|
|
||||||
user.Sar = authUser.Sar
|
|
||||||
}
|
|
||||||
if authUser.Rat != "" && authUser.Rat != user.Rat {
|
|
||||||
user.Rat = authUser.Rat
|
|
||||||
}
|
|
||||||
if authUser.Cn != "" && authUser.Cn != user.Cn {
|
|
||||||
user.Cn = authUser.Cn
|
|
||||||
}
|
|
||||||
if authUser.SmfSel != "" && authUser.SmfSel != user.SmfSel {
|
|
||||||
user.SmfSel = authUser.SmfSel
|
|
||||||
}
|
|
||||||
if authUser.SmData != "" && authUser.SmData != user.SmData {
|
|
||||||
user.SmData = authUser.SmData
|
|
||||||
}
|
|
||||||
if authUser.EpsDat != "" && authUser.EpsDat != user.EpsDat {
|
|
||||||
user.EpsDat = authUser.EpsDat
|
|
||||||
}
|
|
||||||
if authUser.EpsFlag != "" && authUser.EpsFlag != user.EpsFlag {
|
|
||||||
user.EpsFlag = authUser.EpsFlag
|
|
||||||
}
|
|
||||||
if authUser.EpsOdb != "" && authUser.EpsDat != user.EpsDat {
|
|
||||||
user.EpsOdb = authUser.EpsOdb
|
|
||||||
}
|
|
||||||
if authUser.HplmnOdb != "" && authUser.HplmnOdb != user.HplmnOdb {
|
|
||||||
user.HplmnOdb = authUser.HplmnOdb
|
|
||||||
}
|
|
||||||
if authUser.Epstpl != "" && authUser.Epstpl != user.Epstpl {
|
|
||||||
user.Epstpl = authUser.Epstpl
|
|
||||||
}
|
|
||||||
if authUser.Ard != "" && authUser.Ard != user.Ard {
|
|
||||||
user.Ard = authUser.Ard
|
|
||||||
}
|
|
||||||
if authUser.ContextId != "" && authUser.ContextId != user.ContextId {
|
|
||||||
user.ContextId = authUser.ContextId
|
|
||||||
}
|
|
||||||
if authUser.ApnContext != "" && authUser.ApnContext != user.ApnContext {
|
|
||||||
user.ApnContext = authUser.ApnContext
|
|
||||||
}
|
|
||||||
if authUser.StaticIp != "" && authUser.StaticIp != user.StaticIp {
|
|
||||||
user.StaticIp = authUser.StaticIp
|
|
||||||
}
|
|
||||||
|
|
||||||
results, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", user.Imsi, user.NeID).Update(user)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Update err => %v", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update4GIP 批量修改4G IP
|
|
||||||
func (r *RepoUdmSubUser) Update4GIP(neID string, subUser model.UdmSubUser) int64 {
|
|
||||||
var insertNum int64
|
|
||||||
|
|
||||||
imsiV, err := strconv.Atoi(subUser.Imsi)
|
|
||||||
if err != nil || subUser.StaticIp == "" {
|
|
||||||
return insertNum
|
|
||||||
}
|
|
||||||
numV, err := strconv.Atoi(subUser.SubNum)
|
|
||||||
if err != nil {
|
|
||||||
return insertNum
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < numV; i++ {
|
|
||||||
subUser.Imsi = fmt.Sprint(imsiV + i)
|
|
||||||
|
|
||||||
// 查询先
|
|
||||||
var user model.UdmSubUser
|
|
||||||
has, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", subUser.Imsi, neID).Get(&user)
|
|
||||||
if has && err == nil {
|
|
||||||
// IP会自动递增
|
|
||||||
parts := strings.Split(subUser.StaticIp, ".")
|
|
||||||
lastPart := parts[3]
|
|
||||||
lastNum, _ := strconv.Atoi(lastPart)
|
|
||||||
lastNum += i
|
|
||||||
newLastPart := strconv.Itoa(lastNum)
|
|
||||||
parts[3] = newLastPart
|
|
||||||
newIP := strings.Join(parts, ".")
|
|
||||||
user.StaticIp = newIP
|
|
||||||
// 更新
|
|
||||||
results, err := datasource.DefaultDB().Table("u_sub_user").Update(user)
|
|
||||||
if err == nil {
|
|
||||||
log.Errorf("Update err => %v", err)
|
|
||||||
insertNum += results
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return insertNum
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateSmData 批量修改sm-data
|
|
||||||
func (r *RepoUdmSubUser) UpdateSmData(neID string, subUser model.UdmSubUser) int64 {
|
|
||||||
var insertNum int64
|
|
||||||
|
|
||||||
imsiV, err := strconv.Atoi(subUser.Imsi)
|
|
||||||
if err != nil || subUser.StaticIp == "" {
|
|
||||||
return insertNum
|
|
||||||
}
|
|
||||||
numV, err := strconv.Atoi(subUser.SubNum)
|
|
||||||
if err != nil {
|
|
||||||
return insertNum
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < numV; i++ {
|
|
||||||
subUser.Imsi = fmt.Sprint(imsiV + i)
|
|
||||||
|
|
||||||
// 查询先
|
|
||||||
var user model.UdmSubUser
|
|
||||||
has, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", subUser.Imsi, neID).Get(&user)
|
|
||||||
if has && err == nil {
|
|
||||||
// IP会自动递增,需提前规划好DNN对应的IP;如dnn不需要绑定IP则不带此字段名
|
|
||||||
// parts := strings.Split(subUser.SmData, "&")
|
|
||||||
user.SmData = subUser.SmData
|
|
||||||
// 更新
|
|
||||||
results, err := datasource.DefaultDB().Table("u_sub_user").Update(user)
|
|
||||||
if err == nil {
|
|
||||||
log.Errorf("Update err => %v", err)
|
|
||||||
insertNum += results
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return insertNum
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete 删除实体
|
|
||||||
func (r *RepoUdmSubUser) Delete(neID, imsi string) int64 {
|
|
||||||
results, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi = ? and ne_id = ?", imsi, neID).Delete()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Delete err => %v", err)
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete 删除范围实体
|
|
||||||
func (r *RepoUdmSubUser) Deletes(neID, imsi, num string) int64 {
|
|
||||||
imsiV, err := strconv.Atoi(imsi)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
numV, err := strconv.Atoi(num)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
results, err := datasource.DefaultDB().Table("u_sub_user").Where("imsi >= ? and imsi < ? and ne_id = ?", imsiV, imsiV+numV, neID).Delete()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Delete err => %v", err)
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/features/udm_user/model"
|
|
||||||
"be.ems/src/framework/redis"
|
|
||||||
)
|
|
||||||
|
|
||||||
// phoneImsiList 获取所有imsi
|
|
||||||
// func phoneImsiList() map[string]string {
|
|
||||||
// phoneAndImsiArr := make(map[string]string, 0)
|
|
||||||
// phoneKeys, err := redis.GetKeys("udmuser", "1*********")
|
|
||||||
// if err != nil {
|
|
||||||
// return phoneAndImsiArr
|
|
||||||
// }
|
|
||||||
// for _, phone := range phoneKeys {
|
|
||||||
// imsi, err := redis.Get("udmuser", phone)
|
|
||||||
// if err != nil {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// phoneAndImsiArr[phone] = imsi
|
|
||||||
// }
|
|
||||||
// return phoneAndImsiArr
|
|
||||||
// }
|
|
||||||
|
|
||||||
// redisUdmAuthUserList UDM鉴权用户
|
|
||||||
func redisUdmAuthUserList() []model.UdmAuthUser {
|
|
||||||
user := []model.UdmAuthUser{}
|
|
||||||
ausfArr, err := redis.GetKeys("udmuser", "ausf:*")
|
|
||||||
if err != nil {
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
for _, key := range ausfArr {
|
|
||||||
m, err := redis.GetHash("udmuser", key)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 跳过-号数据
|
|
||||||
imsi := key[5:]
|
|
||||||
if strings.Contains(imsi, "-") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
status := "0"
|
|
||||||
if _, ok := m["auth_success"]; ok {
|
|
||||||
status = "1"
|
|
||||||
}
|
|
||||||
amf := ""
|
|
||||||
if v, ok := m["amf"]; ok {
|
|
||||||
amf = strings.Replace(v, "\r\n", "", 1)
|
|
||||||
}
|
|
||||||
a := model.UdmAuthUser{
|
|
||||||
Imsi: imsi,
|
|
||||||
Amf: amf,
|
|
||||||
Status: status,
|
|
||||||
Ki: m["ki"],
|
|
||||||
AlgoIndex: m["algo"],
|
|
||||||
Opc: m["opc"],
|
|
||||||
}
|
|
||||||
user = append(user, a)
|
|
||||||
}
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
|
|
||||||
// redisUdmSubUserList UDM签约用户
|
|
||||||
func redisUdmSubUserList() []model.UdmSubUser {
|
|
||||||
user := []model.UdmSubUser{}
|
|
||||||
udmsdArr, err := redis.GetKeys("udmuser", "udm-sd:*")
|
|
||||||
if err != nil {
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
for _, key := range udmsdArr {
|
|
||||||
m, err := redis.GetHash("udmuser", key)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
a := model.UdmSubUser{
|
|
||||||
Imsi: key[7:],
|
|
||||||
Msisdn: m["gpsi"], // 46003550072 strings.TrimPrefix(m["gpsi"], "86"),
|
|
||||||
SmfSel: m["smf-sel"],
|
|
||||||
SmData: m["sm-dat"], // 1-000001&cmnet&ims&3gnet
|
|
||||||
}
|
|
||||||
|
|
||||||
// def_ambr,def_nssai,0,def_arfb,def_sar,3,1,12000,1,1000,0,1,-
|
|
||||||
if v, ok := m["am-dat"]; ok {
|
|
||||||
arr := strings.Split(v, ",")
|
|
||||||
a.Ambr = arr[0]
|
|
||||||
a.Nssai = arr[1]
|
|
||||||
a.Rat = arr[2]
|
|
||||||
a.Arfb = arr[3]
|
|
||||||
a.Sar = arr[4]
|
|
||||||
a.Cn = arr[5]
|
|
||||||
}
|
|
||||||
// 1,64,24,65,def_eps,1,2,010200000000,-
|
|
||||||
if v, ok := m["eps-dat"]; ok {
|
|
||||||
arr := strings.Split(v, ",")
|
|
||||||
// 跳过非常规数据
|
|
||||||
if len(arr) > 9 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
a.EpsDat = v
|
|
||||||
a.EpsFlag = arr[0]
|
|
||||||
a.EpsOdb = arr[1]
|
|
||||||
a.HplmnOdb = arr[2]
|
|
||||||
a.Ard = arr[3]
|
|
||||||
a.Epstpl = arr[4]
|
|
||||||
a.ContextId = arr[5]
|
|
||||||
a.ApnContext = arr[7]
|
|
||||||
// [6] 是不要的,导入和导出不用
|
|
||||||
a.StaticIp = arr[8]
|
|
||||||
}
|
|
||||||
|
|
||||||
user = append(user, a)
|
|
||||||
}
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"be.ems/features/udm_user/model"
|
|
||||||
"be.ems/features/udm_user/repo"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 ServiceUdmAuthUser 结构体
|
|
||||||
var NewServiceUdmAuthUser = &ServiceUdmAuthUser{
|
|
||||||
repoAuthUser: *repo.NewRepoUdmAuthUser,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceUdmAuthUser UDM鉴权用户 服务层处理
|
|
||||||
type ServiceUdmAuthUser struct {
|
|
||||||
repoAuthUser repo.RepoUdmAuthUser
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save UDM鉴权用户-获取全部保存数据库
|
|
||||||
func (r *ServiceUdmAuthUser) Save(neID string) int64 {
|
|
||||||
var num int64 = 0
|
|
||||||
authArr := redisUdmAuthUserList()
|
|
||||||
// 有数据才清空
|
|
||||||
if len(authArr) == 0 {
|
|
||||||
return num
|
|
||||||
}
|
|
||||||
go r.repoAuthUser.ClearAndInsert(neID, authArr)
|
|
||||||
return int64(len(authArr))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page UDM签约用户-分页查询数据库
|
|
||||||
func (r *ServiceUdmAuthUser) Page(query map[string]any) map[string]any {
|
|
||||||
return r.repoAuthUser.SelectPage(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// List UDM签约用户-查询数据库
|
|
||||||
func (r *ServiceUdmAuthUser) List(authUser model.UdmAuthUser) []model.UdmAuthUser {
|
|
||||||
return r.repoAuthUser.SelectList(authUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM鉴权用户-新增单个
|
|
||||||
// imsi长度15,ki长度32,opc长度0或者32
|
|
||||||
func (r *ServiceUdmAuthUser) Insert(neID string, authUser model.UdmAuthUser) int64 {
|
|
||||||
authUser.NeID = neID
|
|
||||||
authUser.Status = "0"
|
|
||||||
return r.repoAuthUser.Insert(authUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM鉴权用户-批量添加
|
|
||||||
func (r *ServiceUdmAuthUser) Inserts(neID string, authUser model.UdmAuthUser, num string) int64 {
|
|
||||||
var arr []model.UdmAuthUser
|
|
||||||
|
|
||||||
imsiVlen := len(authUser.Imsi)
|
|
||||||
imsiV, err := strconv.Atoi(authUser.Imsi)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
numV, err := strconv.Atoi(num)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
authUser.NeID = neID
|
|
||||||
authUser.Status = "0"
|
|
||||||
for i := 0; i < numV; i++ {
|
|
||||||
imsi := fmt.Sprint(imsiV + i)
|
|
||||||
if len(imsi) < imsiVlen {
|
|
||||||
imsi = fmt.Sprintf("%0*s", imsiVlen, imsi)
|
|
||||||
}
|
|
||||||
authUser.Imsi = imsi
|
|
||||||
arr = append(arr, authUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.repoAuthUser.Inserts(arr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertCSV UDM鉴权用户-批量添加
|
|
||||||
func (r *ServiceUdmAuthUser) InsertCSV(neID string, data []map[string]string) int64 {
|
|
||||||
var arr []model.UdmAuthUser
|
|
||||||
for _, v := range data {
|
|
||||||
var authUser model.UdmAuthUser
|
|
||||||
authUser.NeID = neID
|
|
||||||
authUser.Status = "0"
|
|
||||||
if s, ok := v["imsi"]; ok {
|
|
||||||
authUser.Imsi = s
|
|
||||||
}
|
|
||||||
if s, ok := v["ki"]; ok {
|
|
||||||
authUser.Ki = s
|
|
||||||
}
|
|
||||||
if s, ok := v["algo"]; ok {
|
|
||||||
authUser.AlgoIndex = s
|
|
||||||
}
|
|
||||||
if s, ok := v["amf"]; ok {
|
|
||||||
authUser.Amf = s
|
|
||||||
}
|
|
||||||
if s, ok := v["opc"]; ok {
|
|
||||||
authUser.Opc = s
|
|
||||||
}
|
|
||||||
|
|
||||||
if authUser.Imsi == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
arr = append(arr, authUser)
|
|
||||||
}
|
|
||||||
return r.repoAuthUser.Inserts(arr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertTxt UDM鉴权用户-批量添加
|
|
||||||
func (r *ServiceUdmAuthUser) InsertTxt(neID string, data [][]string) int64 {
|
|
||||||
var arr []model.UdmAuthUser
|
|
||||||
for _, v := range data {
|
|
||||||
if len(v) < 4 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var authUser model.UdmAuthUser
|
|
||||||
authUser.NeID = neID
|
|
||||||
authUser.Status = "0"
|
|
||||||
authUser.Imsi = v[0]
|
|
||||||
authUser.Ki = v[1]
|
|
||||||
authUser.AlgoIndex = v[2]
|
|
||||||
authUser.Amf = v[3]
|
|
||||||
if len(v) == 5 {
|
|
||||||
authUser.Opc = v[4]
|
|
||||||
}
|
|
||||||
|
|
||||||
if authUser.Imsi == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
arr = append(arr, authUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.repoAuthUser.Inserts(arr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM鉴权用户-修改更新
|
|
||||||
func (r *ServiceUdmAuthUser) Update(neID string, authUser model.UdmAuthUser) int64 {
|
|
||||||
return r.repoAuthUser.Update(neID, authUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM鉴权用户-删除单个
|
|
||||||
func (r *ServiceUdmAuthUser) Delete(neID, imsi string) int64 {
|
|
||||||
return r.repoAuthUser.Delete(neID, imsi)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM鉴权用户-删除范围
|
|
||||||
func (r *ServiceUdmAuthUser) Deletes(neID, imsi, num string) int64 {
|
|
||||||
return r.repoAuthUser.Deletes(neID, imsi, num)
|
|
||||||
}
|
|
||||||
@@ -1,231 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/features/udm_user/model"
|
|
||||||
"be.ems/features/udm_user/repo"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实例化服务层 ServiceUdmSubUser 结构体
|
|
||||||
var NewServiceUdmSubUser = &ServiceUdmSubUser{
|
|
||||||
repoSunUser: *repo.NewRepoUdmSubUser,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceUdmSubUser UDM签约用户 服务层处理
|
|
||||||
type ServiceUdmSubUser struct {
|
|
||||||
repoSunUser repo.RepoUdmSubUser
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save UDM签约用户-获取全部保存数据库
|
|
||||||
func (r *ServiceUdmSubUser) Save(neID string) int64 {
|
|
||||||
var num int64 = 0
|
|
||||||
subArr := redisUdmSubUserList()
|
|
||||||
// 有数据才清空
|
|
||||||
if len(subArr) == 0 {
|
|
||||||
return num
|
|
||||||
}
|
|
||||||
go r.repoSunUser.ClearAndInsert(neID, subArr)
|
|
||||||
return int64(len(subArr))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page UDM签约用户-分页查询数据库
|
|
||||||
func (r *ServiceUdmSubUser) Page(query map[string]any) map[string]any {
|
|
||||||
return r.repoSunUser.SelectPage(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
// List UDM签约用户-查询数据库
|
|
||||||
func (r *ServiceUdmSubUser) List(subUser model.UdmSubUser) []model.UdmSubUser {
|
|
||||||
return r.repoSunUser.SelectList(subUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM签约用户-新增单个
|
|
||||||
// imsi长度15,ki长度32,opc长度0或者32
|
|
||||||
func (r *ServiceUdmSubUser) Insert(neID string, subUser model.UdmSubUser) int64 {
|
|
||||||
subUser.NeID = neID
|
|
||||||
return r.repoSunUser.Insert(subUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM签约用户-批量添加
|
|
||||||
func (r *ServiceUdmSubUser) Inserts(neID string, subUser model.UdmSubUser, num string) int64 {
|
|
||||||
var arr []model.UdmSubUser
|
|
||||||
|
|
||||||
imsiVlen := len(subUser.Imsi)
|
|
||||||
imsiV, err := strconv.Atoi(subUser.Imsi)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
msisdnVlen := len(subUser.Msisdn)
|
|
||||||
msisdnV, err := strconv.Atoi(subUser.Msisdn)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
numV, err := strconv.Atoi(num)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
subUser.NeID = neID
|
|
||||||
for i := 0; i < numV; i++ {
|
|
||||||
msisdn := fmt.Sprint(msisdnV + i)
|
|
||||||
if len(msisdn) < msisdnVlen {
|
|
||||||
msisdn = fmt.Sprintf("%0*s", msisdnVlen, msisdn)
|
|
||||||
}
|
|
||||||
subUser.Msisdn = msisdn
|
|
||||||
|
|
||||||
imsi := fmt.Sprint(imsiV + i)
|
|
||||||
if len(imsi) < imsiVlen {
|
|
||||||
imsi = fmt.Sprintf("%0*s", imsiVlen, imsi)
|
|
||||||
}
|
|
||||||
subUser.Imsi = imsi
|
|
||||||
|
|
||||||
// IP会自动递增
|
|
||||||
if len(subUser.StaticIp) > 5 {
|
|
||||||
parts := strings.Split(subUser.StaticIp, ".")
|
|
||||||
lastPart := parts[3]
|
|
||||||
lastNum, _ := strconv.Atoi(lastPart)
|
|
||||||
lastNum += i
|
|
||||||
newLastPart := strconv.Itoa(lastNum)
|
|
||||||
parts[3] = newLastPart
|
|
||||||
newIP := strings.Join(parts, ".")
|
|
||||||
subUser.StaticIp = newIP
|
|
||||||
}
|
|
||||||
|
|
||||||
subUser.EpsDat = fmt.Sprintf("%s,%s,%s,%s,%s,%s,2,%s,%s", subUser.EpsFlag, subUser.EpsOdb, subUser.HplmnOdb, subUser.Ard, subUser.Epstpl, subUser.ContextId, subUser.ApnContext, subUser.StaticIp)
|
|
||||||
|
|
||||||
arr = append(arr, subUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.repoSunUser.Inserts(arr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertCSV UDM签约用户-批量添加
|
|
||||||
func (r *ServiceUdmSubUser) InsertCSV(neID string, data []map[string]string) int64 {
|
|
||||||
var arr []model.UdmSubUser
|
|
||||||
for _, v := range data {
|
|
||||||
var subUser model.UdmSubUser
|
|
||||||
subUser.NeID = neID
|
|
||||||
if s, ok := v["imsi"]; ok {
|
|
||||||
subUser.Imsi = s
|
|
||||||
}
|
|
||||||
if s, ok := v["msisdn"]; ok {
|
|
||||||
subUser.Msisdn = s
|
|
||||||
}
|
|
||||||
if s, ok := v["ambr"]; ok {
|
|
||||||
subUser.Ambr = s
|
|
||||||
}
|
|
||||||
if s, ok := v["nssai"]; ok {
|
|
||||||
subUser.Nssai = s
|
|
||||||
}
|
|
||||||
if s, ok := v["arfb"]; ok {
|
|
||||||
subUser.Arfb = s
|
|
||||||
}
|
|
||||||
if s, ok := v["sar"]; ok {
|
|
||||||
subUser.Sar = s
|
|
||||||
}
|
|
||||||
if s, ok := v["rat"]; ok {
|
|
||||||
subUser.Rat = s
|
|
||||||
}
|
|
||||||
if s, ok := v["cn"]; ok {
|
|
||||||
subUser.Cn = s
|
|
||||||
}
|
|
||||||
if s, ok := v["smf_sel"]; ok {
|
|
||||||
subUser.SmfSel = s
|
|
||||||
}
|
|
||||||
if s, ok := v["sm_dat"]; ok {
|
|
||||||
subUser.SmData = s
|
|
||||||
}
|
|
||||||
if s, ok := v["eps_dat"]; ok {
|
|
||||||
subUser.EpsDat = s
|
|
||||||
arr := strings.Split(s, ",")
|
|
||||||
if len(arr) == 8 {
|
|
||||||
subUser.EpsFlag = arr[0]
|
|
||||||
subUser.EpsOdb = arr[1]
|
|
||||||
subUser.HplmnOdb = arr[2]
|
|
||||||
subUser.Ard = arr[3]
|
|
||||||
subUser.Epstpl = arr[4]
|
|
||||||
subUser.ContextId = arr[5]
|
|
||||||
subUser.ApnContext = arr[6]
|
|
||||||
subUser.StaticIp = arr[7]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if subUser.Imsi == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
arr = append(arr, subUser)
|
|
||||||
}
|
|
||||||
return r.repoSunUser.Inserts(arr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertTxt UDM签约用户-批量添加
|
|
||||||
func (r *ServiceUdmSubUser) InsertTxt(neID string, data [][]string) int64 {
|
|
||||||
var arr []model.UdmSubUser
|
|
||||||
for _, v := range data {
|
|
||||||
if len(v) < 10 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var subUser model.UdmSubUser
|
|
||||||
subUser.NeID = neID
|
|
||||||
subUser.Imsi = v[0]
|
|
||||||
subUser.Msisdn = v[1]
|
|
||||||
subUser.Ambr = v[2]
|
|
||||||
subUser.Nssai = v[3]
|
|
||||||
subUser.Arfb = v[4]
|
|
||||||
subUser.Sar = v[5]
|
|
||||||
subUser.Rat = v[6]
|
|
||||||
subUser.Cn = v[7]
|
|
||||||
subUser.SmfSel = v[8]
|
|
||||||
subUser.SmData = v[9]
|
|
||||||
if len(v) > 17 {
|
|
||||||
subUser.EpsFlag = v[10]
|
|
||||||
subUser.EpsOdb = v[11]
|
|
||||||
subUser.HplmnOdb = v[12]
|
|
||||||
subUser.Ard = v[13]
|
|
||||||
subUser.Epstpl = v[14]
|
|
||||||
subUser.ContextId = v[15]
|
|
||||||
subUser.ApnContext = v[16]
|
|
||||||
subUser.StaticIp = v[17]
|
|
||||||
subUser.EpsDat = strings.Join(v[10:], ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
if subUser.Imsi == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
arr = append(arr, subUser)
|
|
||||||
}
|
|
||||||
return r.repoSunUser.Inserts(arr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM签约用户-批量添加4G用户
|
|
||||||
func (r *ServiceUdmSubUser) Insert4G(neID string, subUser model.UdmSubUser) int64 {
|
|
||||||
return r.repoSunUser.Insert4G(neID, subUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM签约用户-修改更新
|
|
||||||
func (r *ServiceUdmSubUser) Update(neID string, subUser model.UdmSubUser) int64 {
|
|
||||||
return r.repoSunUser.Update(neID, subUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update4GIP UDM签约用户-批量修改4G IP
|
|
||||||
func (r *ServiceUdmSubUser) Update4GIP(neID string, subUser model.UdmSubUser) int64 {
|
|
||||||
return r.repoSunUser.Update4GIP(neID, subUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update4GIP UDM签约用户-批量修改sm-data
|
|
||||||
func (r *ServiceUdmSubUser) UpdateSmData(neID string, subUser model.UdmSubUser) int64 {
|
|
||||||
return r.repoSunUser.UpdateSmData(neID, subUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM签约用户-删除单个
|
|
||||||
func (r *ServiceUdmSubUser) Delete(neID, imsi string) int64 {
|
|
||||||
return r.repoSunUser.Delete(neID, imsi)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert UDM签约用户-删除范围
|
|
||||||
func (r *ServiceUdmSubUser) Deletes(neID, imsi, num string) int64 {
|
|
||||||
return r.repoSunUser.Deletes(neID, imsi, num)
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
package account
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
sysMenuService "be.ems/features/sys_menu/service"
|
|
||||||
sysRoleService "be.ems/features/sys_role/service"
|
|
||||||
"be.ems/lib/core/cache"
|
|
||||||
"be.ems/lib/core/vo"
|
|
||||||
"be.ems/lib/dborm"
|
|
||||||
srcConfig "be.ems/src/framework/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 登录缓存用户信息
|
|
||||||
func CacheLoginUser(user *dborm.User) {
|
|
||||||
// 过期时间
|
|
||||||
expiresStr, err := dborm.XormGetConfigValue("Security", "sessionExpires")
|
|
||||||
if err != nil {
|
|
||||||
expiresStr = "18000"
|
|
||||||
}
|
|
||||||
expiresValue, _ := strconv.Atoi(expiresStr)
|
|
||||||
expireTime := time.Duration(expiresValue) * time.Second
|
|
||||||
|
|
||||||
nowTime := time.Now().UnixMilli()
|
|
||||||
|
|
||||||
// 登录用户
|
|
||||||
loginUser := vo.LoginUser{
|
|
||||||
UserID: fmt.Sprint(user.Id),
|
|
||||||
UserName: user.Name,
|
|
||||||
ExpireTime: nowTime + expireTime.Milliseconds(),
|
|
||||||
LoginTime: nowTime,
|
|
||||||
User: *user,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否管理员
|
|
||||||
if srcConfig.IsAdmin(loginUser.UserID) {
|
|
||||||
loginUser.Permissions = []string{"*:*:*"}
|
|
||||||
} else {
|
|
||||||
// 获取权限标识
|
|
||||||
loginUser.Permissions = sysMenuService.NewRepoSysMenu.SelectMenuPermsByUserId(loginUser.UserID)
|
|
||||||
// 获取角色信息
|
|
||||||
loginUser.User.Roles = sysRoleService.NewRepoSysRole.SelectRoleListByUserId(loginUser.UserID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 缓存时间
|
|
||||||
cache.SetLocalTTL(user.AccountId, loginUser, time.Duration(expireTime))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清除缓存用户信息
|
|
||||||
func ClearLoginUser(accountId string) {
|
|
||||||
cache.DeleteLocalTTL(accountId)
|
|
||||||
}
|
|
||||||
@@ -10,9 +10,9 @@ import (
|
|||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"be.ems/features/sys_role/model"
|
|
||||||
"be.ems/lib/log"
|
"be.ems/lib/log"
|
||||||
"be.ems/lib/oauth"
|
"be.ems/lib/oauth"
|
||||||
|
"be.ems/src/modules/system/model"
|
||||||
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
@@ -1402,11 +1402,11 @@ type MeasureThreshold struct {
|
|||||||
type NeSoftware struct {
|
type NeSoftware struct {
|
||||||
Id int `json:"id" xorm:"pk 'id' autoincr"`
|
Id int `json:"id" xorm:"pk 'id' autoincr"`
|
||||||
NeType string `json:"neType" xorm:"ne_type"`
|
NeType string `json:"neType" xorm:"ne_type"`
|
||||||
FileName string `json:"neName" xorm:"file_name"`
|
FileName string `json:"fileName" xorm:"name"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path" xorm:"path"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version" `
|
||||||
Md5Sum string `json:"md5Sum" xorm:"md5_sum"`
|
Md5Sum string `json:"md5Sum" xorm:"-"`
|
||||||
Comment string `json:"comment"`
|
Comment string `json:"comment" xorm:"description"`
|
||||||
// Status string `json:"status"`
|
// Status string `json:"status"`
|
||||||
UpdateTime string `json:"createTime" xorm:"-" `
|
UpdateTime string `json:"createTime" xorm:"-" `
|
||||||
}
|
}
|
||||||
@@ -1415,18 +1415,18 @@ type NeVersion struct {
|
|||||||
Id int `json:"id" xorm:"pk 'id' autoincr"`
|
Id int `json:"id" xorm:"pk 'id' autoincr"`
|
||||||
NeType string `json:"neType" xorm:"ne_type"`
|
NeType string `json:"neType" xorm:"ne_type"`
|
||||||
NeId string `json:"neId" xorm:"ne_id"`
|
NeId string `json:"neId" xorm:"ne_id"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version" `
|
||||||
FilePath string `json:"filePath" xorm:"file_path"`
|
FilePath string `json:"filePath" xorm:"path"`
|
||||||
NewVersion string `json:"newVersion" xorm:"new_version"`
|
NewVersion string `json:"newVersion" xorm:"new_version"`
|
||||||
NewFile string `json:"newFile" xorm:"new_file"`
|
NewFile string `json:"newFile" xorm:"new_path"`
|
||||||
PreVersion string `json:"preVersion" xorm:"pre_version"`
|
PreVersion string `json:"preVersion" xorm:"pre_version"`
|
||||||
PreFile string `json:"preFile" xorm:"pre_file"`
|
PreFile string `json:"preFile" xorm:"pre_path"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status" xorm:"status"`
|
||||||
UpdateTime string `json:"createTime" xorm:"-" `
|
UpdateTime string `json:"createTime" xorm:"-" `
|
||||||
}
|
}
|
||||||
|
|
||||||
func XormGetDataBySQL(sql string) (*[]map[string]string, error) {
|
func XormGetDataBySQL(sql string) (*[]map[string]string, error) {
|
||||||
//log.Debug("XormGetDataBySQL processing... ")
|
log.Debug("XormGetDataBySQL processing... ")
|
||||||
|
|
||||||
rows := make([]map[string]string, 0)
|
rows := make([]map[string]string, 0)
|
||||||
rows, err := DbClient.XEngine.QueryString(sql)
|
rows, err := DbClient.XEngine.QueryString(sql)
|
||||||
@@ -1708,25 +1708,26 @@ func IsPermissionAllowed(token, method, module, dbname, tbname, pack string) (bo
|
|||||||
type NeLicense struct {
|
type NeLicense struct {
|
||||||
NeType string `json:"neType" xorm:"ne_type"`
|
NeType string `json:"neType" xorm:"ne_type"`
|
||||||
NeID string `json:"neID" xorm:"ne_id"`
|
NeID string `json:"neID" xorm:"ne_id"`
|
||||||
SerialNo string `json:"serialNo" xorm:"serial_no"`
|
SerialNo string `json:"serialNo" xorm:"serial_num"`
|
||||||
Capcity int `json:"capcity" xorm:"capcity"`
|
Capcity int `json:"capcity" xorm:"-"`
|
||||||
Used int `json:"used" xorm:"used"`
|
Used int `json:"used" xorm:"-"`
|
||||||
FeatureEnabled string `json:"featureEnabled" xorm:"feature_enabled"`
|
FeatureEnabled string `json:"featureEnabled" xorm:"-"`
|
||||||
ExpirationDate string `json:"expirationDate" xorm:"expiration_date"`
|
ExpirationDate string `json:"expirationDate" xorm:"expiry_date"`
|
||||||
Status string `json:"status" xorm:"status"`
|
Status string `json:"status" xorm:"status"`
|
||||||
Path string `json:"path" xorm:"path"`
|
Path string `json:"path" xorm:"license_path"`
|
||||||
FileName string `json:"file_name" xorm:"file_name"`
|
FileName string `json:"file_name" xorm:"-"`
|
||||||
Comment string `json:"comment" xorm:"comment"`
|
Comment string `json:"comment" xorm:"remark"`
|
||||||
CreatedAt string `json:"createdAt" xorm:"-"`
|
CreatedAt string `json:"createdAt" xorm:"-"`
|
||||||
UpdatedAt string `json:"updatedAt" xorm:"-"`
|
UpdatedAt string `json:"updatedAt" xorm:"-"`
|
||||||
DeletedAt string `json:"deletedAt" xorm:"-"`
|
DeletedAt string `json:"deletedAt" xorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func XormAdjustmentNeLicense(neType, neID string, value int) (int64, error) {
|
func XormAdjustmentNeLicense(neType, neID string, value int) (int64, error) {
|
||||||
|
return 1, nil
|
||||||
//neLicense := NeLicense{NeType: neType, NeID: neID, Capability: value}
|
//neLicense := NeLicense{NeType: neType, NeID: neID, Capability: value}
|
||||||
// session.LogoutTime.Valid = true
|
// session.LogoutTime.Valid = true
|
||||||
// session.LogoutTime.Time = time.Now()
|
// session.LogoutTime.Time = time.Now()
|
||||||
res, err := xEngine.Exec("update ne_license set capcity=capcity+? where IFNULL(ne_type, '')=? and IFNULL(ne_id, '')=?", value, neType, neID)
|
// res, err := xEngine.Exec("update ne_license set capcity=capcity+? where IFNULL(ne_type, '')=? and IFNULL(ne_id, '')=?", value, neType, neID)
|
||||||
// defer xSession.Close()
|
// defer xSession.Close()
|
||||||
|
|
||||||
//affected, err := xSession.Table("ne_license").Where("ne_type=? and ne_id=?", neType, neID).Update(&neLicense)
|
//affected, err := xSession.Table("ne_license").Where("ne_type=? and ne_id=?", neType, neID).Update(&neLicense)
|
||||||
@@ -1734,25 +1735,26 @@ func XormAdjustmentNeLicense(neType, neID string, value int) (int64, error) {
|
|||||||
// //affected, err := xSession.Table("ne_license").SQL("ne_tye=? and ne_id=?", neType, neID).Update(session)
|
// //affected, err := xSession.Table("ne_license").SQL("ne_tye=? and ne_id=?", neType, neID).Update(session)
|
||||||
// err := xSession.SQL("update ne_license set capability=capability+? where ne_type=? and ne_id=?", value, neType, neID)
|
// err := xSession.SQL("update ne_license set capability=capability+? where ne_type=? and ne_id=?", value, neType, neID)
|
||||||
//xSession.Commit()
|
//xSession.Commit()
|
||||||
affected, err := res.RowsAffected()
|
// affected, err := res.RowsAffected()
|
||||||
return affected, err
|
// return affected, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func XormUpdateNeLicense(neType, neID string, capcity int) (int64, error) {
|
func XormUpdateNeLicense(neType, neID string, capcity int) (int64, error) {
|
||||||
var err error
|
return 1, nil
|
||||||
var res sql.Result
|
// var err error
|
||||||
if neType != "" && neID != "" {
|
// var res sql.Result
|
||||||
res, err = xEngine.Exec("update ne_license set capcity=? where ne_type=? and ne_id=?", capcity, neType, neID)
|
// if neType != "" && neID != "" {
|
||||||
} else if neType != "" && neID == "" {
|
// res, err = xEngine.Exec("update ne_license set capcity=? where ne_type=? and ne_id=?", capcity, neType, neID)
|
||||||
res, err = xEngine.Exec("update ne_license set capcity=? where ne_type=?", capcity, neType)
|
// } else if neType != "" && neID == "" {
|
||||||
} else if neType == "" && neID != "" {
|
// res, err = xEngine.Exec("update ne_license set capcity=? where ne_type=?", capcity, neType)
|
||||||
res, err = xEngine.Exec("update ne_license set capcity=? where ne_id=?", capcity, neID)
|
// } else if neType == "" && neID != "" {
|
||||||
} else {
|
// res, err = xEngine.Exec("update ne_license set capcity=? where ne_id=?", capcity, neID)
|
||||||
res, err = xEngine.Exec("update ne_license set capcity=?", capcity)
|
// } else {
|
||||||
}
|
// res, err = xEngine.Exec("update ne_license set capcity=?", capcity)
|
||||||
|
// }
|
||||||
|
|
||||||
affected, err := res.RowsAffected()
|
// affected, err := res.RowsAffected()
|
||||||
return affected, err
|
// return affected, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type NorthboundCm struct {
|
type NorthboundCm struct {
|
||||||
@@ -1777,21 +1779,21 @@ func XormGetNorthboundCm(neType string, cmResults *[]NorthboundCm) error {
|
|||||||
log.Info("XormGetNorthboundCm processing... ")
|
log.Info("XormGetNorthboundCm processing... ")
|
||||||
|
|
||||||
cmResult := new(NorthboundCm)
|
cmResult := new(NorthboundCm)
|
||||||
rows, err := xEngine.Table("northbound_cm").
|
rows, err := xEngine.Table("nbi_cm").
|
||||||
Distinct("object_type").
|
Distinct("object_type").
|
||||||
Where("`ne_type` = ?", neType).
|
Where("`ne_type` = ?", neType).
|
||||||
Desc("timestamp").
|
Desc("timestamp").
|
||||||
Cols("*").
|
Cols("*").
|
||||||
Rows(cmResult)
|
Rows(cmResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to get table northbound_cm:", err)
|
log.Error("Failed to get table nbi_cm:", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err := rows.Scan(cmResult)
|
err := rows.Scan(cmResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to get table northbound_cm:", err)
|
log.Error("Failed to get table nbi_cm:", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*cmResults = append(*cmResults, *cmResult)
|
*cmResults = append(*cmResults, *cmResult)
|
||||||
@@ -1803,14 +1805,14 @@ func XormGetNorthboundCmLatestObject(neType, neID, objectType string) (*Northbou
|
|||||||
log.Info("XormGetNorthboundCmLatestObject processing... ")
|
log.Info("XormGetNorthboundCmLatestObject processing... ")
|
||||||
|
|
||||||
cmResult := new(NorthboundCm)
|
cmResult := new(NorthboundCm)
|
||||||
_, err := xEngine.Table("northbound_cm").
|
_, err := xEngine.Table("nbi_cm").
|
||||||
Where("`ne_type`=? and `ne_id`=? and `object_type`=?", neType, neID, objectType).
|
Where("`ne_type`=? and `ne_id`=? and `object_type`=?", neType, neID, objectType).
|
||||||
Desc("timestamp").
|
Desc("timestamp").
|
||||||
Cols("*").
|
Cols("*").
|
||||||
Limit(1).
|
Limit(1).
|
||||||
Get(cmResult)
|
Get(cmResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to get table northbound_cm:", err)
|
log.Error("Failed to get table nbi_cm:", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -696,3 +696,33 @@ func IsRpmOrDebPackage(filePath string) int {
|
|||||||
|
|
||||||
return fileType
|
return fileType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RecurseStructToMap(obj any) map[string]any {
|
||||||
|
out := make(map[string]any)
|
||||||
|
v := reflect.ValueOf(obj)
|
||||||
|
if v.Kind() == reflect.Ptr {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归函数,用于处理嵌套结构体
|
||||||
|
var recurse func(reflect.Value) any
|
||||||
|
recurse = func(value reflect.Value) any {
|
||||||
|
if value.Kind() == reflect.Struct {
|
||||||
|
nestedOut := make(map[string]any)
|
||||||
|
for i := 0; i < value.NumField(); i++ {
|
||||||
|
nestedOut[value.Type().Field(i).Name] = recurse(value.Field(i))
|
||||||
|
}
|
||||||
|
return nestedOut
|
||||||
|
} else if value.Kind() == reflect.Ptr {
|
||||||
|
return recurse(value.Elem())
|
||||||
|
}
|
||||||
|
return value.Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
t := v.Type()
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
f := v.Field(i)
|
||||||
|
out[t.Field(i).Name] = recurse(f)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"be.ems/lib/services"
|
"be.ems/lib/services"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 已禁用
|
||||||
// 登录策略限制登录时间和访问ip范围
|
// 登录策略限制登录时间和访问ip范围
|
||||||
func ArrowIPAddr(next http.Handler) http.Handler {
|
func ArrowIPAddr(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
tokenUtils "be.ems/src/framework/utils/token"
|
tokenUtils "be.ems/src/framework/utils/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 已禁用由Gin部分接管
|
||||||
// Authorize 用户身份授权认证校验
|
// Authorize 用户身份授权认证校验
|
||||||
//
|
//
|
||||||
// 只需含有其中角色 "hasRoles": {"xxx"},
|
// 只需含有其中角色 "hasRoles": {"xxx"},
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 已禁用由Gin部分接管
|
||||||
// Cors 跨域
|
// Cors 跨域
|
||||||
func Cors(next http.Handler) http.Handler {
|
func Cors(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"be.ems/lib/core/utils/ctx"
|
||||||
"be.ems/lib/core/utils/parse"
|
"be.ems/lib/core/utils/parse"
|
||||||
"be.ems/lib/dborm"
|
|
||||||
"be.ems/src/framework/constants/common"
|
"be.ems/src/framework/constants/common"
|
||||||
"be.ems/src/framework/middleware/collectlogs"
|
"be.ems/src/framework/middleware/collectlogs"
|
||||||
"be.ems/src/framework/utils/ip2region"
|
"be.ems/src/framework/utils/ip2region"
|
||||||
@@ -47,13 +47,7 @@ func LogOperate(options collectlogs.Options) func(http.Handler) http.Handler {
|
|||||||
funcName = funcName[lastDotIndex+1:]
|
funcName = funcName[lastDotIndex+1:]
|
||||||
|
|
||||||
// 用户名
|
// 用户名
|
||||||
username := "-"
|
username := ctx.LoginUserToUserName(r)
|
||||||
accessToken := r.Header.Get("AccessToken")
|
|
||||||
if accessToken != "" {
|
|
||||||
// 验证令牌 == 这里直接查数据库session
|
|
||||||
se, _ := dborm.XormUpdateSessionShakeTime(accessToken)
|
|
||||||
username = se.AccountId
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析ip地址
|
// 解析ip地址
|
||||||
ip := strings.Split(r.RemoteAddr, ":")[0]
|
ip := strings.Split(r.RemoteAddr, ":")[0]
|
||||||
|
|||||||
@@ -13,21 +13,12 @@ import (
|
|||||||
"be.ems/features/fm"
|
"be.ems/features/fm"
|
||||||
"be.ems/features/lm"
|
"be.ems/features/lm"
|
||||||
"be.ems/features/mml"
|
"be.ems/features/mml"
|
||||||
"be.ems/features/monitor/monitor"
|
|
||||||
"be.ems/features/monitor/psnet"
|
|
||||||
"be.ems/features/nbi"
|
"be.ems/features/nbi"
|
||||||
"be.ems/features/pm"
|
"be.ems/features/pm"
|
||||||
"be.ems/features/security"
|
"be.ems/features/security"
|
||||||
"be.ems/features/sm"
|
"be.ems/features/sm"
|
||||||
"be.ems/features/state"
|
"be.ems/features/state"
|
||||||
sysconfig "be.ems/features/sys_config"
|
|
||||||
sysdictdata "be.ems/features/sys_dict_data"
|
|
||||||
sysdicttype "be.ems/features/sys_dict_type"
|
|
||||||
sysmenu "be.ems/features/sys_menu"
|
|
||||||
sysrole "be.ems/features/sys_role"
|
|
||||||
sysuser "be.ems/features/sys_user"
|
|
||||||
"be.ems/features/trace"
|
"be.ems/features/trace"
|
||||||
udmuser "be.ems/features/udm_user"
|
|
||||||
"be.ems/features/ue"
|
"be.ems/features/ue"
|
||||||
"be.ems/lib/midware"
|
"be.ems/lib/midware"
|
||||||
"be.ems/lib/services"
|
"be.ems/lib/services"
|
||||||
@@ -233,16 +224,6 @@ func init() {
|
|||||||
Register("PUT", trace.CustomUriTraceTask, trace.PutTraceTaskToNF, nil)
|
Register("PUT", trace.CustomUriTraceTask, trace.PutTraceTaskToNF, nil)
|
||||||
Register("DELETE", trace.CustomUriTraceTask, trace.DeleteTraceTaskToNF, nil)
|
Register("DELETE", trace.CustomUriTraceTask, trace.DeleteTraceTaskToNF, nil)
|
||||||
|
|
||||||
// 网元发送执行 pcap抓包任务
|
|
||||||
Register("POST", trace.UriTcpdumpTask, trace.TcpdumpNeTask, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_INSERT)))
|
|
||||||
Register("POST", trace.CustomUriTcpdumpTask, trace.TcpdumpNeTask, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_INSERT)))
|
|
||||||
// 网元发送执行 抓包下载pcap文件
|
|
||||||
Register("POST", trace.UriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_EXPORT)))
|
|
||||||
Register("POST", trace.CustomUriTcpdumpPcapDownload, trace.TcpdumpPcapDownload, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_EXPORT)))
|
|
||||||
// 网元发送执行UPF pcap抓包
|
|
||||||
Register("POST", trace.UriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_INSERT)))
|
|
||||||
Register("POST", trace.CustomUriTcpdumpNeUPFTask, trace.TcpdumpNeUPFTask, midware.LogOperate(collectlogs.OptionNew("Packet Capturing Task", collectlogs.BUSINESS_TYPE_INSERT)))
|
|
||||||
|
|
||||||
// file management
|
// file management
|
||||||
Register("POST", file.UriFile, file.UploadFile, midware.LogOperate(collectlogs.OptionNew("File", collectlogs.BUSINESS_TYPE_INSERT)))
|
Register("POST", file.UriFile, file.UploadFile, midware.LogOperate(collectlogs.OptionNew("File", collectlogs.BUSINESS_TYPE_INSERT)))
|
||||||
Register("GET", file.UriFile, file.DownloadFile, midware.LogOperate(collectlogs.OptionNew("File", collectlogs.BUSINESS_TYPE_OTHER)))
|
Register("GET", file.UriFile, file.DownloadFile, midware.LogOperate(collectlogs.OptionNew("File", collectlogs.BUSINESS_TYPE_OTHER)))
|
||||||
@@ -300,23 +281,17 @@ func init() {
|
|||||||
Register("GET", ue.UriNSSFSubscriptions, ue.GetSubscriptionsFromNSSF, nil)
|
Register("GET", ue.UriNSSFSubscriptions, ue.GetSubscriptionsFromNSSF, nil)
|
||||||
Register("GET", ue.CustomUriNSSFSubscriptions, ue.GetSubscriptionsFromNSSF, nil)
|
Register("GET", ue.CustomUriNSSFSubscriptions, ue.GetSubscriptionsFromNSSF, nil)
|
||||||
|
|
||||||
Register("POST", cdr.UriCDREvent, cdr.PostCDREventFromNF, nil)
|
// ims cdr event
|
||||||
Register("POST", cdr.CustomUriCDREvent, cdr.PostCDREventFromNF, nil)
|
Register("POST", cdr.UriIMSCDREvent, cdr.PostCDREventFromIMS, nil)
|
||||||
|
Register("POST", cdr.CustomUriIMSCDREvent, cdr.PostCDREventFromIMS, nil)
|
||||||
|
|
||||||
// UE event
|
// smf cdr event
|
||||||
|
Register("POST", cdr.UriSMFCDREvent, cdr.PostCDREventFromSMF, nil)
|
||||||
|
Register("POST", cdr.CustomUriSMFCDREvent, cdr.PostCDREventFromSMF, nil)
|
||||||
|
|
||||||
|
// UE event AMF上报的UE事件, 无前缀给到Gin处理
|
||||||
//Register("POST", event.UriUEEvent, event.PostUEEventFromAMF, nil)
|
//Register("POST", event.UriUEEvent, event.PostUEEventFromAMF, nil)
|
||||||
|
|
||||||
// 进程网络
|
|
||||||
Register("GET", psnet.UriWs, psnet.ProcessWs, nil)
|
|
||||||
Register("POST", psnet.UriStop, psnet.StopProcess, nil)
|
|
||||||
Register("POST", psnet.UriPing, psnet.Ping, nil)
|
|
||||||
|
|
||||||
// 主机CPU内存监控
|
|
||||||
Register("POST", monitor.UriLoad, monitor.LoadMonitor, nil)
|
|
||||||
Register("GET", monitor.UriNetOpt, monitor.Netoptions, nil)
|
|
||||||
Register("GET", monitor.UriIPAddr, monitor.IPAddr, nil)
|
|
||||||
Register("GET", monitor.UriIoOpt, monitor.Iooptions, nil)
|
|
||||||
|
|
||||||
// 文件资源
|
// 文件资源
|
||||||
Register("GET", file.UriDiskList, file.DiskList, nil)
|
Register("GET", file.UriDiskList, file.DiskList, nil)
|
||||||
Register("POST", file.UriListFiles, file.ListFiles, nil)
|
Register("POST", file.UriListFiles, file.ListFiles, nil)
|
||||||
@@ -337,56 +312,6 @@ func init() {
|
|||||||
Register("POST", lm.ExtBackupDataUri, lm.ExtDatabaseBackupData, nil)
|
Register("POST", lm.ExtBackupDataUri, lm.ExtDatabaseBackupData, nil)
|
||||||
Register("POST", lm.CustomExtBackupDataUri, lm.ExtDatabaseBackupData, nil)
|
Register("POST", lm.CustomExtBackupDataUri, lm.ExtDatabaseBackupData, nil)
|
||||||
|
|
||||||
// 系统登录
|
|
||||||
Register("POST", security.UriLogin, security.LoginOMC, nil)
|
|
||||||
Register("POST", security.CustomUriLogin, security.LoginOMC, nil)
|
|
||||||
|
|
||||||
// 获取验证码
|
|
||||||
Register("GET", security.UriCaptchaImage, security.CaptchaImage, nil)
|
|
||||||
Register("GET", security.CustomUriCaptchaImage, security.CaptchaImage, nil)
|
|
||||||
|
|
||||||
// 登录用户信息
|
|
||||||
Register("GET", security.UriUserInfo, security.UserInfo, midware.Authorize(nil))
|
|
||||||
Register("GET", security.CustomUriUserInfo, security.UserInfo, midware.Authorize(nil))
|
|
||||||
|
|
||||||
// 登录用户路由信息
|
|
||||||
Register("GET", security.UriRouters, security.Routers, midware.Authorize(nil))
|
|
||||||
Register("GET", security.CustomUriRouters, security.Routers, midware.Authorize(nil))
|
|
||||||
|
|
||||||
// 参数配置信息接口添加到路由
|
|
||||||
for _, v := range sysconfig.Routers() {
|
|
||||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型信息接口添加到路由
|
|
||||||
for _, v := range sysdicttype.Routers() {
|
|
||||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 字典类型对应的字典数据信息接口添加到路由
|
|
||||||
for _, v := range sysdictdata.Routers() {
|
|
||||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 菜单接口添加到路由
|
|
||||||
for _, v := range sysmenu.Routers() {
|
|
||||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 角色接口添加到路由
|
|
||||||
for _, v := range sysrole.Routers() {
|
|
||||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户接口添加到路由
|
|
||||||
for _, v := range sysuser.Routers() {
|
|
||||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UDM 用户信息接口添加到路由
|
|
||||||
for _, v := range udmuser.Routers() {
|
|
||||||
Register(v.Method, v.Pattern, v.Handler, v.Middleware)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// To resolv rest POST/PUT/DELETE/PATCH cross domain
|
// To resolv rest POST/PUT/DELETE/PATCH cross domain
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ type YamlConfig struct {
|
|||||||
Count int `yaml:"count"`
|
Count int `yaml:"count"`
|
||||||
} `yaml:"logger"`
|
} `yaml:"logger"`
|
||||||
|
|
||||||
|
Pprof struct {
|
||||||
|
Enabled bool `yaml:"enabled"`
|
||||||
|
Addr string `yaml:"addr"`
|
||||||
|
} `yaml:"pprof"`
|
||||||
|
|
||||||
// Rest []struct {
|
// Rest []struct {
|
||||||
// IPv4 string `yaml:"ipv4"`
|
// IPv4 string `yaml:"ipv4"`
|
||||||
// IPv6 string `yaml:"ipv6"`
|
// IPv6 string `yaml:"ipv6"`
|
||||||
@@ -76,30 +81,7 @@ type YamlConfig struct {
|
|||||||
CmdTimeout int `yaml:"cmdTimeout"`
|
CmdTimeout int `yaml:"cmdTimeout"`
|
||||||
} `yaml:"omc"`
|
} `yaml:"omc"`
|
||||||
|
|
||||||
Alarm struct {
|
Alarm AlarmConfig `yaml:"alarm"`
|
||||||
ForwardAlarm bool `yaml:"forwardAlarm"`
|
|
||||||
SMProxy string `yaml:"smProxy"`
|
|
||||||
Email struct {
|
|
||||||
Smtp string `yaml:"smtp"`
|
|
||||||
Port uint16 `yaml:"port"`
|
|
||||||
User string `yaml:"user"`
|
|
||||||
Password string `yaml:"password"`
|
|
||||||
TlsSkipVerify bool `yaml:"tlsSkipVerify"`
|
|
||||||
} `yaml:"email"`
|
|
||||||
SMS struct {
|
|
||||||
ApiURL string `yaml:"apiURL"`
|
|
||||||
AccessKeyID string `yaml:"AccessKeyID"`
|
|
||||||
AccessKeySecret string `yaml:"accessKeySecret"`
|
|
||||||
SignName string `yaml:"signName"`
|
|
||||||
TemplateCode string `yaml:"templateCode"`
|
|
||||||
} `yaml:"sms"`
|
|
||||||
SMSC struct {
|
|
||||||
Addr string `yaml:"addr"`
|
|
||||||
SystemID string `yaml:"systemID"`
|
|
||||||
Password string `yaml:"password"`
|
|
||||||
SystemType string `yaml:"systemType"`
|
|
||||||
} `yaml:"smsc"`
|
|
||||||
} `yaml:"alarm"`
|
|
||||||
|
|
||||||
MML MMLParam `yaml:"mml"`
|
MML MMLParam `yaml:"mml"`
|
||||||
|
|
||||||
@@ -164,6 +146,32 @@ type DbConfig struct {
|
|||||||
Backup string `yaml:"backup"`
|
Backup string `yaml:"backup"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AlarmConfig struct {
|
||||||
|
SplitEventAlarm bool `yaml:"splitEventAlarm"`
|
||||||
|
ForwardAlarm bool `yaml:"forwardAlarm"`
|
||||||
|
SMProxy string `yaml:"smProxy"`
|
||||||
|
Email struct {
|
||||||
|
Smtp string `yaml:"smtp"`
|
||||||
|
Port uint16 `yaml:"port"`
|
||||||
|
User string `yaml:"user"`
|
||||||
|
Password string `yaml:"password"`
|
||||||
|
TlsSkipVerify bool `yaml:"tlsSkipVerify"`
|
||||||
|
} `yaml:"email"`
|
||||||
|
SMS struct {
|
||||||
|
ApiURL string `yaml:"apiURL"`
|
||||||
|
AccessKeyID string `yaml:"AccessKeyID"`
|
||||||
|
AccessKeySecret string `yaml:"accessKeySecret"`
|
||||||
|
SignName string `yaml:"signName"`
|
||||||
|
TemplateCode string `yaml:"templateCode"`
|
||||||
|
} `yaml:"sms"`
|
||||||
|
SMSC struct {
|
||||||
|
Addr string `yaml:"addr"`
|
||||||
|
SystemID string `yaml:"systemID"`
|
||||||
|
Password string `yaml:"password"`
|
||||||
|
SystemType string `yaml:"systemType"`
|
||||||
|
} `yaml:"smsc"`
|
||||||
|
}
|
||||||
|
|
||||||
type MMLParam struct {
|
type MMLParam struct {
|
||||||
Port int `yaml:"port"`
|
Port int `yaml:"port"`
|
||||||
Port2 int `yaml:"port2"`
|
Port2 int `yaml:"port2"`
|
||||||
@@ -175,7 +183,6 @@ type MMLParam struct {
|
|||||||
User string `yaml:"user"`
|
User string `yaml:"user"`
|
||||||
Password string `ymal:"password"`
|
Password string `ymal:"password"`
|
||||||
MmlHome string `yaml:"mmlHome"`
|
MmlHome string `yaml:"mmlHome"`
|
||||||
Upload string `yaml:"upload"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestDatas struct {
|
type TestDatas struct {
|
||||||
@@ -223,6 +230,9 @@ func NewYamlConfig() YamlConfig {
|
|||||||
SizeCol: 128,
|
SizeCol: 128,
|
||||||
BufferSize: 65535,
|
BufferSize: 65535,
|
||||||
},
|
},
|
||||||
|
Alarm: AlarmConfig{
|
||||||
|
SplitEventAlarm: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,20 +3,40 @@
|
|||||||
# duration: rotation time with xx hours, example: 1/12/24 hours
|
# duration: rotation time with xx hours, example: 1/12/24 hours
|
||||||
# count: rotation count of log, default is 30 rotation
|
# count: rotation count of log, default is 30 rotation
|
||||||
logger:
|
logger:
|
||||||
file: d:/local.git/be.ems/restagent/log/restagent-t.log
|
file: d:/local.git/be.ems/restagent/log/restagent.log
|
||||||
level: trace
|
level: trace
|
||||||
duration: 24
|
duration: 24
|
||||||
count: 2
|
count: 2
|
||||||
|
|
||||||
# rest agent listen ipv4/v6 and port, support multiple routines
|
# rest agent listen ipv4/v6 and port, support multiple routines
|
||||||
# ip: 0.0.0.0 or ::0, support IPv4/v6
|
# ip: 0.0.0.0 or ::0, support IPv4/v6
|
||||||
|
# clientAuthType: 0:NoClientCert (default), 1:RequestClientCert, 2:RequireAnyClientCert,
|
||||||
|
# 3:VerifyClientCertIfGiven, 4:RequireAndVerifyClientCerts
|
||||||
rest:
|
rest:
|
||||||
- ipv4: 0.0.0.0
|
- ipv4: 0.0.0.0
|
||||||
ipv6:
|
ipv6:
|
||||||
port: 33030
|
port: 33030
|
||||||
- ipv4: 0.0.0.0
|
- ipv4: 0.0.0.0
|
||||||
ipv6:
|
ipv6:
|
||||||
port: 36060
|
port: 33443
|
||||||
|
scheme: https
|
||||||
|
clientAuthType: 0
|
||||||
|
caFile: ./etc/certs/omc-ca.crt
|
||||||
|
certFile: ./etc/certs/omc-server.crt
|
||||||
|
keyFile: ./etc/certs/omc-server.key
|
||||||
|
|
||||||
|
webServer:
|
||||||
|
enabled: false
|
||||||
|
rootDir: d:/local.git/fe.ems.vue3/dist
|
||||||
|
listen:
|
||||||
|
- addr: :80
|
||||||
|
schema: http
|
||||||
|
- addr: :443
|
||||||
|
scheme: https
|
||||||
|
clientAuthType: 0
|
||||||
|
caFile: ./etc/certs/omc-ca.crt
|
||||||
|
certFile: ./etc/certs/omc-server.crt
|
||||||
|
keyFile: ./etc/certs/omc-server.key
|
||||||
|
|
||||||
database:
|
database:
|
||||||
type: mysql
|
type: mysql
|
||||||
@@ -25,6 +45,7 @@ database:
|
|||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 33066
|
port: 33066
|
||||||
name: omc_db
|
name: omc_db
|
||||||
|
connParam: charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True
|
||||||
backup: d:/local.git/be.ems/restagent/database
|
backup: d:/local.git/be.ems/restagent/database
|
||||||
|
|
||||||
# Redis 缓存数据,数据源声明全小写
|
# Redis 缓存数据,数据源声明全小写
|
||||||
@@ -33,25 +54,34 @@ redis:
|
|||||||
# OMC系统使用库
|
# OMC系统使用库
|
||||||
default:
|
default:
|
||||||
port: 6379 # Redis port
|
port: 6379 # Redis port
|
||||||
host: "192.168.2.166" # Redis host
|
host: "192.168.2.219" # Redis host
|
||||||
password: ""
|
password: "123456"
|
||||||
db: 10 # Redis db_num
|
db: 10 # Redis db_num
|
||||||
# UDM网元用户库
|
# UDM网元用户库
|
||||||
udmuser:
|
udmuser:
|
||||||
port: 6379 # Redis port
|
port: 6379 # Redis port
|
||||||
host: "192.168.2.166"
|
host: "192.168.2.219"
|
||||||
password: ""
|
password: "123456"
|
||||||
db: 0 # Redis db_num
|
db: 0 # Redis db_num
|
||||||
# 多个数据源时可以用这个指定默认的数据源
|
# 多个数据源时可以用这个指定默认的数据源
|
||||||
defaultDataSourceName: "default"
|
defaultDataSourceName: "default"
|
||||||
|
|
||||||
|
# sleep: time delay for after write buffer (millisecond)
|
||||||
|
# deadLine: timeout for io read and write (second)
|
||||||
mml:
|
mml:
|
||||||
port: 4100
|
port: 4100
|
||||||
|
port2: 5002
|
||||||
sleep: 200
|
sleep: 200
|
||||||
|
deadLine: 10
|
||||||
|
sizeRow: 100
|
||||||
|
sizeCol: 128
|
||||||
|
bufferSize: 65535
|
||||||
user: admin
|
user: admin
|
||||||
password: admin
|
password: admin
|
||||||
mmlHome: ./mmlhome
|
mmlHome: ./mmlhome
|
||||||
|
upload: /home/manager
|
||||||
|
|
||||||
|
# NE config
|
||||||
ne:
|
ne:
|
||||||
user: root
|
user: root
|
||||||
etcdir: /usr/local/etc
|
etcdir: /usr/local/etc
|
||||||
@@ -59,6 +89,13 @@ ne:
|
|||||||
omcdir: /usr/local/omc
|
omcdir: /usr/local/omc
|
||||||
scpdir: /tmp
|
scpdir: /tmp
|
||||||
licensedir: /usr/local/etc/{neType}/license
|
licensedir: /usr/local/etc/{neType}/license
|
||||||
|
# backup etc list of IMS,no space
|
||||||
|
etcListIMS: '{*.yaml,mmtel,vars.cfg}'
|
||||||
|
etcListDefault: '{*.yaml,*.conf,*.cfg}'
|
||||||
|
# true/false to overwrite config file when dpkg ne software
|
||||||
|
dpkgOverwrite: false
|
||||||
|
# dpkg timeout (second)
|
||||||
|
dpkgTimeout: 180
|
||||||
|
|
||||||
# chk2ne: true/false, if put OmcNeConfig parameters to NE
|
# chk2ne: true/false, if put OmcNeConfig parameters to NE
|
||||||
omc:
|
omc:
|
||||||
@@ -71,42 +108,55 @@ omc:
|
|||||||
vendor: ""
|
vendor: ""
|
||||||
dn: 4600
|
dn: 4600
|
||||||
chk2ne: false
|
chk2ne: false
|
||||||
sn: 13750650
|
sn: "-"
|
||||||
checksign: false
|
checksign: false
|
||||||
|
rootDir: ./
|
||||||
|
binDir: ./bin
|
||||||
backup: ./backup
|
backup: ./backup
|
||||||
upload: ./upload
|
upload: ./upload
|
||||||
frontUpload: d:/local.git/fe.ems/upload
|
frontUpload: d:/local.git/fe.ems/upload
|
||||||
frontTraceDir: d:/local.git/fe.ems/trace
|
frontTraceDir: d:/local.git/fe.ems/trace
|
||||||
software: ./software
|
software: ./software
|
||||||
license: ./license
|
license: ./license
|
||||||
gtpUri: gtp:192.168.2.119:2152
|
gtpUri: gtp:192.168.2.219:2152
|
||||||
checkContentType: false
|
checkContentType: false
|
||||||
testMode: false
|
testMode: false
|
||||||
rbacMode: true
|
rbacMode: true
|
||||||
runDir:
|
runDir:
|
||||||
|
cmdTimeout: 120
|
||||||
|
|
||||||
# Alarm module setting
|
# Alarm module setting
|
||||||
# Forward interface:
|
# Forward interface:
|
||||||
# email/sms
|
# email/sms
|
||||||
|
# smProxy: sms(Short Message Service)/smsc(SMS Centre)
|
||||||
alarm:
|
alarm:
|
||||||
forwardAlarm: true
|
forwardAlarm: true
|
||||||
email:
|
email:
|
||||||
smtp: smtp@xxx.com.cn
|
smtp: mail.agrandtech.com
|
||||||
port: 25
|
port: 25
|
||||||
user: smtpuser
|
user: smtpext@agrandtech.com
|
||||||
password: smtpuser@omc
|
password: "1000smtp@omc!"
|
||||||
|
# TLS skip verify: true/false
|
||||||
|
tlsSkipVerify: true
|
||||||
|
smProxy: smsc
|
||||||
sms:
|
sms:
|
||||||
apiURL: http://smsc.xxx.com.cn/
|
apiURL: http://smsc.xxx.com/
|
||||||
accessKeyID: xxxx
|
accessKeyID: xxxx
|
||||||
accessKeySecret: xxxx
|
accessKeySecret: xxxx
|
||||||
signName: xxx SMSC
|
signName: xxx SMSC
|
||||||
templateCode: 1000
|
templateCode: 1000
|
||||||
|
smsc:
|
||||||
|
addr: "192.168.13.114:2775"
|
||||||
|
systemID: "omc"
|
||||||
|
password: "omc123"
|
||||||
|
systemType: "UTRAN"
|
||||||
|
|
||||||
#User authorized information
|
#User authorized information
|
||||||
# crypt: mysql/md5/bcrypt
|
# crypt: mysql/md5/bcrypt
|
||||||
# token: true/false to check accessToken
|
# token: true/false to check accessToken
|
||||||
# expires for session, unit: second
|
# expires for session, unit: second
|
||||||
# Support single/multiple session of user
|
# Support single/multiple session of user
|
||||||
|
#
|
||||||
auth:
|
auth:
|
||||||
crypt: bcrypt
|
crypt: bcrypt
|
||||||
token: true
|
token: true
|
||||||
@@ -129,6 +179,18 @@ params:
|
|||||||
subidmaxnum: 20
|
subidmaxnum: 20
|
||||||
urimaxlen: 2100000
|
urimaxlen: 2100000
|
||||||
rmuidregexp: "[0-9]{4}[A-Z]{2}[A-Z]{2}[0-9A-Z]{1}[0-9A-Z]{3}[0-9A-Z]{1,16}"
|
rmuidregexp: "[0-9]{4}[A-Z]{2}[A-Z]{2}[0-9A-Z]{1}[0-9A-Z]{3}[0-9A-Z]{1,16}"
|
||||||
|
|
||||||
testConfig:
|
testConfig:
|
||||||
enabled: true
|
enabled: true
|
||||||
file: ./etc/testconfig.yaml
|
file: ./etc/testconfig.yaml
|
||||||
|
|
||||||
|
# 静态文件配置, 相对项目根路径或填绝对路径
|
||||||
|
staticFile:
|
||||||
|
# 默认资源,dir目录需要预先创建
|
||||||
|
default:
|
||||||
|
prefix: "/static"
|
||||||
|
dir: "./static"
|
||||||
|
# 文件上传资源目录映射,与项目目录同级
|
||||||
|
upload:
|
||||||
|
prefix: "/upload"
|
||||||
|
dir: "./upload"
|
||||||
|
|||||||
@@ -2,11 +2,16 @@
|
|||||||
# level: /trace/debug/info/warn/error/fatal, default: debug
|
# level: /trace/debug/info/warn/error/fatal, default: debug
|
||||||
# duration: rotation time with xx hours, example: 1/12/24 hours
|
# duration: rotation time with xx hours, example: 1/12/24 hours
|
||||||
# count: rotation count of log, default is 30 rotation
|
# count: rotation count of log, default is 30 rotation
|
||||||
|
# pprof: false(default)/true to disable/enable pprof
|
||||||
logger:
|
logger:
|
||||||
file: d:/local.git/be.ems/restagent/log/restagent.log
|
file: d:/local.git/be.ems/restagent/log/restagent.log
|
||||||
level: trace
|
level: trace
|
||||||
duration: 24
|
duration: 24
|
||||||
count: 2
|
count: 2
|
||||||
|
|
||||||
|
pprof:
|
||||||
|
enabled: true
|
||||||
|
addr: :36060
|
||||||
|
|
||||||
# rest agent listen ipv4/v6 and port, support multiple routines
|
# rest agent listen ipv4/v6 and port, support multiple routines
|
||||||
# ip: 0.0.0.0 or ::0, support IPv4/v6
|
# ip: 0.0.0.0 or ::0, support IPv4/v6
|
||||||
@@ -16,9 +21,17 @@ rest:
|
|||||||
- ipv4: 0.0.0.0
|
- ipv4: 0.0.0.0
|
||||||
ipv6:
|
ipv6:
|
||||||
port: 33040
|
port: 33040
|
||||||
|
- ipv4: 0.0.0.0
|
||||||
|
ipv6:
|
||||||
|
port: 34443
|
||||||
|
scheme: https
|
||||||
|
clientAuthType: 0
|
||||||
|
caFile: ./etc/certs/omc-ca.crt
|
||||||
|
certFile: ./etc/certs/omc-server.crt
|
||||||
|
keyFile: ./etc/certs/omc-server.key
|
||||||
|
|
||||||
webServer:
|
webServer:
|
||||||
enabled: false
|
enabled: true
|
||||||
rootDir: d:/local.git/fe.ems.vue3/dist
|
rootDir: d:/local.git/fe.ems.vue3/dist
|
||||||
listen:
|
listen:
|
||||||
- addr: :80
|
- addr: :80
|
||||||
@@ -33,10 +46,10 @@ webServer:
|
|||||||
database:
|
database:
|
||||||
type: mysql
|
type: mysql
|
||||||
user: root
|
user: root
|
||||||
password: "root@1234"
|
password: 1000omc@kp!
|
||||||
host: "192.168.5.59"
|
host: 127.0.0.1
|
||||||
port: 3306
|
port: 33066
|
||||||
name: "omc_db"
|
name: omc_db
|
||||||
connParam: charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True
|
connParam: charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=True&interpolateParams=True
|
||||||
backup: d:/local.git/be.ems/restagent/database
|
backup: d:/local.git/be.ems/restagent/database
|
||||||
|
|
||||||
@@ -46,14 +59,14 @@ redis:
|
|||||||
# OMC系统使用库
|
# OMC系统使用库
|
||||||
default:
|
default:
|
||||||
port: 6379 # Redis port
|
port: 6379 # Redis port
|
||||||
host: "192.168.5.59" # Redis host
|
host: "192.168.2.219" # Redis host
|
||||||
password: "redis@1234"
|
password: "123456"
|
||||||
db: 10 # Redis db_num
|
db: 10 # Redis db_num
|
||||||
# UDM网元用户库
|
# UDM网元用户库
|
||||||
udmuser:
|
udmuser:
|
||||||
port: 6379 # Redis port
|
port: 6379 # Redis port
|
||||||
host: "172.60.5.140"
|
host: "192.168.2.219"
|
||||||
password: "helloearth"
|
password: "123456"
|
||||||
db: 0 # Redis db_num
|
db: 0 # Redis db_num
|
||||||
# 多个数据源时可以用这个指定默认的数据源
|
# 多个数据源时可以用这个指定默认的数据源
|
||||||
defaultDataSourceName: "default"
|
defaultDataSourceName: "default"
|
||||||
@@ -71,11 +84,10 @@ mml:
|
|||||||
user: admin
|
user: admin
|
||||||
password: admin
|
password: admin
|
||||||
mmlHome: ./mmlhome
|
mmlHome: ./mmlhome
|
||||||
upload: /home/agtuser
|
|
||||||
|
|
||||||
# NE config
|
# NE config
|
||||||
ne:
|
ne:
|
||||||
user: agtuser
|
user: root
|
||||||
etcdir: /usr/local/etc
|
etcdir: /usr/local/etc
|
||||||
bindir: /usr/local/bin
|
bindir: /usr/local/bin
|
||||||
omcdir: /usr/local/omc
|
omcdir: /usr/local/omc
|
||||||
@@ -119,9 +131,10 @@ omc:
|
|||||||
|
|
||||||
# Alarm module setting
|
# Alarm module setting
|
||||||
# Forward interface:
|
# Forward interface:
|
||||||
# email/sms
|
# email/sms
|
||||||
|
# smProxy: sms(Short Message Service)/smsc(SMS Centre)
|
||||||
alarm:
|
alarm:
|
||||||
forwardAlarm: false
|
forwardAlarm: true
|
||||||
email:
|
email:
|
||||||
smtp: mail.agrandtech.com
|
smtp: mail.agrandtech.com
|
||||||
port: 25
|
port: 25
|
||||||
@@ -129,8 +142,9 @@ alarm:
|
|||||||
password: "1000smtp@omc!"
|
password: "1000smtp@omc!"
|
||||||
# TLS skip verify: true/false
|
# TLS skip verify: true/false
|
||||||
tlsSkipVerify: true
|
tlsSkipVerify: true
|
||||||
|
smProxy: smsc
|
||||||
sms:
|
sms:
|
||||||
apiURL: http://smsc.xxx.com.cn/
|
apiURL: http://smsc.xxx.com/
|
||||||
accessKeyID: xxxx
|
accessKeyID: xxxx
|
||||||
accessKeySecret: xxxx
|
accessKeySecret: xxxx
|
||||||
signName: xxx SMSC
|
signName: xxx SMSC
|
||||||
@@ -175,12 +189,12 @@ testConfig:
|
|||||||
file: ./etc/testconfig.yaml
|
file: ./etc/testconfig.yaml
|
||||||
|
|
||||||
# 静态文件配置, 相对项目根路径或填绝对路径
|
# 静态文件配置, 相对项目根路径或填绝对路径
|
||||||
# staticFile:
|
staticFile:
|
||||||
# # 默认资源,dir目录需要预先创建
|
# 默认资源,dir目录需要预先创建
|
||||||
# default:
|
default:
|
||||||
# prefix: "/static"
|
prefix: "/static"
|
||||||
# dir: "./static"
|
dir: "./static"
|
||||||
# # 文件上传资源目录映射,与项目目录同级
|
# 文件上传资源目录映射,与项目目录同级
|
||||||
# upload:
|
upload:
|
||||||
# prefix: "/upload"
|
prefix: "/upload"
|
||||||
# dir: "./upload"
|
dir: "./upload"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Makefile for rest agent project
|
# Makefile for rest agent project
|
||||||
|
|
||||||
PROJECT = OMC
|
PROJECT = OMC
|
||||||
VERSION = 2.2404.6
|
VERSION = 2.2405.4
|
||||||
PLATFORM = amd64
|
PLATFORM = amd64
|
||||||
ARMPLATFORM = aarch64
|
ARMPLATFORM = aarch64
|
||||||
BUILDDIR = ../../build
|
BUILDDIR = ../../build
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
_ "net/http/pprof"
|
||||||
|
|
||||||
"be.ems/features/dbrest"
|
"be.ems/features/dbrest"
|
||||||
"be.ems/features/event"
|
"be.ems/features/event"
|
||||||
"be.ems/features/fm"
|
"be.ems/features/fm"
|
||||||
@@ -185,12 +187,20 @@ func HttpListenWebServer(addr string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
// src 配置中心初始加载
|
// src 配置中心初始加载
|
||||||
src.ConfigurationInit()
|
src.ConfigurationInit()
|
||||||
app := src.AppEngine()
|
app := src.AppEngine()
|
||||||
|
|
||||||
conf := config.GetYamlConfig()
|
conf := config.GetYamlConfig()
|
||||||
|
|
||||||
|
if conf.Pprof.Enabled {
|
||||||
|
// 启用pprof HTTP服务
|
||||||
|
go func() {
|
||||||
|
fmt.Println(http.ListenAndServe(conf.Pprof.Addr, nil))
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
log.InitLogger(conf.Logger.File, conf.Logger.Duration, conf.Logger.Count, "omc:restagent", config.GetLogLevel())
|
log.InitLogger(conf.Logger.File, conf.Logger.Duration, conf.Logger.Count, "omc:restagent", config.GetLogLevel())
|
||||||
fmt.Printf("OMC restagent version: %s\n", global.Version)
|
fmt.Printf("OMC restagent version: %s\n", global.Version)
|
||||||
log.Infof("========================= OMC restagent startup =========================")
|
log.Infof("========================= OMC restagent startup =========================")
|
||||||
@@ -241,9 +251,6 @@ func main() {
|
|||||||
// AMF上报的UE事件, 无前缀,暂时特殊处理
|
// AMF上报的UE事件, 无前缀,暂时特殊处理
|
||||||
app.POST(event.UriUEEvent, event.PostUEEventFromAMF)
|
app.POST(event.UriUEEvent, event.PostUEEventFromAMF)
|
||||||
|
|
||||||
// 开启监控采集
|
|
||||||
// monitor.StartMonitor(false, "")
|
|
||||||
|
|
||||||
var listenLocalhost bool = false
|
var listenLocalhost bool = false
|
||||||
for _, rest := range conf.Rest {
|
for _, rest := range conf.Rest {
|
||||||
// ipv4 goroutines
|
// ipv4 goroutines
|
||||||
|
|||||||
15
src/app.go
15
src/app.go
@@ -8,6 +8,7 @@ import (
|
|||||||
"be.ems/src/framework/errorcatch"
|
"be.ems/src/framework/errorcatch"
|
||||||
"be.ems/src/framework/middleware"
|
"be.ems/src/framework/middleware"
|
||||||
"be.ems/src/framework/middleware/security"
|
"be.ems/src/framework/middleware/security"
|
||||||
|
"be.ems/src/framework/utils/machine"
|
||||||
"be.ems/src/modules/chart"
|
"be.ems/src/modules/chart"
|
||||||
"be.ems/src/modules/common"
|
"be.ems/src/modules/common"
|
||||||
"be.ems/src/modules/crontask"
|
"be.ems/src/modules/crontask"
|
||||||
@@ -18,7 +19,9 @@ import (
|
|||||||
"be.ems/src/modules/trace"
|
"be.ems/src/modules/trace"
|
||||||
"be.ems/src/modules/ws"
|
"be.ems/src/modules/ws"
|
||||||
|
|
||||||
|
"github.com/chenjiandongx/ginprom"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed assets/*
|
//go:embed assets/*
|
||||||
@@ -28,6 +31,13 @@ var assetsDir embed.FS
|
|||||||
func AppEngine() *gin.Engine {
|
func AppEngine() *gin.Engine {
|
||||||
app := initAppEngine()
|
app := initAppEngine()
|
||||||
|
|
||||||
|
// TODO 不建议在主分支中加入
|
||||||
|
// 性能分析监控
|
||||||
|
if promEnabled := config.Get("pprof.enabled"); promEnabled != nil && promEnabled.(bool) {
|
||||||
|
app.Use(ginprom.PromMiddleware(nil))
|
||||||
|
app.GET("/metrics", ginprom.PromHandler(promhttp.Handler()))
|
||||||
|
}
|
||||||
|
|
||||||
// 初始全局默认
|
// 初始全局默认
|
||||||
initDefeat(app)
|
initDefeat(app)
|
||||||
|
|
||||||
@@ -37,6 +47,9 @@ func AppEngine() *gin.Engine {
|
|||||||
// 设置程序内全局资源访问
|
// 设置程序内全局资源访问
|
||||||
config.SetAssetsDirFS(assetsDir)
|
config.SetAssetsDirFS(assetsDir)
|
||||||
|
|
||||||
|
// 首次安装启动记录
|
||||||
|
machine.Launch()
|
||||||
|
|
||||||
// 读取服务配置
|
// 读取服务配置
|
||||||
app.ForwardedByClientIP = config.Get("server.proxy").(bool)
|
app.ForwardedByClientIP = config.Get("server.proxy").(bool)
|
||||||
return app
|
return app
|
||||||
@@ -108,7 +121,7 @@ func initDefeat(app *gin.Engine) {
|
|||||||
app.NoRoute(func(c *gin.Context) {
|
app.NoRoute(func(c *gin.Context) {
|
||||||
c.JSON(404, gin.H{
|
c.JSON(404, gin.H{
|
||||||
"code": 404,
|
"code": 404,
|
||||||
"msg": fmt.Sprintf("%s Not Found", c.Request.RequestURI),
|
"msg": fmt.Sprintf("Not Found %s", c.Request.RequestURI),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# 项目信息
|
# 项目信息
|
||||||
framework:
|
framework:
|
||||||
name: "CN EMS"
|
name: "CN EMS"
|
||||||
version: "2.2404.6"
|
version: "2.2405.4"
|
||||||
|
|
||||||
# 应用服务配置
|
# 应用服务配置
|
||||||
server:
|
server:
|
||||||
@@ -15,7 +15,7 @@ logger:
|
|||||||
fileDir: "/var/log"
|
fileDir: "/var/log"
|
||||||
fileName: "omc.log"
|
fileName: "omc.log"
|
||||||
level: 2 # 日志记录的等级 0:silent<1:info<2:warn<3:error
|
level: 2 # 日志记录的等级 0:silent<1:info<2:warn<3:error
|
||||||
maxDay: 180 # 日志会保留 180 天
|
maxDay: 7 # 日志会保留 180 天
|
||||||
maxSize: 10 # 调整按 10MB 大小的切割
|
maxSize: 10 # 调整按 10MB 大小的切割
|
||||||
|
|
||||||
# 静态文件配置, 相对项目根路径或填绝对路径
|
# 静态文件配置, 相对项目根路径或填绝对路径
|
||||||
|
|||||||
@@ -19,3 +19,6 @@ const STATUS_NO = "0"
|
|||||||
|
|
||||||
// 上下文信息-登录用户
|
// 上下文信息-登录用户
|
||||||
const CTX_LOGIN_USER = "loginuser"
|
const CTX_LOGIN_USER = "loginuser"
|
||||||
|
|
||||||
|
// 启动-引导系统初始
|
||||||
|
const LAUNCH_BOOTLOADER = "bootloader"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const (
|
|||||||
// NewLogger 实例日志器对象
|
// NewLogger 实例日志器对象
|
||||||
func NewLogger(env, fileDir, fileName string, level, maxDay, maxSize int) (*Logger, error) {
|
func NewLogger(env, fileDir, fileName string, level, maxDay, maxSize int) (*Logger, error) {
|
||||||
logFilePath := filepath.Join(fileDir, fileName)
|
logFilePath := filepath.Join(fileDir, fileName)
|
||||||
if err := os.MkdirAll(filepath.Dir(logFilePath), 0750); err != nil {
|
if err := os.MkdirAll(filepath.Dir(logFilePath), 0775); err != nil {
|
||||||
return nil, fmt.Errorf("failed to mkdir logger dir: %v", err)
|
return nil, fmt.Errorf("failed to mkdir logger dir: %v", err)
|
||||||
}
|
}
|
||||||
fileHandle, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
fileHandle, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||||
|
|||||||
@@ -10,21 +10,17 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// aesKey 字符串AES加解密密钥
|
|
||||||
const aesKey = "AGT66VfY4SMaiT97"
|
|
||||||
|
|
||||||
// StringEncryptByAES 字符串AES加密
|
// StringEncryptByAES 字符串AES加密
|
||||||
func StringEncryptByAES(text string) (string, error) {
|
func StringEncryptByAES(text string) (string, error) {
|
||||||
if len(text) == 0 {
|
if len(text) == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
pass := []byte(text)
|
xpass, err := aesEncryptWithSalt([]byte(text))
|
||||||
xpass, err := aesEncryptWithSalt([]byte(aesKey), pass)
|
if err != nil {
|
||||||
if err == nil {
|
return "", err
|
||||||
pass64 := base64.StdEncoding.EncodeToString(xpass)
|
|
||||||
return pass64, err
|
|
||||||
}
|
}
|
||||||
return "", err
|
pass64 := base64.StdEncoding.EncodeToString(xpass)
|
||||||
|
return pass64, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringDecryptByAES 字符串AES解密
|
// StringDecryptByAES 字符串AES解密
|
||||||
@@ -36,53 +32,70 @@ func StringDecryptByAES(text string) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
var tpass []byte
|
|
||||||
tpass, err = aesDecryptWithSalt([]byte(aesKey), bytesPass)
|
tpass, err := aesDecryptWithSalt(bytesPass)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
result := string(tpass[:])
|
return "", err
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
return "", err
|
return string(tpass), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// aesEncryptWithSalt AES加密
|
// aesKey 字符串AES加解密密钥
|
||||||
func aesEncryptWithSalt(key, plaintext []byte) ([]byte, error) {
|
const aesKey = "AGT66VfY4SMaiT97a7df0aef1704d5c5"
|
||||||
blockSize := aes.BlockSize
|
|
||||||
padding := blockSize - len(plaintext)%blockSize
|
|
||||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
||||||
plaintext = append(plaintext, padtext...)
|
|
||||||
|
|
||||||
block, err := aes.NewCipher(key)
|
// const aesKey = "AGT66VfY4SMaiT97"
|
||||||
|
// aesEncryptWithSalt AES加密
|
||||||
|
func aesEncryptWithSalt(plaintext []byte) ([]byte, error) {
|
||||||
|
block, err := aes.NewCipher([]byte(aesKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
blockSize := aes.BlockSize
|
||||||
|
|
||||||
|
padding := blockSize - (len(plaintext) % blockSize)
|
||||||
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||||
|
plaintext = append(plaintext, padtext...)
|
||||||
|
|
||||||
ciphertext := make([]byte, blockSize+len(plaintext))
|
ciphertext := make([]byte, blockSize+len(plaintext))
|
||||||
iv := ciphertext[0:blockSize]
|
iv := ciphertext[:blockSize]
|
||||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cbc := cipher.NewCBCEncrypter(block, iv)
|
|
||||||
cbc.CryptBlocks(ciphertext[blockSize:], plaintext)
|
mode := cipher.NewCBCEncrypter(block, iv)
|
||||||
|
mode.CryptBlocks(ciphertext[blockSize:], plaintext)
|
||||||
|
|
||||||
return ciphertext, nil
|
return ciphertext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// aesDecryptWithSalt AES解密
|
// aesDecryptWithSalt AES解密
|
||||||
func aesDecryptWithSalt(key, ciphertext []byte) ([]byte, error) {
|
func aesDecryptWithSalt(ciphertext []byte) ([]byte, error) {
|
||||||
blockSize := aes.BlockSize
|
blockSize := aes.BlockSize
|
||||||
var block cipher.Block
|
if len(ciphertext) < blockSize {
|
||||||
block, err := aes.NewCipher(key)
|
return nil, fmt.Errorf("ciphertext too short")
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := ciphertext[:blockSize]
|
||||||
|
ciphertext = ciphertext[blockSize:]
|
||||||
|
|
||||||
|
block, err := aes.NewCipher([]byte(aesKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(ciphertext) < blockSize {
|
|
||||||
return nil, fmt.Errorf("iciphertext too short")
|
if len(ciphertext)%blockSize != 0 {
|
||||||
|
return nil, fmt.Errorf("ciphertext is not a multiple of the block size")
|
||||||
}
|
}
|
||||||
iv := ciphertext[:blockSize]
|
|
||||||
ciphertext = ciphertext[blockSize:]
|
mode := cipher.NewCBCDecrypter(block, iv)
|
||||||
cbc := cipher.NewCBCDecrypter(block, iv)
|
mode.CryptBlocks(ciphertext, ciphertext)
|
||||||
cbc.CryptBlocks(ciphertext, ciphertext)
|
|
||||||
length := len(ciphertext)
|
// 去除填充
|
||||||
unpadding := int(ciphertext[len(ciphertext)-1])
|
padding := int(ciphertext[len(ciphertext)-1])
|
||||||
ciphertext = ciphertext[:(length - unpadding)]
|
if padding > blockSize || padding == 0 {
|
||||||
|
return nil, fmt.Errorf("invalid padding")
|
||||||
|
}
|
||||||
|
ciphertext = ciphertext[:len(ciphertext)-padding]
|
||||||
|
|
||||||
return ciphertext, nil
|
return ciphertext, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func WriterFileCSV(data [][]string, filePath string) error {
|
|||||||
dirPath := filepath.Dir(filePath)
|
dirPath := filepath.Dir(filePath)
|
||||||
|
|
||||||
// 确保文件夹路径存在
|
// 确保文件夹路径存在
|
||||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
err := os.MkdirAll(dirPath, 0775)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("MkdirAll dir %v", err)
|
logger.Errorf("MkdirAll dir %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ func WriteSheet(headerCells map[string]string, dataCells []map[string]any, fileN
|
|||||||
saveFilePath := filepath.Join(dir, filePath, fileName)
|
saveFilePath := filepath.Join(dir, filePath, fileName)
|
||||||
|
|
||||||
// 创建文件目录
|
// 创建文件目录
|
||||||
if err := os.MkdirAll(filepath.Dir(saveFilePath), 0750); err != nil {
|
if err := os.MkdirAll(filepath.Dir(saveFilePath), 0775); err != nil {
|
||||||
return "", fmt.Errorf("failed to create save file %v", err)
|
return "", fmt.Errorf("failed to create save file %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -177,13 +177,13 @@ func ReadUploadFileStream(filePath, headerRange string) (map[string]any, error)
|
|||||||
"range": "",
|
"range": "",
|
||||||
"chunkSize": 0,
|
"chunkSize": 0,
|
||||||
"fileSize": 0,
|
"fileSize": 0,
|
||||||
"data": nil,
|
"data": []byte{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文件大小
|
// 文件大小
|
||||||
fileSize := getFileSize(fileAsbPath)
|
fileSize := getFileSize(fileAsbPath)
|
||||||
if fileSize <= 0 {
|
if fileSize <= 0 {
|
||||||
return result, nil
|
return result, fmt.Errorf("file does not exist")
|
||||||
}
|
}
|
||||||
result["fileSize"] = fileSize
|
result["fileSize"] = fileSize
|
||||||
|
|
||||||
@@ -312,12 +312,12 @@ func CopyUploadFile(filePath, dst string) error {
|
|||||||
}
|
}
|
||||||
defer src.Close()
|
defer src.Close()
|
||||||
|
|
||||||
if err := os.MkdirAll(filepath.Dir(dst), 0750); err != nil {
|
if err := os.MkdirAll(filepath.Dir(dst), 0775); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果目标文件已经存在,先将目标文件重命名
|
// 如果目标文件已经存在,先将目标文件重命名
|
||||||
if _, err := os.Stat(dst); err == nil {
|
if info, err := os.Stat(dst); err == nil && !info.IsDir() {
|
||||||
ext := filepath.Ext(dst)
|
ext := filepath.Ext(dst)
|
||||||
name := dst[0 : len(dst)-len(ext)]
|
name := dst[0 : len(dst)-len(ext)]
|
||||||
newName := fmt.Sprintf("%s-%s%s", name, time.Now().Format("20060102_150405"), ext)
|
newName := fmt.Sprintf("%s-%s%s", name, time.Now().Format("20060102_150405"), ext)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func WriterFileJSON(data any, filePath string) error {
|
|||||||
dirPath := filepath.Dir(filePath)
|
dirPath := filepath.Dir(filePath)
|
||||||
|
|
||||||
// 确保文件夹路径存在
|
// 确保文件夹路径存在
|
||||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
err := os.MkdirAll(dirPath, 0775)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("CreateFile MkdirAll %v", err)
|
logger.Errorf("CreateFile MkdirAll %v", err)
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ func WriterFileJSONLine(data []any, filePath string) error {
|
|||||||
dirPath := filepath.Dir(filePath)
|
dirPath := filepath.Dir(filePath)
|
||||||
|
|
||||||
// 确保文件夹路径存在
|
// 确保文件夹路径存在
|
||||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
err := os.MkdirAll(dirPath, 0775)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("CreateFile MkdirAll %v", err)
|
logger.Errorf("CreateFile MkdirAll %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func WriterFileTXT(data [][]string, sep string, filePath string) error {
|
|||||||
dirPath := filepath.Dir(filePath)
|
dirPath := filepath.Dir(filePath)
|
||||||
|
|
||||||
// 确保文件夹路径存在
|
// 确保文件夹路径存在
|
||||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
err := os.MkdirAll(dirPath, 0775)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("CreateFile MkdirAll %v", err)
|
logger.Errorf("CreateFile MkdirAll %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func transferToNewFile(file *multipart.FileHeader, dst string) error {
|
|||||||
}
|
}
|
||||||
defer src.Close()
|
defer src.Close()
|
||||||
|
|
||||||
if err = os.MkdirAll(filepath.Dir(dst), 0750); err != nil {
|
if err = os.MkdirAll(filepath.Dir(dst), 0775); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ func mergeToNewFile(dirPath string, writePath string, fileName string) error {
|
|||||||
|
|
||||||
// 写入到新路径文件
|
// 写入到新路径文件
|
||||||
newFilePath := filepath.Join(writePath, fileName)
|
newFilePath := filepath.Join(writePath, fileName)
|
||||||
if err = os.MkdirAll(filepath.Dir(newFilePath), 0750); err != nil {
|
if err = os.MkdirAll(filepath.Dir(newFilePath), 0775); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
178
src/framework/utils/machine/launch.go
Normal file
178
src/framework/utils/machine/launch.go
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"be.ems/src/framework/constants/common"
|
||||||
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/utils/cmd"
|
||||||
|
"be.ems/src/framework/utils/crypto"
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 机器的唯一标识符
|
||||||
|
var Code string
|
||||||
|
|
||||||
|
// 初始信息
|
||||||
|
var LaunchInfo map[string]any
|
||||||
|
|
||||||
|
// codeGenerate 生成机器的唯一标识符
|
||||||
|
func codeGenerate() string {
|
||||||
|
var machineID string
|
||||||
|
|
||||||
|
// 获取主机名
|
||||||
|
hostname, err := os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
machineID += hostname
|
||||||
|
|
||||||
|
// 获取 CPU 信息
|
||||||
|
numCPU := runtime.NumCPU()
|
||||||
|
machineID += fmt.Sprintf("%d", numCPU)
|
||||||
|
|
||||||
|
// 获取操作系统信息
|
||||||
|
osInfo := runtime.GOOS
|
||||||
|
machineID += osInfo
|
||||||
|
|
||||||
|
// 使用哈希函数生成机器码
|
||||||
|
h := fnv.New32a()
|
||||||
|
h.Write([]byte(machineID))
|
||||||
|
machineCode := h.Sum32()
|
||||||
|
|
||||||
|
return fmt.Sprintf("%x", machineCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网管本地路径
|
||||||
|
func filePath() string {
|
||||||
|
filePath := "/usr/local/etc/omc/machine.ini"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
filePath = fmt.Sprintf("C:%s", filePath)
|
||||||
|
}
|
||||||
|
return filePath
|
||||||
|
}
|
||||||
|
|
||||||
|
// codeFileRead 读取机器保留的信息
|
||||||
|
func codeFileRead() (map[string]any, error) {
|
||||||
|
var mapData map[string]any
|
||||||
|
// 读取文件内容
|
||||||
|
bytes, err := os.ReadFile(filePath())
|
||||||
|
if err != nil {
|
||||||
|
logger.Warnf("CodeFileRead ReadFile => %s", err.Error())
|
||||||
|
return mapData, fmt.Errorf("not file")
|
||||||
|
}
|
||||||
|
content := string(bytes)
|
||||||
|
// 解密
|
||||||
|
contentDe, err := crypto.StringDecryptByAES(content)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CodeFileRead decrypt: %v", err.Error())
|
||||||
|
return mapData, fmt.Errorf("decrypt fail")
|
||||||
|
}
|
||||||
|
// 序列化Map
|
||||||
|
mapData, err = parse.ConvertConfigToMap("json", string(contentDe))
|
||||||
|
if err != nil {
|
||||||
|
logger.Warnf("NeConfPara5GRead ConvertConfigToMap => %s", err.Error())
|
||||||
|
return mapData, fmt.Errorf("content error")
|
||||||
|
}
|
||||||
|
return mapData, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// codeFileWrite 写入机器保留的信息
|
||||||
|
func codeFileWrite(data map[string]any) error {
|
||||||
|
jsonByte, _ := json.Marshal(data)
|
||||||
|
// 加密
|
||||||
|
contentEn, err := crypto.StringEncryptByAES(string(jsonByte))
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("insert encrypt: %v", err.Error())
|
||||||
|
return fmt.Errorf("encrypt fail")
|
||||||
|
}
|
||||||
|
return parse.ConvertConfigToFile("txt", filePath(), contentEn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch 记录首次安装启动初始信息
|
||||||
|
func Launch() {
|
||||||
|
Code = codeGenerate()
|
||||||
|
// 检查文件是否存在
|
||||||
|
if _, err := os.Stat(filePath()); err != nil {
|
||||||
|
LaunchInfo = map[string]any{
|
||||||
|
"code": Code, // 机器码
|
||||||
|
"useTime": time.Now().UnixMilli(), // 首次使用时间
|
||||||
|
|
||||||
|
common.LAUNCH_BOOTLOADER: true, // 启动引导
|
||||||
|
common.LAUNCH_BOOTLOADER + "Time": 0, // 引导完成时间
|
||||||
|
}
|
||||||
|
codeFileWrite(LaunchInfo)
|
||||||
|
} else {
|
||||||
|
// 读取记录文件
|
||||||
|
data, err := codeFileRead()
|
||||||
|
if err != nil {
|
||||||
|
// 文件异常就重新生成
|
||||||
|
os.Remove(filePath())
|
||||||
|
Launch()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
LaunchInfo = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLaunchInfo 新增额外的初始信息
|
||||||
|
func SetLaunchInfo(info map[string]any) error {
|
||||||
|
if info == nil {
|
||||||
|
return fmt.Errorf("not info")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 固定值禁止变更
|
||||||
|
constKeys := []string{"code", "useTime"}
|
||||||
|
for k, v := range info {
|
||||||
|
constKey := false
|
||||||
|
for _, ck := range constKeys {
|
||||||
|
if ck == k {
|
||||||
|
constKey = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if constKey {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
LaunchInfo[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return codeFileWrite(LaunchInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bootloader 启动引导标记
|
||||||
|
func Bootloader(flag bool) error {
|
||||||
|
return SetLaunchInfo(map[string]any{
|
||||||
|
common.LAUNCH_BOOTLOADER: flag, // 启动引导 true开 false关
|
||||||
|
common.LAUNCH_BOOTLOADER + "Time": time.Now().UnixMilli(), // 引导完成时间
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset 引导数据重置
|
||||||
|
func Reset() error {
|
||||||
|
// 重置数据库
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
// return fmt.Errorf("not support window")
|
||||||
|
} else {
|
||||||
|
// 重置数据库
|
||||||
|
if _, err := cmd.Execf("sudo /usr/local/omc/bin/setomc.sh -m install"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 重启服务
|
||||||
|
if _, err := cmd.Execf("nohup sh -c \"sleep 1s && %s\" > /dev/null 2>&1 &", "sudo systemctl restart restagent"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置引导标记
|
||||||
|
if err := Bootloader(true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
package parse
|
package parse
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -10,6 +13,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/robfig/cron/v3"
|
"github.com/robfig/cron/v3"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Number 解析数值型
|
// Number 解析数值型
|
||||||
@@ -51,6 +55,8 @@ func Boolean(str any) bool {
|
|||||||
case float32, float64:
|
case float32, float64:
|
||||||
num := reflect.ValueOf(str).Float()
|
num := reflect.ValueOf(str).Float()
|
||||||
return num != 0
|
return num != 0
|
||||||
|
case bool:
|
||||||
|
return str
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -165,3 +171,83 @@ func Color(colorStr string) *color.RGBA {
|
|||||||
A: 255, // 不透明
|
A: 255, // 不透明
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConvertIPMask 转换IP网络地址掩码 24 -> 255.255.255.0
|
||||||
|
func ConvertIPMask(bits int64) string {
|
||||||
|
if bits < 0 || bits > 32 {
|
||||||
|
return "Invalid Mask Bits"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建一个32位的uint32类型掩码,指定前bits位为1,其余为0
|
||||||
|
mask := uint32((1<<bits - 1) << (32 - bits))
|
||||||
|
|
||||||
|
// 将掩码转换为四个八位分组
|
||||||
|
groups := []string{
|
||||||
|
fmt.Sprintf("%d", mask>>24),
|
||||||
|
fmt.Sprintf("%d", (mask>>16)&255),
|
||||||
|
fmt.Sprintf("%d", (mask>>8)&255),
|
||||||
|
fmt.Sprintf("%d", mask&255),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将分组用点号连接起来形成掩码字符串
|
||||||
|
return strings.Join(groups, ".")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertConfigToMap 将配置内容转换为Map结构数据
|
||||||
|
//
|
||||||
|
// configType 类型支持:txt json yaml yml
|
||||||
|
func ConvertConfigToMap(configType, content string) (map[string]any, error) {
|
||||||
|
// 类型支持:viper.SupportedExts
|
||||||
|
// config := viper.New()
|
||||||
|
// config.SetConfigType(configType)
|
||||||
|
// err := config.ReadConfig(bytes.NewBuffer([]byte(content)))
|
||||||
|
// return config.AllSettings(), err
|
||||||
|
|
||||||
|
var configMap map[string]interface{}
|
||||||
|
var err error
|
||||||
|
if configType == "" || configType == "txt" {
|
||||||
|
configMap = map[string]interface{}{
|
||||||
|
"txt": content,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if configType == "yaml" || configType == "yml" {
|
||||||
|
err = yaml.Unmarshal([]byte(content), &configMap)
|
||||||
|
}
|
||||||
|
if configType == "json" {
|
||||||
|
err = json.Unmarshal([]byte(content), &configMap)
|
||||||
|
}
|
||||||
|
return configMap, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertConfigToFile 将数据写入到指定文件内
|
||||||
|
//
|
||||||
|
// configType 类型支持:txt json yaml yml
|
||||||
|
func ConvertConfigToFile(configType, filePath string, data any) error {
|
||||||
|
// viper.SupportedExts
|
||||||
|
// config := viper.New()
|
||||||
|
// config.SetConfigType(configType)
|
||||||
|
// for key, value := range mapData {
|
||||||
|
// config.Set(key, value)
|
||||||
|
// }
|
||||||
|
// return config.WriteConfigAs(filePath)
|
||||||
|
|
||||||
|
var dataByte []byte
|
||||||
|
var err error
|
||||||
|
if configType == "" || configType == "txt" {
|
||||||
|
dataByte = []byte(data.(string))
|
||||||
|
}
|
||||||
|
if configType == "yaml" || configType == "yml" {
|
||||||
|
dataByte, err = yaml.Marshal(data)
|
||||||
|
}
|
||||||
|
if configType == "json" {
|
||||||
|
dataByte, err = json.Marshal(data)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(filepath.Dir(filePath), 0775); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.WriteFile(filePath, dataByte, 0644)
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func PageNumSize(pageNum, pageSize any) (int64, int64) {
|
|||||||
|
|
||||||
// 显示记录数
|
// 显示记录数
|
||||||
size := parse.Number(pageSize)
|
size := parse.Number(pageSize)
|
||||||
if size < 0 {
|
if size < 1 {
|
||||||
size = 10
|
size = 10
|
||||||
}
|
}
|
||||||
return num - 1, size
|
return num - 1, size
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func FileSCPLocalToNe(neIp, localPath, nePath string) error {
|
|||||||
// 网元NE 远程文件复制到本地文件
|
// 网元NE 远程文件复制到本地文件
|
||||||
func FileSCPNeToLocal(neIp, nePath, localPath string) error {
|
func FileSCPNeToLocal(neIp, nePath, localPath string) error {
|
||||||
// 确保文件夹路径存在
|
// 确保文件夹路径存在
|
||||||
if err := os.MkdirAll(filepath.Dir(localPath), 0750); err != nil {
|
if err := os.MkdirAll(filepath.Dir(localPath), 0775); err != nil {
|
||||||
logger.Errorf("FileSCPNeToLocal MkdirAll err %v", err)
|
logger.Errorf("FileSCPNeToLocal MkdirAll err %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"be.ems/src/framework/logger"
|
"be.ems/src/framework/logger"
|
||||||
"be.ems/src/framework/utils/cmd"
|
"be.ems/src/framework/utils/cmd"
|
||||||
|
gosftp "github.com/pkg/sftp"
|
||||||
gossh "golang.org/x/crypto/ssh"
|
gossh "golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -133,8 +135,12 @@ func (c *ConnSSH) SendToAuthorizedKeys() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
authorizedKeysEntry := fmt.Sprintln(strings.TrimSpace(publicKey))
|
authorizedKeysEntry := fmt.Sprintln(strings.TrimSpace(publicKey))
|
||||||
cmdStr := "echo '" + authorizedKeysEntry + "' >> ~/.ssh/authorized_keys"
|
cmdStrArr := []string{
|
||||||
_, err = c.RunCMD(cmdStr)
|
fmt.Sprintf("sudo mkdir -p /home/%s/.ssh && sudo chown %s:%s /home/%s/.ssh && sudo chmod 700 /home/%s/.ssh", c.User, c.User, c.User, c.User, c.User),
|
||||||
|
fmt.Sprintf("sudo touch /home/%s/.ssh/authorized_keys && sudo chown %s:%s /home/%s/.ssh/authorized_keys && sudo chmod 600 /home/%s/.ssh/authorized_keys", c.User, c.User, c.User, c.User, c.User),
|
||||||
|
fmt.Sprintf("echo '%s' | sudo tee -a /home/%s/.ssh/authorized_keys", authorizedKeysEntry, c.User),
|
||||||
|
}
|
||||||
|
_, err = c.RunCMD(strings.Join(cmdStrArr, " && "))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("SendAuthorizedKeys echo err %s", err.Error())
|
logger.Errorf("SendAuthorizedKeys echo err %s", err.Error())
|
||||||
return err
|
return err
|
||||||
@@ -156,9 +162,8 @@ func (c *ConnSSH) CurrentUserRsaKey(publicKey bool) (string, error) {
|
|||||||
// 是否存在私钥并创建
|
// 是否存在私钥并创建
|
||||||
keyPath := fmt.Sprintf("%s/.ssh/id_rsa", usr.HomeDir)
|
keyPath := fmt.Sprintf("%s/.ssh/id_rsa", usr.HomeDir)
|
||||||
if _, err := os.Stat(keyPath); err != nil {
|
if _, err := os.Stat(keyPath); err != nil {
|
||||||
_, err2 := cmd.ExecWithCheck("ssh-keygen", "-t", "rsa", "-P", "", "-f", keyPath)
|
if _, err := cmd.ExecWithCheck("ssh-keygen", "-t", "rsa", "-P", "", "-f", keyPath); err != nil {
|
||||||
if err2 != nil {
|
logger.Errorf("CurrentUserPrivateKey ssh-keygen [%s] rsa => %s", usr.Username, err.Error())
|
||||||
logger.Errorf("CurrentUserPrivateKey ssh-keygen [%s] rsa => %s", usr.Username, err2.Error())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,12 +244,11 @@ func (s *SSHClientSession) Write(cmd string) (int, error) {
|
|||||||
return s.Stdin.Write([]byte(cmd))
|
return s.Stdin.Write([]byte(cmd))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read 读取结果 等待一会才有结果
|
// Read 读取结果
|
||||||
func (s *SSHClientSession) Read() []byte {
|
func (s *SSHClientSession) Read() []byte {
|
||||||
if s.Stdout == nil {
|
if s.Stdout == nil {
|
||||||
return []byte{}
|
return []byte{}
|
||||||
}
|
}
|
||||||
// time.Sleep(300 * time.Millisecond)
|
|
||||||
bs := s.Stdout.Bytes()
|
bs := s.Stdout.Bytes()
|
||||||
if len(bs) > 0 {
|
if len(bs) > 0 {
|
||||||
s.Stdout.Reset()
|
s.Stdout.Reset()
|
||||||
@@ -253,15 +257,6 @@ func (s *SSHClientSession) Read() []byte {
|
|||||||
return []byte{}
|
return []byte{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CombinedOutput 发送命令带结果返回
|
|
||||||
func (s *SSHClientSession) CombinedOutput(cmd string) (string, error) {
|
|
||||||
n, err := s.Write(cmd)
|
|
||||||
if n == 0 || err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(s.Read()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// singleWriter SSH客户端会话消息
|
// singleWriter SSH客户端会话消息
|
||||||
type singleWriter struct {
|
type singleWriter struct {
|
||||||
b bytes.Buffer
|
b bytes.Buffer
|
||||||
@@ -283,3 +278,208 @@ func (w *singleWriter) Reset() {
|
|||||||
defer w.mu.Unlock()
|
defer w.mu.Unlock()
|
||||||
w.b.Reset()
|
w.b.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewClientSFTP 创建SSH客户端SFTP对象
|
||||||
|
func (c *ConnSSH) NewClientSFTP() (*SSHClientSFTP, error) {
|
||||||
|
sftpClient, err := gosftp.NewClient(c.Client)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("NewClientSFTP failed to create sftp: => %s", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SSHClientSFTP{
|
||||||
|
Client: sftpClient,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SSHClientSFTP SSH客户端SFTP对象
|
||||||
|
type SSHClientSFTP struct {
|
||||||
|
Client *gosftp.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close 关闭会话
|
||||||
|
func (s *SSHClientSFTP) Close() {
|
||||||
|
if s.Client != nil {
|
||||||
|
s.Client.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyDirRemoteToLocal 复制目录-远程到本地
|
||||||
|
func (s *SSHClientSFTP) CopyDirRemoteToLocal(remoteDir, localDir string) error {
|
||||||
|
// 列出远程目录中的文件和子目录
|
||||||
|
remoteFiles, err := s.Client.ReadDir(remoteDir)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirRemoteToLocal failed to reading remote directory %s: => %s", remoteDir, err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建本地目录
|
||||||
|
err = os.MkdirAll(localDir, 0775)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirRemoteToLocal failed to creating local directory %s: => %s", localDir, err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历远程文件和子目录并复制到本地
|
||||||
|
for _, remoteFile := range remoteFiles {
|
||||||
|
remotePath := filepath.Join(remoteDir, remoteFile.Name())
|
||||||
|
localPath := filepath.Join(localDir, remoteFile.Name())
|
||||||
|
|
||||||
|
if remoteFile.IsDir() {
|
||||||
|
// 如果是子目录,则递归复制子目录
|
||||||
|
err = s.CopyDirRemoteToLocal(remotePath, localPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirRemoteToLocal failed to copying remote directory %s: => %s", remotePath, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果是文件,则复制文件内容
|
||||||
|
remoteFile, err := s.Client.Open(remotePath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirRemoteToLocal failed to opening remote file %s: => %s", remotePath, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defer remoteFile.Close()
|
||||||
|
|
||||||
|
localFile, err := os.Create(localPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirRemoteToLocal failed to creating local file %s: => %s", localPath, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defer localFile.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(localFile, remoteFile)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirRemoteToLocal failed to copying file contents from %s to %s: => %s", remotePath, localPath, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyDirRemoteToLocal 复制目录-本地到远程
|
||||||
|
func (s *SSHClientSFTP) CopyDirLocalToRemote(localDir, remoteDir string) error {
|
||||||
|
// 创建远程目录
|
||||||
|
err := s.Client.MkdirAll(remoteDir)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remoteDir, err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历本地目录中的文件和子目录并复制到远程
|
||||||
|
err = filepath.Walk(localDir, func(localPath string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成远程路径
|
||||||
|
remotePath := filepath.Join(remoteDir, localPath[len(localDir):])
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
// 如果是子目录,则创建远程目录
|
||||||
|
err := s.Client.MkdirAll(remotePath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remotePath, err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果是文件,则复制文件内容
|
||||||
|
localFile, err := os.Open(localPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirLocalToRemote failed to opening local file %s: => %s", localPath, err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer localFile.Close()
|
||||||
|
|
||||||
|
remoteFile, err := s.Client.Create(remotePath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirLocalToRemote failed to creating remote file %s: => %s", remotePath, err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer remoteFile.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(remoteFile, localFile)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirLocalToRemote failed to copying file contents from %s to %s: => %s", localPath, remotePath, err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyDirLocalToRemote failed to walking local directory: => %s", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyDirRemoteToLocal 复制文件-远程到本地
|
||||||
|
func (s *SSHClientSFTP) CopyFileRemoteToLocal(remotePath, localPath string) error {
|
||||||
|
// 打开远程文件
|
||||||
|
remoteFile, err := s.Client.Open(remotePath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyFileRemoteToLocal failed to opening remote file: => %s", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer remoteFile.Close()
|
||||||
|
|
||||||
|
if err := os.MkdirAll(filepath.Dir(localPath), 0775); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果目标文件已经存在,先将目标文件重命名
|
||||||
|
// if info, err := os.Stat(localPath); err == nil && !info.IsDir() {
|
||||||
|
// ext := filepath.Ext(localPath)
|
||||||
|
// name := localPath[0 : len(localPath)-len(ext)]
|
||||||
|
// newName := fmt.Sprintf("%s-%s%s", name, time.Now().Format("20060102_150405"), ext)
|
||||||
|
// err := os.Rename(localPath, newName)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 创建本地文件
|
||||||
|
localFile, err := os.Create(localPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyFileRemoteToLocal failed to creating local file: => %s", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer localFile.Close()
|
||||||
|
|
||||||
|
// 复制文件内容
|
||||||
|
_, err = io.Copy(localFile, remoteFile)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyFileRemoteToLocal failed to copying contents: => %s", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyDirRemoteToLocal 复制文件-本地到远程
|
||||||
|
func (s *SSHClientSFTP) CopyFileLocalToRemote(localPath, remotePath string) error {
|
||||||
|
// 打开本地文件
|
||||||
|
localFile, err := os.Open(localPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyFileLocalToRemote failed to opening local file: => %s", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer localFile.Close()
|
||||||
|
|
||||||
|
// 创建远程文件
|
||||||
|
remoteFile, err := s.Client.Create(remotePath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyFileLocalToRemote failed to creating remote file: => %s", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer remoteFile.Close()
|
||||||
|
|
||||||
|
// 复制文件内容
|
||||||
|
_, err = io.Copy(remoteFile, localFile)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("CopyFileLocalToRemote failed to copying contents: => %s", err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,7 +50,13 @@ func (c *ConnTelnet) NewClient() (*ConnTelnet, error) {
|
|||||||
// fmt.Fprintln(client, c.User)
|
// fmt.Fprintln(client, c.User)
|
||||||
// fmt.Fprintln(client, c.Password)
|
// fmt.Fprintln(client, c.Password)
|
||||||
|
|
||||||
|
// 需要确保接收方理解并正确处理发送窗口大小设置命令
|
||||||
|
client.Write([]byte{255, 251, 31}) // 发送窗口大小选项
|
||||||
|
client.Write([]byte{255, 250, 31, 0, 128, 0, 120, 255, 240}) // 发送窗口行和列的大小
|
||||||
c.Client = &client
|
c.Client = &client
|
||||||
|
|
||||||
|
// 排空连接登录的信息
|
||||||
|
c.RunCMD("")
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,32 +76,14 @@ func (c *ConnTelnet) RunCMD(cmd string) (string, error) {
|
|||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
tmp := make([]byte, 1024)
|
tmp := make([]byte, 1024)
|
||||||
|
|
||||||
// 排空连接登录的信息
|
|
||||||
for {
|
|
||||||
// 设置读取超时时间为100毫秒
|
|
||||||
conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
|
|
||||||
n, err := conn.Read(tmp)
|
|
||||||
if err != nil {
|
|
||||||
// 判断是否是超时错误
|
|
||||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if n == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buf.Write(tmp[:n])
|
|
||||||
}
|
|
||||||
buf.Reset()
|
|
||||||
|
|
||||||
// 写入命令
|
// 写入命令
|
||||||
_, err := conn.Write([]byte(cmd))
|
if cmd != "" {
|
||||||
if err != nil {
|
if _, err := conn.Write([]byte(cmd)); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 读取本次响应命令消息
|
// 读取命令消息
|
||||||
for {
|
for {
|
||||||
// 设置读取超时时间为1000毫秒
|
// 设置读取超时时间为1000毫秒
|
||||||
conn.SetReadDeadline(time.Now().Add(1000 * time.Millisecond))
|
conn.SetReadDeadline(time.Now().Add(1000 * time.Millisecond))
|
||||||
@@ -119,35 +107,12 @@ func (c *ConnTelnet) RunCMD(cmd string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewClient 创建Telnet客户端会话对象
|
// NewClient 创建Telnet客户端会话对象
|
||||||
func (c *ConnTelnet) NewClientSession() (*TelnetClientSession, error) {
|
func (c *ConnTelnet) NewClientSession(cols, rows uint8) (*TelnetClientSession, error) {
|
||||||
if c.Client == nil {
|
if c.Client == nil {
|
||||||
return nil, fmt.Errorf("telnet client not connected")
|
return nil, fmt.Errorf("telnet client not connected")
|
||||||
}
|
}
|
||||||
conn := *c.Client
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
tmp := make([]byte, 1024)
|
|
||||||
// 排空连接登录的信息
|
|
||||||
for {
|
|
||||||
// 设置读取超时时间为5毫秒
|
|
||||||
conn.SetReadDeadline(time.Now().Add(5 * time.Millisecond))
|
|
||||||
n, err := conn.Read(tmp)
|
|
||||||
if err != nil {
|
|
||||||
// 判断是否是超时错误
|
|
||||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if n == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buf.Write(tmp[:n])
|
|
||||||
}
|
|
||||||
buf.Reset()
|
|
||||||
|
|
||||||
return &TelnetClientSession{
|
return &TelnetClientSession{
|
||||||
Client: conn,
|
Client: *c.Client,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"be.ems/src/framework/logger"
|
"be.ems/src/framework/logger"
|
||||||
redisCahe "be.ems/src/framework/redis"
|
redisCahe "be.ems/src/framework/redis"
|
||||||
"be.ems/src/framework/utils/generate"
|
"be.ems/src/framework/utils/generate"
|
||||||
|
"be.ems/src/framework/utils/machine"
|
||||||
"be.ems/src/framework/vo"
|
"be.ems/src/framework/vo"
|
||||||
|
|
||||||
jwt "github.com/golang-jwt/jwt/v5"
|
jwt "github.com/golang-jwt/jwt/v5"
|
||||||
@@ -74,7 +75,7 @@ func Create(loginUser *vo.LoginUser, ilobArgs ...string) string {
|
|||||||
|
|
||||||
// 生成令牌设置密钥
|
// 生成令牌设置密钥
|
||||||
secret := config.Get("jwt.secret").(string)
|
secret := config.Get("jwt.secret").(string)
|
||||||
tokenStr, err := jwtToken.SignedString([]byte(secret))
|
tokenStr, err := jwtToken.SignedString([]byte(machine.Code + "@" + secret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Infof("jwt sign err : %v", err)
|
logger.Infof("jwt sign err : %v", err)
|
||||||
return ""
|
return ""
|
||||||
@@ -118,7 +119,7 @@ func Verify(tokenString string) (jwt.MapClaims, error) {
|
|||||||
// 判断加密算法是预期的加密算法
|
// 判断加密算法是预期的加密算法
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); ok {
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); ok {
|
||||||
secret := config.Get("jwt.secret").(string)
|
secret := config.Get("jwt.secret").(string)
|
||||||
return []byte(secret), nil
|
return []byte(machine.Code + "@" + secret), nil
|
||||||
}
|
}
|
||||||
return nil, jwt.ErrSignatureInvalid
|
return nil, jwt.ErrSignatureInvalid
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ func Setup(router *gin.Engine) {
|
|||||||
|
|
||||||
// 系统可暴露的配置信息
|
// 系统可暴露的配置信息
|
||||||
indexGroup.GET("/sys-conf", controller.NewCommont.SysConfig)
|
indexGroup.GET("/sys-conf", controller.NewCommont.SysConfig)
|
||||||
|
// 系统引导初始化
|
||||||
|
guideGroup := router.Group("/bootloader")
|
||||||
|
{
|
||||||
|
guideGroup.POST("", controller.NewBootloader.Start)
|
||||||
|
guideGroup.PUT("", middleware.PreAuthorize(nil), controller.NewBootloader.Done)
|
||||||
|
guideGroup.DELETE("", middleware.PreAuthorize(nil), controller.NewBootloader.Reset)
|
||||||
|
guideGroup.PUT("/account", middleware.PreAuthorize(nil), controller.NewBootloader.Account)
|
||||||
|
}
|
||||||
|
|
||||||
// 验证码操作处理
|
// 验证码操作处理
|
||||||
indexGroup.GET("/captchaImage",
|
indexGroup.GET("/captchaImage",
|
||||||
|
|||||||
181
src/modules/common/controller/bootloader.go
Normal file
181
src/modules/common/controller/bootloader.go
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
adminConstants "be.ems/src/framework/constants/admin"
|
||||||
|
"be.ems/src/framework/constants/common"
|
||||||
|
tokenConstants "be.ems/src/framework/constants/token"
|
||||||
|
"be.ems/src/framework/i18n"
|
||||||
|
"be.ems/src/framework/utils/ctx"
|
||||||
|
"be.ems/src/framework/utils/machine"
|
||||||
|
"be.ems/src/framework/utils/regular"
|
||||||
|
tokenUtils "be.ems/src/framework/utils/token"
|
||||||
|
"be.ems/src/framework/vo"
|
||||||
|
"be.ems/src/framework/vo/result"
|
||||||
|
commonService "be.ems/src/modules/common/service"
|
||||||
|
systemService "be.ems/src/modules/system/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化控制层 BootloaderController 结构体
|
||||||
|
var NewBootloader = &BootloaderController{
|
||||||
|
accountService: commonService.NewAccountImpl,
|
||||||
|
sysUserService: systemService.NewSysUserImpl,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 系统引导初始化
|
||||||
|
//
|
||||||
|
// PATH /bootloader
|
||||||
|
type BootloaderController struct {
|
||||||
|
// 账号身份操作服务
|
||||||
|
accountService commonService.IAccount
|
||||||
|
// 用户信息服务
|
||||||
|
sysUserService systemService.ISysUser
|
||||||
|
}
|
||||||
|
|
||||||
|
// 首次引导开始
|
||||||
|
//
|
||||||
|
// POST /
|
||||||
|
func (s *BootloaderController) Start(c *gin.Context) {
|
||||||
|
// 是否完成引导
|
||||||
|
launchInfo := machine.LaunchInfo
|
||||||
|
if launchInfo == nil {
|
||||||
|
c.JSON(200, result.Err(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
|
||||||
|
c.JSON(200, result.ErrMsg("bootloader done"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询用户登录账号
|
||||||
|
sysUser := s.sysUserService.SelectUserById("1")
|
||||||
|
if sysUser.UserID != "1" {
|
||||||
|
c.JSON(200, result.ErrMsg("not found user data"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录用户信息
|
||||||
|
loginUser := vo.LoginUser{
|
||||||
|
UserID: sysUser.UserID,
|
||||||
|
DeptID: sysUser.DeptID,
|
||||||
|
User: sysUser,
|
||||||
|
Permissions: []string{adminConstants.PERMISSION},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当前请求信息
|
||||||
|
ipaddr, location := ctx.IPAddrLocation(c)
|
||||||
|
os, browser := ctx.UaOsBrowser(c)
|
||||||
|
|
||||||
|
// 生成令牌,创建系统访问记录
|
||||||
|
tokenStr := tokenUtils.Create(&loginUser, ipaddr, location, os, browser)
|
||||||
|
if tokenStr == "" {
|
||||||
|
c.JSON(200, result.Err(nil))
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
s.accountService.UpdateLoginDateAndIP(&loginUser)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(200, result.OkData(map[string]any{
|
||||||
|
tokenConstants.RESPONSE_FIELD: tokenStr,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 首次引导完成
|
||||||
|
//
|
||||||
|
// PUT /
|
||||||
|
func (s *BootloaderController) Done(c *gin.Context) {
|
||||||
|
// 是否完成引导
|
||||||
|
launchInfo := machine.LaunchInfo
|
||||||
|
if launchInfo == nil {
|
||||||
|
c.JSON(200, result.Err(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
|
||||||
|
c.JSON(200, result.ErrMsg("bootloader done"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标记引导完成
|
||||||
|
if err := machine.Bootloader(false); err != nil {
|
||||||
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除授权信息
|
||||||
|
tokenUtils.Remove(ctx.Authorization(c))
|
||||||
|
c.JSON(200, result.Ok(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 引导系统数据重置
|
||||||
|
//
|
||||||
|
// DELETE /
|
||||||
|
func (s *BootloaderController) Reset(c *gin.Context) {
|
||||||
|
// 是否完成引导
|
||||||
|
launchInfo := machine.LaunchInfo
|
||||||
|
if launchInfo == nil {
|
||||||
|
c.JSON(200, result.Err(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && v.(bool) {
|
||||||
|
c.JSON(200, result.ErrMsg("bootloader not done"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := machine.Reset(); err != nil {
|
||||||
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除授权信息
|
||||||
|
tokenUtils.Remove(ctx.Authorization(c))
|
||||||
|
c.JSON(200, result.Ok(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 账号变更
|
||||||
|
//
|
||||||
|
// PUT /account
|
||||||
|
func (s *BootloaderController) Account(c *gin.Context) {
|
||||||
|
language := ctx.AcceptLanguage(c)
|
||||||
|
var body struct {
|
||||||
|
UserName string `json:"username" binding:"required"`
|
||||||
|
Password string `json:"password" binding:"required"`
|
||||||
|
}
|
||||||
|
if err := c.ShouldBindJSON(&body); err != nil {
|
||||||
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !regular.ValidPassword(body.Password) {
|
||||||
|
// 登录密码至少包含大小写字母、数字、特殊符号,且不少于6位
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "user.errPasswd")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否完成引导
|
||||||
|
launchInfo := machine.LaunchInfo
|
||||||
|
if launchInfo == nil {
|
||||||
|
c.JSON(200, result.Err(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok && !v.(bool) {
|
||||||
|
c.JSON(200, result.ErrMsg("bootloader done"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询用户登录账号
|
||||||
|
sysUser := s.sysUserService.SelectUserById("2")
|
||||||
|
if sysUser.UserID != "2" {
|
||||||
|
c.JSON(200, result.ErrMsg("not found user data"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sysUser.UserName = body.UserName
|
||||||
|
sysUser.NickName = body.UserName
|
||||||
|
sysUser.Password = body.Password
|
||||||
|
sysUser.UpdateBy = ctx.LoginUserToUserName(c)
|
||||||
|
rows := s.sysUserService.UpdateUser(sysUser)
|
||||||
|
if rows > 0 {
|
||||||
|
c.JSON(200, result.Ok(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(200, result.Err(nil))
|
||||||
|
}
|
||||||
@@ -43,13 +43,6 @@ func (s *FileController) Download(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
routerPath := string(decodedBytes)
|
routerPath := string(decodedBytes)
|
||||||
// 地址文件名截取
|
|
||||||
fileName := routerPath[strings.LastIndex(routerPath, "/")+1:]
|
|
||||||
|
|
||||||
// 响应头
|
|
||||||
c.Writer.Header().Set("Content-Disposition", `attachment; filename="`+url.QueryEscape(fileName)+`"`)
|
|
||||||
c.Writer.Header().Set("Accept-Ranges", "bytes")
|
|
||||||
c.Writer.Header().Set("Content-Type", "application/octet-stream")
|
|
||||||
|
|
||||||
// 断点续传
|
// 断点续传
|
||||||
headerRange := c.GetHeader("Range")
|
headerRange := c.GetHeader("Range")
|
||||||
@@ -58,6 +51,12 @@ func (s *FileController) Download(c *gin.Context) {
|
|||||||
c.JSON(200, result.ErrMsg(err.Error()))
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 响应头
|
||||||
|
c.Writer.Header().Set("Content-Disposition", `attachment; filename="`+url.QueryEscape(filepath.Base(routerPath))+`"`)
|
||||||
|
c.Writer.Header().Set("Accept-Ranges", "bytes")
|
||||||
|
c.Writer.Header().Set("Content-Type", "application/octet-stream")
|
||||||
|
|
||||||
if headerRange != "" {
|
if headerRange != "" {
|
||||||
c.Writer.Header().Set("Content-Range", fmt.Sprint(resultMap["range"]))
|
c.Writer.Header().Set("Content-Range", fmt.Sprint(resultMap["range"]))
|
||||||
c.Writer.Header().Set("Content-Length", fmt.Sprint(resultMap["chunkSize"]))
|
c.Writer.Header().Set("Content-Length", fmt.Sprint(resultMap["chunkSize"]))
|
||||||
@@ -65,7 +64,6 @@ func (s *FileController) Download(c *gin.Context) {
|
|||||||
} else {
|
} else {
|
||||||
c.Writer.Header().Set("Content-Length", fmt.Sprint(resultMap["fileSize"]))
|
c.Writer.Header().Set("Content-Length", fmt.Sprint(resultMap["fileSize"]))
|
||||||
c.Status(200)
|
c.Status(200)
|
||||||
|
|
||||||
}
|
}
|
||||||
c.Writer.Write(resultMap["data"].([]byte))
|
c.Writer.Write(resultMap["data"].([]byte))
|
||||||
}
|
}
|
||||||
@@ -222,7 +220,7 @@ func (s *CommontController) TransferStaticFile(c *gin.Context) {
|
|||||||
|
|
||||||
delPrefix := strings.Replace(body.StaticPath, static["prefix"].(string), "", 1)
|
delPrefix := strings.Replace(body.StaticPath, static["prefix"].(string), "", 1)
|
||||||
staticPath := strings.Replace(delPrefix, "{language}", lang, 1)
|
staticPath := strings.Replace(delPrefix, "{language}", lang, 1)
|
||||||
newFile := fmt.Sprintf("%s%s", dir, staticPath)
|
newFile := filepath.ToSlash(fmt.Sprintf("%s%s", dir, staticPath))
|
||||||
|
|
||||||
err = file.CopyUploadFile(body.UploadPath, newFile)
|
err = file.CopyUploadFile(body.UploadPath, newFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
|
|
||||||
"be.ems/lib/global"
|
"be.ems/lib/global"
|
||||||
"be.ems/src/framework/config"
|
"be.ems/src/framework/config"
|
||||||
|
"be.ems/src/framework/constants/common"
|
||||||
|
"be.ems/src/framework/utils/machine"
|
||||||
systemService "be.ems/src/modules/system/service"
|
systemService "be.ems/src/modules/system/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,6 +31,17 @@ func (s *CommontImpl) SystemConfigInfo() map[string]string {
|
|||||||
infoMap["version"] = global.Version
|
infoMap["version"] = global.Version
|
||||||
infoMap["buildTime"] = global.BuildTime
|
infoMap["buildTime"] = global.BuildTime
|
||||||
infoMap["goVer"] = global.GoVer
|
infoMap["goVer"] = global.GoVer
|
||||||
|
// 系统首次使用标记
|
||||||
|
launchInfo := machine.LaunchInfo
|
||||||
|
if launchInfo != nil {
|
||||||
|
if v, ok := launchInfo[common.LAUNCH_BOOTLOADER]; ok {
|
||||||
|
infoMap[common.LAUNCH_BOOTLOADER] = fmt.Sprint(v)
|
||||||
|
} else {
|
||||||
|
infoMap[common.LAUNCH_BOOTLOADER] = "true"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
infoMap[common.LAUNCH_BOOTLOADER] = "true"
|
||||||
|
}
|
||||||
// 序列号
|
// 序列号
|
||||||
infoMap["serialNum"] = fmt.Sprint(config.Get("omc.sn"))
|
infoMap["serialNum"] = fmt.Sprint(config.Get("omc.sn"))
|
||||||
// 获取LOGO类型
|
// 获取LOGO类型
|
||||||
|
|||||||
80
src/modules/network_data/controller/smf.go
Normal file
80
src/modules/network_data/controller/smf.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"be.ems/src/framework/i18n"
|
||||||
|
"be.ems/src/framework/utils/ctx"
|
||||||
|
"be.ems/src/framework/utils/parse"
|
||||||
|
"be.ems/src/framework/vo/result"
|
||||||
|
"be.ems/src/modules/network_data/model"
|
||||||
|
neDataService "be.ems/src/modules/network_data/service"
|
||||||
|
neService "be.ems/src/modules/network_element/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化控制层 IMSController 结构体
|
||||||
|
var NewSMFController = &SMFController{
|
||||||
|
neInfoService: neService.NewNeInfoImpl,
|
||||||
|
cdrEventService: neDataService.NewSMFCDREventImpl,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网元IMS
|
||||||
|
//
|
||||||
|
// PATH /ims
|
||||||
|
type SMFController struct {
|
||||||
|
// 网元信息服务
|
||||||
|
neInfoService neService.INeInfo
|
||||||
|
// SMF CDR会话事件服务
|
||||||
|
cdrEventService neDataService.SMFCDREvent
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDR会话列表
|
||||||
|
//
|
||||||
|
// GET /cdr/list
|
||||||
|
func (s *SMFController) CDRList(c *gin.Context) {
|
||||||
|
language := ctx.AcceptLanguage(c)
|
||||||
|
var querys model.SMFCDREventQuery
|
||||||
|
if err := c.ShouldBindQuery(&querys); err != nil {
|
||||||
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询网元获取IP
|
||||||
|
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID)
|
||||||
|
if neInfo.NeId != querys.NeID || neInfo.IP == "" {
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
querys.RmUID = neInfo.RmUID
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
data := s.cdrEventService.SelectPage(querys)
|
||||||
|
c.JSON(200, result.Ok(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDR会话删除
|
||||||
|
//
|
||||||
|
// DELETE /cdr/:cdrIds
|
||||||
|
func (s *SMFController) CDRRemove(c *gin.Context) {
|
||||||
|
language := ctx.AcceptLanguage(c)
|
||||||
|
cdrIds := c.Param("cdrIds")
|
||||||
|
if cdrIds == "" {
|
||||||
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 处理字符转id数组后去重
|
||||||
|
ids := strings.Split(cdrIds, ",")
|
||||||
|
uniqueIDs := parse.RemoveDuplicates(ids)
|
||||||
|
if len(uniqueIDs) <= 0 {
|
||||||
|
c.JSON(200, result.Err(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rows, err := s.cdrEventService.DeleteByIds(uniqueIDs)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
|
||||||
|
c.JSON(200, result.OkMsg(msg))
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package model
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
// CDREvent CDR会话对象 cdr_event
|
// CDREvent CDR会话对象 cdr_event_ims/cdr_event_smf
|
||||||
type CDREvent struct {
|
type CDREvent struct {
|
||||||
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||||
NeType string `json:"neType" gorm:"column:ne_type"`
|
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||||
@@ -15,14 +15,16 @@ type CDREvent struct {
|
|||||||
|
|
||||||
// CDREventQuery CDR会话对象查询参数结构体
|
// CDREventQuery CDR会话对象查询参数结构体
|
||||||
type CDREventQuery struct {
|
type CDREventQuery struct {
|
||||||
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型, 暂时支持IMS
|
NeType string `json:"neType" form:"neType" binding:"required"` // 网元类型
|
||||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||||
RmUID string `json:"rmUID" form:"rmUID"`
|
RmUID string `json:"rmUID" form:"rmUID"`
|
||||||
RecordType string `json:"recordType" form:"recordType"` // 记录行为 MOC MTC MOSM MTSM
|
RecordType string `json:"recordType" form:"recordType"` // 记录行为 MOC MTC MOSM MTSM
|
||||||
StartTime string `json:"startTime" form:"startTime"`
|
CallerParty string `json:"callerParty" form:"callerParty"` // 主叫号码
|
||||||
EndTime string `json:"endTime" form:"endTime"`
|
CalledParty string `json:"calledParty" form:"calledParty"` // 被叫号码
|
||||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
StartTime string `json:"startTime" form:"startTime"`
|
||||||
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
EndTime string `json:"endTime" form:"endTime"`
|
||||||
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
|
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
||||||
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
|
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||||
|
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
|
||||||
|
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|||||||
35
src/modules/network_data/model/cdr_event_smf.go
Normal file
35
src/modules/network_data/model/cdr_event_smf.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// CDREvent CDR会话对象 cdr_event_smf
|
||||||
|
type CDREventSMF struct {
|
||||||
|
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
|
||||||
|
NeType string `json:"neType" gorm:"column:ne_type"`
|
||||||
|
NeName string `json:"neName" gorm:"column:ne_name"`
|
||||||
|
RmUID string `json:"rmUID" gorm:"column:rm_uid"`
|
||||||
|
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"`
|
||||||
|
RecordType string `json:"recordType" gorm:"column:record_type"`
|
||||||
|
ChargingID string `json:"chargingID" gorm:"column:charging_id"`
|
||||||
|
SubscriberID string `json:"subscriberID" gorm:"column:subscriber_id"`
|
||||||
|
Duration string `json:"duration" gorm:"column:duration"`
|
||||||
|
DataVolumeUplink string `json:"dataVolumeUplink" gorm:"column:data_volume_uplink"`
|
||||||
|
DataVolumeDownlink string `json:"dataVolumeDownlink" gorm:"column:data_volume_downlink"`
|
||||||
|
DataTotalVolume string `json:"dataTotalVolume" gorm:"column:data_total_volume"`
|
||||||
|
PDUAddress string `json:"pduAddress" gorm:"column:pdu_address"`
|
||||||
|
CreatedAt time.Time `json:"createdAt" gorm:"column:created_at;default:CURRENT_TIMESTAMP"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SMFCDREventQuery struct {
|
||||||
|
NeType string `json:"neType" form:"neType" binding:"required"` // SMF
|
||||||
|
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||||
|
RmUID string `json:"rmUID" form:"rmUID"`
|
||||||
|
RecordType string `json:"recordType" form:"recordType"`
|
||||||
|
SubscriberID string `json:"subscriberID" form:"subscriberID"`
|
||||||
|
StartTime string `json:"startTime" form:"startTime"`
|
||||||
|
EndTime string `json:"endTime" form:"endTime"`
|
||||||
|
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
||||||
|
SortOrder string `json:"sortOrder" form:"sortOrder" binding:"omitempty,oneof=asc desc"` // 排序升降序,asc desc
|
||||||
|
PageNum int64 `json:"pageNum" form:"pageNum" binding:"required"`
|
||||||
|
PageSize int64 `json:"pageSize" form:"pageSize" binding:"required"`
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ type UEEventQuery struct {
|
|||||||
NeID string `json:"neId" form:"neId" binding:"required"`
|
NeID string `json:"neId" form:"neId" binding:"required"`
|
||||||
RmUID string `json:"rmUID" form:"rmUID"`
|
RmUID string `json:"rmUID" form:"rmUID"`
|
||||||
EventType string `json:"eventType" form:"eventType"` // 事件类型 auth-result detach cm-state
|
EventType string `json:"eventType" form:"eventType"` // 事件类型 auth-result detach cm-state
|
||||||
|
IMSI string `json:"imsi" form:"imsi"` // imsi
|
||||||
StartTime string `json:"startTime" form:"startTime"`
|
StartTime string `json:"startTime" form:"startTime"`
|
||||||
EndTime string `json:"endTime" form:"endTime"`
|
EndTime string `json:"endTime" form:"endTime"`
|
||||||
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
SortField string `json:"sortField" form:"sortField" binding:"omitempty,oneof=timestamp"` // 排序字段,填写结果字段
|
||||||
|
|||||||
@@ -57,6 +57,22 @@ func Setup(router *gin.Engine) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 网元SMF
|
||||||
|
smfGroup := neDataGroup.Group("/smf")
|
||||||
|
{
|
||||||
|
// CDR会话事件列表
|
||||||
|
smfGroup.GET("/cdr/list",
|
||||||
|
middleware.PreAuthorize(nil),
|
||||||
|
controller.NewSMFController.CDRList,
|
||||||
|
)
|
||||||
|
// CDR会话删除
|
||||||
|
smfGroup.DELETE("/cdr/:cdrIds",
|
||||||
|
middleware.PreAuthorize(nil),
|
||||||
|
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_DELETE)),
|
||||||
|
controller.NewSMFController.CDRRemove,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// 网元AMF
|
// 网元AMF
|
||||||
amfGroup := neDataGroup.Group("/amf")
|
amfGroup := neDataGroup.Group("/amf")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,3 +13,15 @@ type ICDREvent interface {
|
|||||||
// DeleteByIds 批量删除信息
|
// DeleteByIds 批量删除信息
|
||||||
DeleteByIds(cdrIds []string) int64
|
DeleteByIds(cdrIds []string) int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SMF CDR Event
|
||||||
|
type SMFCDREvent interface {
|
||||||
|
// SelectPage 根据条件分页查询
|
||||||
|
SelectPage(querys model.SMFCDREventQuery) map[string]any
|
||||||
|
|
||||||
|
// SelectByIds 通过ID查询
|
||||||
|
SelectByIds(cdrIds []string) []model.CDREventSMF
|
||||||
|
|
||||||
|
// DeleteByIds 批量删除信息
|
||||||
|
DeleteByIds(cdrIds []string) int64
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
// 实例化数据层 CDREventImpl 结构体
|
// 实例化数据层 CDREventImpl 结构体
|
||||||
var NewCDREventImpl = &CDREventImpl{
|
var NewCDREventImpl = &CDREventImpl{
|
||||||
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event`,
|
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, cdr_json, created_at from cdr_event_ims`,
|
||||||
|
|
||||||
resultMap: map[string]string{
|
resultMap: map[string]string{
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
@@ -35,6 +35,36 @@ type CDREventImpl struct {
|
|||||||
resultMap map[string]string
|
resultMap map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instance of SMF CDREventImpl
|
||||||
|
var NewSMFCDREventImpl = &SMFCDREventImpl{
|
||||||
|
selectSql: `select id, ne_type, ne_name, rm_uid, timestamp, JSON_EXTRACT(cdr_json, '$.recordType') AS record_type, JSON_EXTRACT(cdr_json, '$.chargingID') AS charging_id, JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') AS subscriber_id, JSON_EXTRACT(cdr_json, '$.duration') AS duration, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeUplink') AS data_volume_uplink, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataVolumeDownlink') AS data_volume_downlink, JSON_EXTRACT(cdr_json, '$.listOfMultipleUnitUsage[*].usedUnitContainer[*].dataTotalVolume') AS data_total_volume, JSON_EXTRACT(cdr_json, '$.pDUSessionChargingInformation.pDUAddress') AS pdu_address, created_at from cdr_event_smf`,
|
||||||
|
|
||||||
|
resultMap: map[string]string{
|
||||||
|
"id": "ID",
|
||||||
|
"ne_type": "NeType",
|
||||||
|
"ne_name": "NeName",
|
||||||
|
"rm_uid": "RmUID",
|
||||||
|
"timestamp": "Timestamp",
|
||||||
|
"record_type": "RecordType",
|
||||||
|
"charging_id": "ChargingID",
|
||||||
|
"subscriber_id": "SubscriberID",
|
||||||
|
"duration": "Duration",
|
||||||
|
"data_volume_uplink": "DataVolumeUplink",
|
||||||
|
"data_volume_downlink": "DataVolumeDownlink",
|
||||||
|
"data_total_volume": "DataTotalVolume",
|
||||||
|
"pdu_address": "PDUAddress",
|
||||||
|
"created_at": "CreatedAt",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// CDREventImpl CDR会话事件 数据层处理
|
||||||
|
type SMFCDREventImpl struct {
|
||||||
|
// 查询视图对象SQL
|
||||||
|
selectSql string
|
||||||
|
// 结果字段与实体映射
|
||||||
|
resultMap map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
// convertResultRows 将结果记录转实体结果组
|
// convertResultRows 将结果记录转实体结果组
|
||||||
func (r *CDREventImpl) convertResultRows(rows []map[string]any) []model.CDREvent {
|
func (r *CDREventImpl) convertResultRows(rows []map[string]any) []model.CDREvent {
|
||||||
arr := make([]model.CDREvent, 0)
|
arr := make([]model.CDREvent, 0)
|
||||||
@@ -63,10 +93,6 @@ func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
|
|||||||
conditions = append(conditions, "rm_uid = ?")
|
conditions = append(conditions, "rm_uid = ?")
|
||||||
params = append(params, querys.RmUID)
|
params = append(params, querys.RmUID)
|
||||||
}
|
}
|
||||||
if querys.RmUID != "" {
|
|
||||||
conditions = append(conditions, "rm_uid = ?")
|
|
||||||
params = append(params, querys.RmUID)
|
|
||||||
}
|
|
||||||
if querys.StartTime != "" {
|
if querys.StartTime != "" {
|
||||||
conditions = append(conditions, "timestamp >= ?")
|
conditions = append(conditions, "timestamp >= ?")
|
||||||
beginDate := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS)
|
beginDate := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||||
@@ -77,6 +103,14 @@ func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
|
|||||||
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
|
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||||
params = append(params, endDate.Unix())
|
params = append(params, endDate.Unix())
|
||||||
}
|
}
|
||||||
|
if querys.CallerParty != "" {
|
||||||
|
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.callerParty') = ?")
|
||||||
|
params = append(params, querys.CallerParty)
|
||||||
|
}
|
||||||
|
if querys.CalledParty != "" {
|
||||||
|
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.calledParty') = ?")
|
||||||
|
params = append(params, querys.CalledParty)
|
||||||
|
}
|
||||||
if querys.RecordType != "" {
|
if querys.RecordType != "" {
|
||||||
recordTypes := strings.Split(querys.RecordType, ",")
|
recordTypes := strings.Split(querys.RecordType, ",")
|
||||||
placeholder := repo.KeyPlaceholderByQuery(len(recordTypes))
|
placeholder := repo.KeyPlaceholderByQuery(len(recordTypes))
|
||||||
@@ -98,7 +132,7 @@ func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查询数量 长度为0直接返回
|
// 查询数量 长度为0直接返回
|
||||||
totalSql := "select count(1) as 'total' from cdr_event"
|
totalSql := "select count(1) as 'total' from cdr_event_ims"
|
||||||
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("total err => %v", err)
|
logger.Errorf("total err => %v", err)
|
||||||
@@ -160,7 +194,146 @@ func (r *CDREventImpl) SelectByIds(cdrIds []string) []model.CDREvent {
|
|||||||
// DeleteByIds 批量删除信息
|
// DeleteByIds 批量删除信息
|
||||||
func (r *CDREventImpl) DeleteByIds(cdrIds []string) int64 {
|
func (r *CDREventImpl) DeleteByIds(cdrIds []string) int64 {
|
||||||
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||||
sql := "delete from cdr_event where id in (" + placeholder + ")"
|
sql := "delete from cdr_event_ims where id in (" + placeholder + ")"
|
||||||
|
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||||
|
results, err := datasource.ExecDB("", sql, parameters)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("delete err => %v", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertResultRows 将结果记录转实体结果组
|
||||||
|
func (r *SMFCDREventImpl) convertResultRows(rows []map[string]any) []model.CDREventSMF {
|
||||||
|
arr := make([]model.CDREventSMF, 0)
|
||||||
|
for _, row := range rows {
|
||||||
|
item := model.CDREventSMF{}
|
||||||
|
for key, value := range row {
|
||||||
|
if keyMapper, ok := r.resultMap[key]; ok {
|
||||||
|
repo.SetFieldValue(&item, keyMapper, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr = append(arr, item)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectPage 根据条件分页查询
|
||||||
|
func (r *SMFCDREventImpl) SelectPage(querys model.SMFCDREventQuery) map[string]any {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
if querys.NeType != "" {
|
||||||
|
conditions = append(conditions, "ne_type = ?")
|
||||||
|
params = append(params, querys.NeType)
|
||||||
|
}
|
||||||
|
if querys.RmUID != "" {
|
||||||
|
conditions = append(conditions, "rm_uid = ?")
|
||||||
|
params = append(params, querys.RmUID)
|
||||||
|
}
|
||||||
|
if querys.StartTime != "" {
|
||||||
|
conditions = append(conditions, "timestamp >= ?")
|
||||||
|
beginDate := date.ParseStrToDate(querys.StartTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||||
|
params = append(params, beginDate.Unix())
|
||||||
|
}
|
||||||
|
if querys.EndTime != "" {
|
||||||
|
conditions = append(conditions, "timestamp <= ?")
|
||||||
|
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||||
|
params = append(params, endDate.Unix())
|
||||||
|
}
|
||||||
|
if querys.RecordType != "" {
|
||||||
|
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.recordType') = ?")
|
||||||
|
params = append(params, querys.RecordType)
|
||||||
|
}
|
||||||
|
if querys.SubscriberID != "" {
|
||||||
|
conditions = append(conditions, "JSON_EXTRACT(cdr_json, '$.subscriberIdentifier.subscriptionIDData') = ?")
|
||||||
|
params = append(params, querys.SubscriberID)
|
||||||
|
}
|
||||||
|
// if querys.RecordType != "" {
|
||||||
|
// recordTypes := strings.Split(querys.RecordType, ",")
|
||||||
|
// placeholder := repo.KeyPlaceholderByQuery(len(recordTypes))
|
||||||
|
// conditions = append(conditions, fmt.Sprintf("JSON_EXTRACT(cdr_json, '$.recordType') in (%s)", placeholder))
|
||||||
|
// for _, recordType := range recordTypes {
|
||||||
|
// params = append(params, recordType)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
result := map[string]any{
|
||||||
|
"total": 0,
|
||||||
|
"rows": []model.CDREventSMF{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数量 长度为0直接返回
|
||||||
|
totalSql := "select count(1) as 'total' from cdr_event_smf"
|
||||||
|
totalRows, err := datasource.RawDB("", totalSql+whereSql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("total err => %v", err)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
total := parse.Number(totalRows[0]["total"])
|
||||||
|
if total == 0 {
|
||||||
|
return result
|
||||||
|
} else {
|
||||||
|
result["total"] = total
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize)
|
||||||
|
pageSql := " limit ?,? "
|
||||||
|
params = append(params, pageNum*pageSize)
|
||||||
|
params = append(params, pageSize)
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
orderSql := ""
|
||||||
|
if querys.SortField != "" {
|
||||||
|
sortSql := querys.SortField
|
||||||
|
if querys.SortOrder != "" {
|
||||||
|
if querys.SortOrder == "desc" {
|
||||||
|
sortSql += " desc "
|
||||||
|
} else {
|
||||||
|
sortSql += " asc "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
querySql := r.selectSql + whereSql + orderSql + pageSql
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换实体
|
||||||
|
result["rows"] = r.convertResultRows(results)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectByIds 通过ID查询
|
||||||
|
func (r *SMFCDREventImpl) SelectByIds(cdrIds []string) []model.CDREventSMF {
|
||||||
|
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||||
|
querySql := r.selectSql + " where id in (" + placeholder + ")"
|
||||||
|
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||||
|
results, err := datasource.RawDB("", querySql, parameters)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return []model.CDREventSMF{}
|
||||||
|
}
|
||||||
|
// 转换实体
|
||||||
|
return r.convertResultRows(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteByIds 批量删除信息
|
||||||
|
func (r *SMFCDREventImpl) DeleteByIds(cdrIds []string) int64 {
|
||||||
|
placeholder := repo.KeyPlaceholderByQuery(len(cdrIds))
|
||||||
|
sql := "delete from cdr_event_smf where id in (" + placeholder + ")"
|
||||||
parameters := repo.ConvertIdsSlice(cdrIds)
|
parameters := repo.ConvertIdsSlice(cdrIds)
|
||||||
results, err := datasource.ExecDB("", sql, parameters)
|
results, err := datasource.ExecDB("", sql, parameters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -7,9 +7,15 @@ type IPerfKPI interface {
|
|||||||
// SelectGoldKPI 通过网元指标数据信息
|
// SelectGoldKPI 通过网元指标数据信息
|
||||||
SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) []map[string]any
|
SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) []map[string]any
|
||||||
|
|
||||||
|
// select from new kpi report table, exp. kpi_report_upf
|
||||||
|
SelectKpiReport(query model.GoldKPIQuery, kpiIds []string) []map[string]any
|
||||||
|
|
||||||
// SelectGoldKPITitle 网元对应的指标名称
|
// SelectGoldKPITitle 网元对应的指标名称
|
||||||
SelectGoldKPITitle(neType string) []model.GoldKPITitle
|
SelectGoldKPITitle(neType string) []model.GoldKPITitle
|
||||||
|
|
||||||
// SelectUPFTotalFlow 查询UPF总流量 N3上行 N6下行
|
// SelectUPFTotalFlow 查询UPF总流量 N3上行 N6下行
|
||||||
SelectUPFTotalFlow(neType, rmUID, startDate, endDate string) map[string]any
|
SelectUPFTotalFlow(neType, rmUID, startDate, endDate string) map[string]any
|
||||||
|
|
||||||
|
// select upf throughput from new kpi_report
|
||||||
|
SelectUPFThroughput(neType, rmUID, startDate, endDate string) map[string]any
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,79 @@ func (r *PerfKPIImpl) SelectGoldKPI(query model.GoldKPIQuery, kpiIds []string) [
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *PerfKPIImpl) SelectKpiReport(query model.GoldKPIQuery, kpiIds []string) []map[string]any {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
var tableName string = "kpi_report_"
|
||||||
|
if query.RmUID != "" {
|
||||||
|
conditions = append(conditions, "gk.rm_uid = ?")
|
||||||
|
params = append(params, query.RmUID)
|
||||||
|
}
|
||||||
|
if query.NeType != "" {
|
||||||
|
conditions = append(conditions, "gk.ne_type = ?")
|
||||||
|
params = append(params, query.NeType)
|
||||||
|
tableName += strings.ToLower(query.NeType)
|
||||||
|
}
|
||||||
|
var dateTimeStr string = "CONCAT(gk.`date`, \" \", gk.start_time)"
|
||||||
|
if query.StartTime != "" {
|
||||||
|
conditions = append(conditions, dateTimeStr+" >= ?")
|
||||||
|
params = append(params, query.StartTime)
|
||||||
|
}
|
||||||
|
if query.EndTime != "" {
|
||||||
|
conditions = append(conditions, dateTimeStr+" <= ?")
|
||||||
|
params = append(params, query.EndTime)
|
||||||
|
}
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询字段列
|
||||||
|
timeFormat := "DATE_FORMAT(" + dateTimeStr + ", '%Y-%m-%d %H:%i:')"
|
||||||
|
secondGroup := fmt.Sprintf("LPAD(FLOOR(SECOND(gk.start_time) / %d) * %d, 2, '0')", query.Interval, query.Interval)
|
||||||
|
groupByField := fmt.Sprintf("CONCAT( %s, %s ) AS timeGroup", timeFormat, secondGroup)
|
||||||
|
if query.Interval > 60 {
|
||||||
|
minute := query.Interval / 60
|
||||||
|
timeFormat = "DATE_FORMAT(" + dateTimeStr + ", '%Y-%m-%d %H:')"
|
||||||
|
minuteGroup := fmt.Sprintf("LPAD(FLOOR(MINUTE(gk.start_time) / %d) * %d, 2, '0')", minute, minute)
|
||||||
|
groupByField = fmt.Sprintf("CONCAT( %s, %s ) AS timeGroup", timeFormat, minuteGroup)
|
||||||
|
}
|
||||||
|
var fields = []string{
|
||||||
|
groupByField,
|
||||||
|
"min(CASE WHEN gk.index != '' THEN gk.index ELSE 0 END) AS startIndex",
|
||||||
|
"min(CASE WHEN gk.ne_type != '' THEN gk.ne_type ELSE 0 END) AS neType",
|
||||||
|
"min(CASE WHEN gk.ne_name != '' THEN gk.ne_name ELSE 0 END) AS neName",
|
||||||
|
}
|
||||||
|
for i, kid := range kpiIds {
|
||||||
|
// 特殊字段,只取最后一次收到的非0值
|
||||||
|
if kid == "AMF.01" || kid == "UDM.01" || kid == "UDM.02" || kid == "UDM.03" || kid == "SMF.01" {
|
||||||
|
str := fmt.Sprintf("IFNULL(SUBSTRING_INDEX(GROUP_CONCAT( CASE WHEN JSON_EXTRACT(gk.kpi_values, '$[%d].kpi_id') = '%s' THEN JSON_EXTRACT(gk.kpi_values, '$[%d].value') END ), ',', 1), 0) AS '%s'", i, kid, i, kid)
|
||||||
|
fields = append(fields, str)
|
||||||
|
} else {
|
||||||
|
str := fmt.Sprintf("sum(CASE WHEN JSON_EXTRACT(gk.kpi_values, '$[%d].kpi_id') = '%s' THEN JSON_EXTRACT(gk.kpi_values, '$[%d].value') ELSE 0 END) AS '%s'", i, kid, i, kid)
|
||||||
|
fields = append(fields, str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fieldsSql := strings.Join(fields, ",")
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
if query.SortField == "" {
|
||||||
|
query.SortField = "timeGroup"
|
||||||
|
}
|
||||||
|
if query.SortOrder == "" {
|
||||||
|
query.SortOrder = "desc"
|
||||||
|
}
|
||||||
|
orderSql := fmt.Sprintf(" order by %s %s", query.SortField, query.SortOrder)
|
||||||
|
querySql := fmt.Sprintf("SELECT %s FROM %s gk %s GROUP BY timeGroup %s", fieldsSql, tableName, whereSql, orderSql)
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
// SelectGoldKPITitle 网元对应的指标名称
|
// SelectGoldKPITitle 网元对应的指标名称
|
||||||
func (r *PerfKPIImpl) SelectGoldKPITitle(neType string) []model.GoldKPITitle {
|
func (r *PerfKPIImpl) SelectGoldKPITitle(neType string) []model.GoldKPITitle {
|
||||||
result := []model.GoldKPITitle{}
|
result := []model.GoldKPITitle{}
|
||||||
@@ -131,3 +204,39 @@ func (r *PerfKPIImpl) SelectUPFTotalFlow(neType, rmUID, startDate, endDate strin
|
|||||||
}
|
}
|
||||||
return results[0]
|
return results[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SelectUPFTotalFlow 查询UPF总流量 N3上行 N6下行
|
||||||
|
func (r *PerfKPIImpl) SelectUPFThroughput(neType, rmUID, startDate, endDate string) map[string]any {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
if neType != "" {
|
||||||
|
conditions = append(conditions, "gk.ne_type = ?")
|
||||||
|
params = append(params, neType)
|
||||||
|
}
|
||||||
|
if rmUID != "" {
|
||||||
|
conditions = append(conditions, "gk.rm_uid = ?")
|
||||||
|
params = append(params, rmUID)
|
||||||
|
}
|
||||||
|
if startDate != "" {
|
||||||
|
conditions = append(conditions, "gk.date >= ?")
|
||||||
|
params = append(params, startDate)
|
||||||
|
}
|
||||||
|
if endDate != "" {
|
||||||
|
conditions = append(conditions, "gk.date <= ?")
|
||||||
|
params = append(params, endDate)
|
||||||
|
}
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
querySql := fmt.Sprintf("SELECT sum( CASE WHEN JSON_EXTRACT(gk.kpi_values, '$[2].kpi_id') = 'UPF.03' THEN JSON_EXTRACT(gk.kpi_values, '$[2].value') ELSE 0 END ) AS 'up', sum( CASE WHEN JSON_EXTRACT(gk.kpi_values, '$[5].kpi_id') = 'UPF.06' THEN JSON_EXTRACT(gk.kpi_values, '$[5].value') ELSE 0 END ) AS 'down' FROM kpi_report_upf gk %s", whereSql)
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
}
|
||||||
|
return results[0]
|
||||||
|
}
|
||||||
|
|||||||
@@ -74,6 +74,10 @@ func (r *UEEventImpl) SelectPage(querys model.UEEventQuery) map[string]any {
|
|||||||
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
|
endDate := date.ParseStrToDate(querys.EndTime, date.YYYY_MM_DD_HH_MM_SS)
|
||||||
params = append(params, endDate.Unix())
|
params = append(params, endDate.Unix())
|
||||||
}
|
}
|
||||||
|
if querys.IMSI != "" {
|
||||||
|
conditions = append(conditions, "JSON_EXTRACT(event_json, '$.imsi') = ?")
|
||||||
|
params = append(params, querys.IMSI)
|
||||||
|
}
|
||||||
if querys.EventType != "" {
|
if querys.EventType != "" {
|
||||||
eventTypes := strings.Split(querys.EventType, ",")
|
eventTypes := strings.Split(querys.EventType, ",")
|
||||||
placeholder := repo.KeyPlaceholderByQuery(len(eventTypes))
|
placeholder := repo.KeyPlaceholderByQuery(len(eventTypes))
|
||||||
|
|||||||
@@ -10,3 +10,12 @@ type ICDREvent interface {
|
|||||||
// DeleteByIds 批量删除信息
|
// DeleteByIds 批量删除信息
|
||||||
DeleteByIds(cdrIds []string) (int64, error)
|
DeleteByIds(cdrIds []string) (int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CDR会话事件 服务层接口
|
||||||
|
type SMFCDREvent interface {
|
||||||
|
// SelectPage 根据条件分页查询
|
||||||
|
SelectPage(querys model.SMFCDREventQuery) map[string]any
|
||||||
|
|
||||||
|
// DeleteByIds 批量删除信息
|
||||||
|
DeleteByIds(cdrIds []string) (int64, error)
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,12 +12,21 @@ var NewCDREventImpl = &CDREventImpl{
|
|||||||
cdrEventRepository: repository.NewCDREventImpl,
|
cdrEventRepository: repository.NewCDREventImpl,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var NewSMFCDREventImpl = &SMFCDREventImpl{
|
||||||
|
cdrEventRepository: repository.NewSMFCDREventImpl,
|
||||||
|
}
|
||||||
|
|
||||||
// CDREventImpl CDR会话事件 服务层处理
|
// CDREventImpl CDR会话事件 服务层处理
|
||||||
type CDREventImpl struct {
|
type CDREventImpl struct {
|
||||||
// CDR会话事件数据信息
|
// CDR会话事件数据信息
|
||||||
cdrEventRepository repository.ICDREvent
|
cdrEventRepository repository.ICDREvent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SMFCDREventImpl struct {
|
||||||
|
// CDR会话事件数据信息
|
||||||
|
cdrEventRepository repository.SMFCDREvent
|
||||||
|
}
|
||||||
|
|
||||||
// SelectPage 根据条件分页查询
|
// SelectPage 根据条件分页查询
|
||||||
func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
|
func (r *CDREventImpl) SelectPage(querys model.CDREventQuery) map[string]any {
|
||||||
return r.cdrEventRepository.SelectPage(querys)
|
return r.cdrEventRepository.SelectPage(querys)
|
||||||
@@ -38,3 +47,23 @@ func (r *CDREventImpl) DeleteByIds(cdrIds []string) (int64, error) {
|
|||||||
// 删除信息失败!
|
// 删除信息失败!
|
||||||
return 0, fmt.Errorf("delete fail")
|
return 0, fmt.Errorf("delete fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *SMFCDREventImpl) SelectPage(querys model.SMFCDREventQuery) map[string]any {
|
||||||
|
return r.cdrEventRepository.SelectPage(querys)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteByIds 批量删除信息
|
||||||
|
func (r *SMFCDREventImpl) DeleteByIds(cdrIds []string) (int64, error) {
|
||||||
|
// 检查是否存在
|
||||||
|
ids := r.cdrEventRepository.SelectByIds(cdrIds)
|
||||||
|
if len(ids) <= 0 {
|
||||||
|
return 0, fmt.Errorf("not data")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ids) == len(cdrIds) {
|
||||||
|
rows := r.cdrEventRepository.DeleteByIds(cdrIds)
|
||||||
|
return rows, nil
|
||||||
|
}
|
||||||
|
// 删除信息失败!
|
||||||
|
return 0, fmt.Errorf("delete fail")
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ func (r *PerfKPIImpl) SelectGoldKPI(query model.GoldKPIQuery) []map[string]any {
|
|||||||
kpiIds = append(kpiIds, kpiId.KPIID)
|
kpiIds = append(kpiIds, kpiId.KPIID)
|
||||||
}
|
}
|
||||||
|
|
||||||
data := r.perfKPIRepository.SelectGoldKPI(query, kpiIds)
|
//data := r.perfKPIRepository.SelectGoldKPI(query, kpiIds)
|
||||||
|
data := r.perfKPIRepository.SelectKpiReport(query, kpiIds)
|
||||||
if data == nil {
|
if data == nil {
|
||||||
return []map[string]any{}
|
return []map[string]any{}
|
||||||
}
|
}
|
||||||
@@ -66,7 +67,8 @@ func (r *PerfKPIImpl) SelectUPFTotalFlow(neType, rmUID string, day int) map[stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info = r.perfKPIRepository.SelectUPFTotalFlow(neType, rmUID, startDate, endDate)
|
//info = r.perfKPIRepository.SelectUPFTotalFlow(neType, rmUID, startDate, endDate)
|
||||||
|
info = r.perfKPIRepository.SelectUPFThroughput(neType, rmUID, startDate, endDate)
|
||||||
|
|
||||||
// 保存到缓存
|
// 保存到缓存
|
||||||
infoJSON, _ := json.Marshal(info)
|
infoJSON, _ := json.Marshal(info)
|
||||||
|
|||||||
@@ -155,3 +155,52 @@ func (s *NeActionController) Files(c *gin.Context) {
|
|||||||
"rows": splitRows,
|
"rows": splitRows,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 网元服务操作
|
||||||
|
//
|
||||||
|
// PUT /service
|
||||||
|
func (s *NeActionController) Service(c *gin.Context) {
|
||||||
|
language := ctx.AcceptLanguage(c)
|
||||||
|
var body struct {
|
||||||
|
NeType string `json:"neType" binding:"required"`
|
||||||
|
NeID string `json:"neId" binding:"required"`
|
||||||
|
Action string `json:"action" binding:"required,oneof=start restart stop reboot poweroff"` // 操作行为
|
||||||
|
}
|
||||||
|
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
|
||||||
|
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询网元获取IP
|
||||||
|
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(body.NeType, body.NeID)
|
||||||
|
if neInfo.NeId != body.NeID || neInfo.IP == "" {
|
||||||
|
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
neTypeLower := strings.ToLower(neInfo.NeType)
|
||||||
|
cmdStr := fmt.Sprintf("sudo service %s %s", neTypeLower, body.Action)
|
||||||
|
if neTypeLower == "omc" {
|
||||||
|
cmdStr = fmt.Sprintf("nohup sh -c \"sudo systemctl stop restagent && sleep 5s && sudo systemctl %s restagent\" > /dev/null 2>&1 &", body.Action)
|
||||||
|
} else if neTypeLower == "ims" {
|
||||||
|
if body.Action == "restart" {
|
||||||
|
cmdStr = "sudo ims-stop || true && sudo ims-start"
|
||||||
|
} else {
|
||||||
|
cmdStr = fmt.Sprintf("sudo ims-%s", body.Action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if body.Action == "reboot" {
|
||||||
|
cmdStr = "sudo shutdown -r now"
|
||||||
|
}
|
||||||
|
if body.Action == "poweroff" {
|
||||||
|
cmdStr = "sudo shutdown -h now"
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := s.neInfoService.NeRunCMD(body.NeType, body.NeID, cmdStr)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(200, result.ErrMsg(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(200, result.Ok(nil))
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user