Some checks failed
Go / build (push) Failing after 19s
- 新增联系人保存与删除逻辑处理 - 新增工厂信息保存逻辑,支持银行、财务等详细信息 - 部门与员工模块接口参数调整,统一使用实体对象返回 - 优化部门与员工的增删改查操作,去除冗余代码 - 统一使用 constant 包管理业务类型常量 - 增加性别转换与整型数组转字符串工具函数 - RPC 注册新增工厂与联系人服务路由 - 调整客户端调用参数结构,增强代码可读性与维护性
358 lines
8.0 KiB
Go
358 lines
8.0 KiB
Go
package common
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/md5"
|
|
"encoding/hex"
|
|
"io"
|
|
"math/rand"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"golang.org/x/text/encoding/simplifiedchinese"
|
|
"golang.org/x/text/transform"
|
|
)
|
|
|
|
// @Title 随机数种子
|
|
func init() {
|
|
// 随机数种子
|
|
rand.Seed(time.Now().UnixNano())
|
|
}
|
|
|
|
// MD5 @Title md5加密
|
|
func MD5(str string) string {
|
|
h := md5.New()
|
|
h.Write([]byte(str))
|
|
return hex.EncodeToString(h.Sum(nil))
|
|
}
|
|
|
|
// RandStr @Title 生成随机数
|
|
func RandStr(n int, str ...string) string {
|
|
s := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
|
|
if len(str) > 0 {
|
|
s = str[0]
|
|
}
|
|
res := ""
|
|
for i := 0; i < n; i++ {
|
|
res += string(s[rand.Intn(len(s))])
|
|
}
|
|
return res
|
|
}
|
|
|
|
// InArray @Title 是否在数组中
|
|
func InArray[T comparable](need T, array []T) bool {
|
|
for _, item := range array {
|
|
if item == need {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// CreateDateDir 根据当前日期来创建文件夹
|
|
func CreateDateDir(Path string) string {
|
|
folderName := time.Now().Format("20060102")
|
|
folderPath := filepath.Join(Path, folderName)
|
|
if _, err := os.Stat(folderPath); os.IsNotExist(err) {
|
|
os.MkdirAll(folderPath, 0755)
|
|
}
|
|
return folderName
|
|
}
|
|
|
|
// DownloadFormUrl @Title 下载文件
|
|
func DownloadFormUrl(src string, filename string) error {
|
|
res, err := http.Get(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer res.Body.Close()
|
|
// 获得get请求响应的reader对象
|
|
body, err := io.ReadAll(res.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out, err := os.Create(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := io.Copy(out, bytes.NewReader(body)); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Utf8ToGbk @Title utf8转gbk
|
|
func Utf8ToGbk(source string) string {
|
|
result, _, _ := transform.String(simplifiedchinese.GBK.NewEncoder(), source)
|
|
return result
|
|
}
|
|
|
|
// GbkToUtf8 @Title gbk转utf8
|
|
func GbkToUtf8(source string) string {
|
|
result, _, _ := transform.String(simplifiedchinese.GBK.NewDecoder(), source)
|
|
return result
|
|
}
|
|
|
|
// GetPassword @Title 密码加密
|
|
func GetPassword(password, salt string) string {
|
|
return MD5(salt + MD5(password+salt))
|
|
}
|
|
|
|
// IsPhone @Title 是否手机号
|
|
func IsPhone(phone string) bool {
|
|
return regexp.MustCompile(`^1\d{10}$`).MatchString(phone)
|
|
}
|
|
|
|
// Equal @TITLE 数据比较
|
|
func Equal[T any](a, b T, fun func(a, b T) bool) bool {
|
|
return fun(a, b)
|
|
}
|
|
|
|
// Ptr @TITLE 返回指针
|
|
func Ptr[T any](data T) *T {
|
|
return &data
|
|
}
|
|
|
|
// Split @TITLE 字符串分隔
|
|
func Split(s, sep string) []string {
|
|
if s == "" {
|
|
return nil
|
|
}
|
|
return strings.Split(s, sep)
|
|
}
|
|
|
|
// PtrData @TITLE 指针数据
|
|
func PtrData[T any](data *T) T {
|
|
if data != nil {
|
|
return *data
|
|
}
|
|
return *new(T)
|
|
}
|
|
|
|
// PtrDecimal @TITLE Decimal比较数据
|
|
func PtrDecimal(a *decimal.Decimal, b *decimal.Decimal) bool {
|
|
if a == b {
|
|
return true
|
|
}
|
|
if a == nil || b == nil {
|
|
return false
|
|
}
|
|
return a.Cmp(*b) == 0
|
|
}
|
|
|
|
// PtrCmp @TITLE 客户比较数据引用比较
|
|
func PtrCmp[T comparable](a *T, b *T) bool {
|
|
if a == b {
|
|
return true
|
|
}
|
|
if a == nil || b == nil {
|
|
return false
|
|
}
|
|
return *a == *b
|
|
}
|
|
|
|
// DefaultData @TITLE 反射创建默认值
|
|
func DefaultData(data any) any {
|
|
var value reflect.Value
|
|
if reflect.TypeOf(data).Kind() != reflect.Ptr {
|
|
value = reflect.ValueOf(&data).Elem()
|
|
} else {
|
|
value = reflect.ValueOf(data).Elem()
|
|
}
|
|
if value.Kind() == reflect.Interface {
|
|
value = reflect.New(value.Elem().Type()).Elem()
|
|
}
|
|
|
|
labels := map[string]string{}
|
|
|
|
typeOf := value.Type()
|
|
for i := 0; i < typeOf.NumField(); i++ {
|
|
field := typeOf.Field(i)
|
|
name := field.Name
|
|
if field.IsExported() {
|
|
if !field.Anonymous {
|
|
labels[name] = field.Tag.Get("label")
|
|
} else {
|
|
name = ""
|
|
}
|
|
if field.Type.Kind() == reflect.Struct {
|
|
_, valueLabels := DefaultValue(value.Field(i), name)
|
|
for valueKey, valueLabel := range valueLabels {
|
|
labels[valueKey] = valueLabel
|
|
}
|
|
}
|
|
if field.Type.Kind() == reflect.Slice {
|
|
newValue := reflect.New(field.Type.Elem()).Elem()
|
|
defaultValue, valueLabels := DefaultValue(newValue, name)
|
|
for valueKey, valueLabel := range valueLabels {
|
|
labels[valueKey] = valueLabel
|
|
}
|
|
value.Field(i).Set(reflect.Append(value.Field(i), defaultValue))
|
|
}
|
|
}
|
|
}
|
|
return map[string]interface{}{
|
|
"Data": value.Interface(),
|
|
"Label": labels,
|
|
}
|
|
}
|
|
|
|
func DefaultValue(value reflect.Value, name string) (reflect.Value, map[string]string) {
|
|
typeOf := value.Type()
|
|
labels := map[string]string{}
|
|
if typeOf.Kind() == reflect.Struct {
|
|
for i := 0; i < typeOf.NumField(); i++ {
|
|
field := typeOf.Field(i)
|
|
fieldName := field.Name
|
|
if field.IsExported() {
|
|
if !field.Anonymous {
|
|
labels[strings.Trim(name+"."+fieldName, ".")] = field.Tag.Get("label")
|
|
} else {
|
|
fieldName = ""
|
|
}
|
|
labels[strings.Trim(name+"."+fieldName, ".")] = field.Tag.Get("label")
|
|
if field.Type.Kind() == reflect.Struct {
|
|
_, valueLabels := DefaultValue(value.Field(i), fieldName)
|
|
for valueKey, valueLabel := range valueLabels {
|
|
labels[strings.Trim(name+"."+valueKey, ".")] = valueLabel
|
|
}
|
|
}
|
|
if field.Type.Kind() == reflect.Slice {
|
|
newValue := reflect.New(field.Type.Elem()).Elem()
|
|
defaultValue, valueLabels := DefaultValue(newValue, fieldName)
|
|
for valueKey, valueLabel := range valueLabels {
|
|
labels[strings.Trim(name+"."+valueKey, ".")] = valueLabel
|
|
}
|
|
value.Field(i).Set(reflect.Append(value.Field(i), defaultValue))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return value, labels
|
|
}
|
|
|
|
func wrapIfStruct[T any](data T) T {
|
|
v := reflect.ValueOf(data)
|
|
if v.Kind() == reflect.Struct {
|
|
ptr := reflect.New(v.Type())
|
|
ptr.Elem().Set(v)
|
|
return ptr.Interface().(T)
|
|
}
|
|
return data
|
|
}
|
|
func DefaultSlice[T any](data T) T {
|
|
data = wrapIfStruct(data)
|
|
value := reflect.ValueOf(data).Elem()
|
|
typeOf := value.Type()
|
|
|
|
switch typeOf.Kind() {
|
|
case reflect.Struct:
|
|
DefaultSliceValue(value)
|
|
case reflect.Slice:
|
|
if value.IsNil() {
|
|
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
|
|
}
|
|
for j := 0; j < value.Len(); j++ {
|
|
DefaultSliceValue(value.Index(j))
|
|
}
|
|
}
|
|
|
|
if reflect.TypeOf(data).Kind() != reflect.Ptr {
|
|
return value.Interface().(T)
|
|
} else {
|
|
return value.Addr().Interface().(T)
|
|
}
|
|
}
|
|
|
|
func DefaultSliceValue(value reflect.Value) reflect.Value {
|
|
typeOf := value.Type()
|
|
if typeOf.Kind() == reflect.Struct {
|
|
for i := 0; i < typeOf.NumField(); i++ {
|
|
DefaultSliceType(value.Field(i))
|
|
}
|
|
}
|
|
return value
|
|
}
|
|
func DefaultSliceType(value reflect.Value) reflect.Value {
|
|
switch value.Type().Kind() {
|
|
case reflect.Ptr:
|
|
if !value.IsNil() {
|
|
DefaultSliceType(value.Elem())
|
|
} else {
|
|
valueType := value.Type().Elem()
|
|
if valueType.Kind() == reflect.Slice {
|
|
slice := reflect.MakeSlice(valueType, 0, 0)
|
|
ptr := reflect.New(valueType)
|
|
ptr.Elem().Set(slice)
|
|
value.Set(ptr)
|
|
}
|
|
}
|
|
case reflect.Struct:
|
|
DefaultSliceValue(value)
|
|
case reflect.Slice:
|
|
if value.IsNil() {
|
|
if value.CanSet() {
|
|
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
|
|
}
|
|
}
|
|
for j := 0; j < value.Len(); j++ {
|
|
DefaultSliceValue(value.Index(j))
|
|
}
|
|
}
|
|
return value
|
|
}
|
|
|
|
// Unique @Title 去重
|
|
func Unique[T comparable](array []T) (result []T) {
|
|
for _, item := range array {
|
|
if !InArray(item, result) {
|
|
result = append(result, item)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// InsertSorted @TITLE array插入排序
|
|
func InsertSorted[T any](array []T, value T, comp func(int) bool) []T {
|
|
i, j := 0, len(array)
|
|
for i < j {
|
|
h := int(uint(i+j) >> 1) // avoid overflow when computing h
|
|
// i ≤ h < j
|
|
if !comp(h) {
|
|
i = h + 1 // preserves f(i-1) == false
|
|
} else {
|
|
j = h // preserves f(j) == true
|
|
}
|
|
}
|
|
// 插入:保持有序
|
|
array = append(array, value) // 增加一个空位
|
|
copy(array[i+1:], array[i:]) // 后移
|
|
array[i] = value // 插入值
|
|
return array
|
|
}
|
|
|
|
// GetGender @TITLE 获取性别
|
|
func GetGender(sex string) string {
|
|
if InArray(sex, []string{"男", "M"}) {
|
|
return "SEX01_SYS"
|
|
} else if InArray(sex, []string{"女", "F"}) {
|
|
return "SEX02_SYS"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func IntArrayToString(args []int64) string {
|
|
var result []string
|
|
for _, item := range args {
|
|
result = append(result, strconv.FormatInt(item, 10))
|
|
}
|
|
return strings.Join(result, ",")
|
|
}
|