HaiLin Huang před 2 měsíci
revize
f6c3d63394

binární
.DS_Store


+ 96 - 0
algor/main.go

@@ -0,0 +1,96 @@
+package algor
+
+import (
+	"fmt"
+
+	"github.com/guonaihong/gout"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/utils"
+)
+
+var s *setting
+
+type setting struct {
+	Domain    string
+	AppKey    string
+	AppSecret string
+	Debug     bool
+}
+
+func InitClient(domain, appKey, appSecret string, debug bool) {
+	s = &setting{
+		Domain:    domain,
+		AppKey:    appKey,
+		AppSecret: appSecret,
+		Debug:     debug,
+	}
+}
+
+// 获取授权列表
+func ListAuthorizes() (*sdk.BaseResponse[sdk.ListResponse[sdk.AlgorAppAuth]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[sdk.AlgorAppAuth]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.ListResponse[sdk.AlgorAppAuth]]]("/openapi/authorize/list", gout.H{})
+	if err != nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取问卷信息
+func DetailSurvey(decisionModelSn string) (*sdk.BaseResponse[sdk.DetailResponse[any]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.DetailResponse[any]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.DetailResponse[any]]]("/openapi/survey/detail", gout.H{
+		"decisionModelSn": decisionModelSn,
+	})
+	if err != nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 执行决策模型
+func Run(request sdk.ExecuteRequest) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/openapi/run", utils.StructToGoutH(request))
+	if err != nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+func postReq[T any](path string, data gout.H) (T, error) {
+	url := fmt.Sprintf("%s%s", s.Domain, path)
+	fmt.Println("请求地址 ===>", url)
+	var res T
+	err := gout.POST(url).Debug(s.Debug).
+		SetHeader(gout.H{
+			"token":  fmt.Sprintf("%s:%s", s.AppKey, utils.Md5(s.AppSecret)),
+			"appkey": s.AppKey,
+		}).
+		SetJSON(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		return res, err
+	}
+	return res, nil
+}

+ 23 - 0
algor/main_test.go

@@ -0,0 +1,23 @@
+package algor_test
+
+import (
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/algor"
+)
+
+func init() {
+}
+
+func TestGetAuthorizeList(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		algor.InitClient("https://api.mdfitnesscao.com", "k7bDcSj9KanD8TB4", "96fcO7IxM1pKYjGgl0D4pbxRr98PeShU", true)
+
+		response, err := algor.ListAuthorizes()
+		list := response.Data.List
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("list len: %d", len(list))
+	})
+}

+ 513 - 0
archives/main.go

@@ -0,0 +1,513 @@
+package archives
+
+import (
+	"fmt"
+
+	"github.com/guonaihong/gout"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/utils"
+)
+
+// 获取档案详细资料
+func Detail(id string, mechanismId string, staffId string) (*sdk.BaseResponse[sdk.DetailResponse[*sdk.Archives]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.DetailResponse[*sdk.Archives]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.DetailResponse[*sdk.Archives]]]("/archivesService/openapi/archives/detail", gout.H{
+		"archivesId":  id,
+		"mechanismId": mechanismId,
+		"staffId":     staffId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 触发档案的报告分析
+func TriggerArchivesMedicalReport(id string) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/archivesService/openapi/archives/medicalReportTrigger", gout.H{
+		"archivesId": id,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取档案的指定数据
+func GetArchivesValues(archivesId string, valueIds []string) (*sdk.BaseResponse[*sdk.ListResponse[*sdk.ArchivesValues]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[*sdk.ListResponse[*sdk.ArchivesValues]]
+	// 将结构体转换为map
+	resp, err := postReq[*sdk.BaseResponse[*sdk.ListResponse[*sdk.ArchivesValues]]]("/archivesService/openapi/archives/values/query", gout.H{
+		"archivesId": archivesId,
+		"ids":        valueIds,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取档案的指定数据
+func GetArchivesValuesByArchivesIds(archivesIds []string, valueIds []string) (*sdk.BaseResponse[*sdk.ListResponse[*sdk.ArchivesValues]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[*sdk.ListResponse[*sdk.ArchivesValues]]
+	// 将结构体转换为map
+	resp, err := postReq[*sdk.BaseResponse[*sdk.ListResponse[*sdk.ArchivesValues]]]("/archivesService/openapi/archives/values/query/multi", gout.H{
+		"archivesIds": archivesIds,
+		"ids":         valueIds,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取档案的指定数据
+func UpdateArchivesValues(archivesId string, answers []*sdk.ArchivesValues) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	// 将结构体转换为map
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/archivesService/openapi/archives/values/update", gout.H{
+		"archivesId": archivesId,
+		"answers":    answers,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 创建档案
+func Create(archivesForm *sdk.Archives) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	// 将结构体转换为map
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/archivesService/openapi/archives/create", utils.StructToGoutH(archivesForm))
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 创建档案
+func CreateOrFindByAccount(archivesForm *sdk.Archives, attachForm *sdk.ArchivesAttachForm, account *sdk.Account) (*sdk.BaseResponse[map[string]string], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]string]
+	// 将结构体转换为map
+	resp, err := postReq[*sdk.BaseResponse[map[string]string]]("/archivesService/openapi/archives/createOrFindByAccount", gout.H{
+		"archivesForm": utils.StructToGoutH(archivesForm),
+		"attachForm":   utils.StructToGoutH(attachForm),
+		"account":      utils.StructToGoutH(account),
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 通过档案编号列表获取档案列表
+func ListArchivesById(ids []string, mechanismId string, staffId string, isDensenstize int64) (*sdk.BaseResponse[sdk.ListResponse[*sdk.Archives]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[*sdk.Archives]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.ListResponse[*sdk.Archives]]]("/archivesService/openapi/archives/listById", gout.H{
+		"archivesIds":   ids,
+		"mechanismId":   mechanismId,
+		"staffId":       staffId,
+		"isDensenstize": isDensenstize,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 通过档案编号列表获取档案列表
+func ListArchivesIds(queryData *sdk.ArchivesPaginateQuery, mechanismId string, staffId string) (*sdk.BaseResponse[sdk.ListResponse[string]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[string]]
+	var queryStruct = utils.StructToGoutH(queryData)
+	queryStruct["mechanismId"] = mechanismId
+	queryStruct["staffId"] = staffId
+	resp, err := postReq[*sdk.BaseResponse[sdk.ListResponse[string]]]("/archivesService/openapi/archives/list/id", queryStruct)
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 通过档案编号列表获取档案列表
+func PaginateArchives(queryData *sdk.ArchivesPaginateQuery, mechanismId string, staffId string) (*sdk.BaseResponse[sdk.PaginateTotalSumResponse[*sdk.Archives]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.PaginateTotalSumResponse[*sdk.Archives]]
+	var queryStruct = utils.StructToGoutH(queryData)
+	queryStruct["mechanismId"] = mechanismId
+	queryStruct["staffId"] = staffId
+	resp, err := postReq[*sdk.BaseResponse[sdk.PaginateTotalSumResponse[*sdk.Archives]]]("/archivesService/openapi/archives/paginate", queryStruct)
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取某个日期有更新的档案列表
+func ListUpdatedArchivesByDate(date string) (*sdk.BaseResponse[sdk.ListResponse[*sdk.Archives]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[*sdk.Archives]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.ListResponse[*sdk.Archives]]]("/archivesService/openapi/archives/updatedListByDate", gout.H{
+		"date": date,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取某个日期有更新的档案列表
+func ListUpdatedArchivesDataByDate(date string, archivesId string) (*sdk.BaseResponse[sdk.ListResponse[*sdk.ArchivesValues]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[*sdk.ArchivesValues]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.ListResponse[*sdk.ArchivesValues]]]("/archivesService/openapi/archives/data/updatedListByDate", gout.H{
+		"date":       date,
+		"archivesId": archivesId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 检查档案是否属于同一个家庭
+func CheckIsArchivesFamily(archivesIds []string) (*sdk.BaseResponse[map[string]bool], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]bool]
+	resp, err := postReq[*sdk.BaseResponse[map[string]bool]]("/archivesService/openapi/archives/checkFamily", gout.H{
+		"archivesIds": archivesIds,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 检查档案是否属于同一个家庭
+func GetValidArchivesIdsForMechanism(archivesIds []string, mechanismId string) (*sdk.BaseResponse[sdk.ListResponse[string]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[string]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.ListResponse[string]]]("/archivesService/openapi/archives/getValidArchivesIdsForMechanism", gout.H{
+		"archivesIds": archivesIds,
+		"mechanismId": mechanismId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 检查档案是否属于同一个家庭
+func ListChannelByIds(channelIds []int64, mechanismId string) (*sdk.BaseResponse[sdk.ListResponse[*sdk.Channel]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[*sdk.Channel]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.ListResponse[*sdk.Channel]]]("/archivesService/openapi/channel/listByIds", gout.H{
+		"ids":         channelIds,
+		"mechanismId": mechanismId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 检查档案是否属于同一个家庭
+func GetAgencyInfoByAppKey(appKey string) (*sdk.BaseResponse[sdk.DetailResponse[*sdk.AgencyDeveloperSettingForm]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.DetailResponse[*sdk.AgencyDeveloperSettingForm]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.DetailResponse[*sdk.AgencyDeveloperSettingForm]]]("/archivesService/openapi/agency/developerInfo", gout.H{
+		"appKey": appKey,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 检查档案是否属于同一个家庭
+func GetAgencyInfoByAgencyId(agencyId int64) (*sdk.BaseResponse[sdk.DetailResponse[*sdk.AgencyDeveloperSettingForm]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.DetailResponse[*sdk.AgencyDeveloperSettingForm]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.DetailResponse[*sdk.AgencyDeveloperSettingForm]]]("/archivesService/openapi/agency/developerInfoById", gout.H{
+		"agencyId": agencyId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 将多个档案加入某个机构下的渠道部门中
+func PushArchivesToDepartment(archivesIds []string, departmentId int64, mechanismId string) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/archivesService/openapi/department/pushArchives", gout.H{
+		"archivesIds":  archivesIds,
+		"departmentId": departmentId,
+		"mechanismId":  mechanismId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 将多个档案加入某个机构下的渠道部门中
+func SendSubscribeMessage(mechanismId string, archivesId string, templateId string, data map[string]any, page string, state string) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/archivesService/openapi/subscribeMessage/send", gout.H{
+		"mechanismId": mechanismId,
+		"archivesId":  archivesId,
+		"templateId":  templateId,
+		"data":        data,
+		"page":        page,
+		"state":       state,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// postReq 发送post请求
+func postReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.POST(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetJSON(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}

+ 231 - 0
archives/main_test.go

@@ -0,0 +1,231 @@
+package archives_test
+
+import (
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/archives"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/utils"
+)
+
+func TestList(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := archives.Detail("B8JB6J0d", "", "")
+		list := response.Data.Detail
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("list: %v", list)
+	})
+}
+
+func TestGetArchivesDataListByDate(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := archives.ListUpdatedArchivesDataByDate("2023-09-15", "aaaaa")
+		list := response.Data.List
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("list: %v", utils.JsonEncode(list))
+	})
+}
+
+func TestGetArchivesListByDate(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := archives.ListUpdatedArchivesByDate("2023-09-15")
+		list := response.Data.List
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("lista :%v", list)
+	})
+}
+
+func TestCheckIsArchivesFamily(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, _ := archives.CheckIsArchivesFamily([]string{
+			"pWJM3jrG",
+			"Ydm62mB8",
+		})
+		isFamily := response.Data["isFamily"]
+		t.Logf("lista :%v", isFamily)
+	})
+}
+
+func TestGetArchivesListByIds(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := archives.ListArchivesById([]string{
+			"Ydm660mB", "8VjdwPm4", "123",
+		}, "", "", 0)
+		list := response.Data.List
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("lista :%v", list)
+	})
+}
+
+func TestCreateArchives(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := archives.Create(&sdk.Archives{
+			Name:     "哈哈哈哈",
+			Gender:   1,
+			Birthday: "2023-09-15",
+			Accounts: []*sdk.Account{
+				{
+					Account: "18523523535",
+					Type:    1,
+				},
+			},
+		})
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("response :%v", response)
+	})
+}
+
+func TestCreateArchivesOrFindByAccount(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := archives.CreateOrFindByAccount(&sdk.Archives{
+			Name:     "哈哈哈哈12",
+			Gender:   1,
+			Birthday: "2023-09-15",
+			Accounts: []*sdk.Account{
+				{
+					Account: "zhangsan_hhhh",
+					Type:    3,
+				},
+			},
+		}, &sdk.ArchivesAttachForm{
+			ChannelId: 3,
+		}, &sdk.Account{
+			Account: "zhangsan_hhhh",
+			Type:    3,
+		})
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("response :%v", response)
+	})
+}
+
+func TestTriggerArchivesMedicalReport(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := archives.TriggerArchivesMedicalReport("WNm0dm07")
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("response :%v", response)
+	})
+}
+
+func TestGetArchivesValues(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := archives.GetArchivesValues("yojkwRjZ", []string{"medicationStatus"})
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("response :%v", response)
+	})
+}
+
+func TestPaginateArchives(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := archives.PaginateArchives(&sdk.ArchivesPaginateQuery{
+			Page:              1,
+			PageSize:          100,
+			RegistMechanismId: "Xwlg97rP",
+			AgeEnd:            200,
+		}, "", "")
+		list := response.Data.List
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("list :%v", list)
+	})
+}
+
+func TestListArchivesIds(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := archives.ListArchivesIds(nil, "Xwlg97rP", "yEw98oR0")
+		list := response.Data.List
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("list :%v", list)
+	})
+}
+
+func TestGetValidArchivesIdsForMechanism(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, _ := archives.GetValidArchivesIdsForMechanism([]string{
+			"pWJM3jrG",
+			"Ydm62mB8",
+		}, "M57wVRNZ")
+		isFamily := response.Data.List
+		t.Logf("lista :%v", isFamily)
+	})
+}
+
+func TestListChannelByIds(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, _ := archives.ListChannelByIds([]int64{
+			3,
+		}, "")
+		isFamily := response.Data.List
+		t.Logf("list :%v", isFamily)
+	})
+}

+ 109 - 0
common/common.go

@@ -0,0 +1,109 @@
+package common
+
+import (
+	"fmt"
+
+	"github.com/guonaihong/gout"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+)
+
+type ConfigResponse struct {
+	Config map[string]any `json:"config"`
+}
+
+// 获取OSS的配置信息
+func GetOssConfig() (*sdk.BaseResponse[ConfigResponse], *response.ErrCode) {
+	var resp *sdk.BaseResponse[ConfigResponse]
+	resp, err := getReq[*sdk.BaseResponse[ConfigResponse]]("/commonService/openapi/oss/config", gout.H{})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+type RegionResponse struct {
+	Province *sdk.Province `json:"province"`
+	City     *sdk.City     `json:"city"`
+	County   *sdk.County   `json:"county"`
+	Street   *sdk.Street   `json:"street"`
+	Villages *sdk.Villages `json:"villages"`
+}
+
+// 通过省市区编码获取省市区详细信息
+func GetRegionByCode(provinceId string, cityId string, countyId string, streetId string, villagesId string) (*sdk.BaseResponse[RegionResponse], *response.ErrCode) {
+	var resp *sdk.BaseResponse[RegionResponse]
+	resp, err := getReq[*sdk.BaseResponse[RegionResponse]]("/commonService/openapi/region/get", gout.H{
+		"provinceCode": provinceId,
+		"cityCode":     cityId,
+		"countyCode":   countyId,
+		"streetCode":   streetId,
+		"villagesCode": villagesId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// postReq 发送post请求
+func postReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.POST(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetJSON(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}
+
+// postReq 发送post请求
+func getReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.GET(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetQuery(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}

+ 40 - 0
common/common_test.go

@@ -0,0 +1,40 @@
+package common_test
+
+import (
+	"encoding/json"
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/common"
+)
+
+func TestGetConfig(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  false,
+		})
+		response, err := common.GetOssConfig()
+		if err != nil {
+			t.Errorf("err %v", err)
+		}
+		detail := response.Data.Config
+		t.Logf("%v", detail)
+	})
+}
+
+func TestGetRegion(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  false,
+		})
+		response, err := common.GetRegionByCode("500000000000", "", "", "", "")
+		if err != nil {
+			t.Errorf("err %v", err)
+		}
+		detail := response.Data
+		detailStr, _ := json.Marshal(detail)
+		t.Logf("%v", string(detailStr))
+	})
+}

+ 167 - 0
constants/algor_permission.go

@@ -0,0 +1,167 @@
+package constants
+
+const (
+	// 决策模型
+	AlgorUserPermissionDecisionModelView   = "algor:decisionModel:view"
+	AlgorUserPermissionDecisionModelEdit   = "algor:decisionModel:edit"
+	AlgorUserPermissionDecisionModelDelete = "algor:decisionModel:delete"
+
+	// 应用
+	AlgorUserPermissionAppView        = "algor:app:view"
+	AlgorUserPermissionAppEdit        = "algor:app:edit"
+	AlgorUserPermissionAppResetSecret = "algor:app:resetSecret"
+	AlgorUserPermissionAppDelete      = "algor:app:delete"
+
+	// 系统标签
+	AlgorUserPermissionSystemTagView   = "algor:systemTag:view"
+	AlgorUserPermissionSystemTagEdit   = "algor:systemTag:edit"
+	AlgorUserPermissionSystemTagDelete = "algor:systemTag:delete"
+
+	// 问题模板
+	AlgorUserPermissionQuestionnaireTemplateView   = "algor:questionnaireTemplate:view"
+	AlgorUserPermissionQuestionnaireTemplateEdit   = "algor:questionnaireTemplate:edit"
+	AlgorUserPermissionQuestionnaireTemplateDelete = "algor:questionnaireTemplate:delete"
+
+	// 问题库
+	AlgorUserPermissionQuestionnaireSubjectView   = "algor:questionnaireSubject:view"
+	AlgorUserPermissionQuestionnaireSubjectEdit   = "algor:questionnaireSubject:edit"
+	AlgorUserPermissionQuestionnaireSubjectDelete = "algor:questionnaireSubject:delete"
+
+	// 问卷
+	AlgorUserPermissionSurveyView   = "algor:survey:view"
+	AlgorUserPermissionSurveyEdit   = "algor:survey:edit"
+	AlgorUserPermissionSurveyDelete = "algor:survey:delete"
+
+	// 数据处理
+	AlgorUserPermissionDataView            = "algor:data:view"             // 数据查看
+	AlgorUserPermissionDataProcess         = "algor:data:process"          // 数据处理
+	AlgorUserPermissionDataEdit            = "algor:data:edit"             // 数据编辑
+	AlgorUserPermissionDataChangeProcesser = "algor:data:change-processer" // 更改数据处理者
+	AlgorUserPermissionDataTableHeaderSet  = "algor:data:table-header-set" // 表头设置
+	AlgorUserPermissionDataTemplateSet     = "algor:data:template-set"     // 模板设置
+
+	// 知识图谱
+	AlgorUserPermissionKnowledgeGraphEdit     = "algor:knowledgeGraph:edit"     // 知识图谱编辑
+	AlgorUserPermissionKnowledgeGraphNodeEdit = "algor:knowledgeGraphNode:edit" // 图谱节点编辑
+
+	// 知识库
+	AlgorUserPermissionArticleView   = "algor:article:view"   // 知识库查看
+	AlgorUserPermissionArticleEdit   = "algor:article:edit"   // 知识库编辑
+	AlgorUserPermissionArticleDelete = "algor:article:delete" // 知识库删除
+	// 知识库图片管理
+	AlgorUserPermissionArticlePictureView   = "algor:articlePicture:view"   // 知识库图片查看
+	AlgorUserPermissionArticlePictureEdit   = "algor:articlePicture:edit"   // 知识库图片编辑
+	AlgorUserPermissionArticlePictureDelete = "algor:articlePicture:delete" // 知识库图片删除
+
+	// 表单管理
+	AlgorUserPermissionFormView = "algor:form:view" // 表单查看
+	AlgorUserPermissionFormEdit = "algor:form:edit" // 表单编辑
+)
+
+var AlgorUserPermissionNames = map[string]*Permission{
+	AlgorUserPermissionDecisionModelView: {
+		Name: "决策模型查看",
+	},
+	AlgorUserPermissionDecisionModelEdit: {
+		Name: "决策模型编辑",
+	},
+	AlgorUserPermissionDecisionModelDelete: {
+		Name: "决策模型删除",
+	},
+	AlgorUserPermissionAppView: {
+		Name: "应用查看",
+	},
+	AlgorUserPermissionAppEdit: {
+		Name: "应用编辑",
+	},
+	AlgorUserPermissionAppResetSecret: {
+		Name: "应用重置密钥",
+	},
+	AlgorUserPermissionAppDelete: {
+		Name: "应用删除",
+	},
+	AlgorUserPermissionSystemTagView: {
+		Name: "系统标签查看",
+	},
+	AlgorUserPermissionSystemTagEdit: {
+		Name: "系统标签编辑",
+	},
+	AlgorUserPermissionSystemTagDelete: {
+		Name: "系统标签删除",
+	},
+	AlgorUserPermissionQuestionnaireTemplateView: {
+		Name: "问题模板查看",
+	},
+	AlgorUserPermissionQuestionnaireTemplateEdit: {
+		Name: "问题模板编辑",
+	},
+	AlgorUserPermissionQuestionnaireTemplateDelete: {
+		Name: "问题模板删除",
+	},
+	AlgorUserPermissionQuestionnaireSubjectView: {
+		Name: "问题库查看",
+	},
+	AlgorUserPermissionQuestionnaireSubjectEdit: {
+		Name: "问题库编辑",
+	},
+	AlgorUserPermissionQuestionnaireSubjectDelete: {
+		Name: "问题库删除",
+	},
+	AlgorUserPermissionSurveyView: {
+		Name: "问卷查看",
+	},
+	AlgorUserPermissionSurveyEdit: {
+		Name: "问卷编辑",
+	},
+	AlgorUserPermissionSurveyDelete: {
+		Name: "问卷删除",
+	},
+	AlgorUserPermissionDataView: {
+		Name: "数据查看",
+	},
+	AlgorUserPermissionDataProcess: {
+		Name: "数据处理",
+	},
+	AlgorUserPermissionDataEdit: {
+		Name: "数据编辑",
+	},
+	AlgorUserPermissionDataChangeProcesser: {
+		Name: "更改数据处理者",
+	},
+	AlgorUserPermissionDataTableHeaderSet: {
+		Name: "表头设置",
+	},
+	AlgorUserPermissionDataTemplateSet: {
+		Name: "模板设置",
+	},
+	AlgorUserPermissionKnowledgeGraphEdit: {
+		Name: "图谱设置",
+	},
+	AlgorUserPermissionKnowledgeGraphNodeEdit: {
+		Name: "知识图谱",
+	},
+	AlgorUserPermissionArticleView: {
+		Name: "知识库内容查看",
+	},
+	AlgorUserPermissionArticleEdit: {
+		Name: "知识库内容编辑",
+	},
+	AlgorUserPermissionArticleDelete: {
+		Name: "知识库内容删除",
+	},
+	AlgorUserPermissionArticlePictureView: {
+		Name: "知识库图片查看",
+	},
+	AlgorUserPermissionArticlePictureEdit: {
+		Name: "知识库图片编辑",
+	},
+	AlgorUserPermissionArticlePictureDelete: {
+		Name: "知识库图片删除",
+	},
+	AlgorUserPermissionFormView: {
+		Name: "表单查看",
+	},
+	AlgorUserPermissionFormEdit: {
+		Name: "表单编辑",
+	},
+}

+ 32 - 0
constants/common_permission.go

@@ -0,0 +1,32 @@
+package constants
+
+const (
+	PermissionUserView   = "user:view"
+	PermissionUserEdit   = "user:edit"
+	PermissionUserDelete = "user:delete"
+
+	PermissionRoleView   = "role:view"
+	PermissionRoleEdit   = "role:edit"
+	PermissionRoleDelete = "role:delete"
+)
+
+var CommonPermissionNames = map[string]*Permission{
+	PermissionUserView: {
+		Name: "用户查看",
+	},
+	PermissionUserEdit: {
+		Name: "用户编辑",
+	},
+	PermissionUserDelete: {
+		Name: "用户删除",
+	},
+	PermissionRoleView: {
+		Name: "角色查看",
+	},
+	PermissionRoleEdit: {
+		Name: "角色编辑",
+	},
+	PermissionRoleDelete: {
+		Name: "角色删除",
+	},
+}

+ 451 - 0
constants/mechanism_permission.go

@@ -0,0 +1,451 @@
+package constants
+
+const (
+	MechanismStaffPermissionUserView                     = "user:view"                     // 员工查看
+	MechanismStaffPermissionUserEdit                     = "user:edit"                     // 员工编辑
+	MechanismStaffPermissionUserDelete                   = "user:delete"                   // 员工删除
+	MechanismStaffPermissionRoleView                     = "role:view"                     // 角色查看
+	MechanismStaffPermissionRoleEdit                     = "role:edit"                     // 角色编辑
+	MechanismStaffPermissionRoleDelete                   = "role:delete"                   // 角色删除
+	MechanismStaffPermissionArchivesView                 = "archives:view"                 // 查看档案
+	MechanismStaffPermissionArchivesEdit                 = "archives:edit"                 // 编辑档案
+	MechanismStaffPermissionArchivesCreate               = "archives:create"               // 创建档案
+	MechanismStaffPermissionArchivesRunAlgor             = "archives:runAlgor"             // 档案综合分析
+	MechanismStaffPermissionArchivesExport               = "archives:export"               // 档案导出
+	MechanismStaffPermissionArchivesManagePlan           = "archives:managePlan"           // 管理方案
+	MechanismStaffPermissionArchivesManagePlanHealth     = "archives:managePlanHealth"     // 管理方案(功能医学)
+	MechanismStaffPermissionArchivesMechanismConfigView  = "archives:mechanismConfig:view" // 获取档案配置信息
+	MechanismStaffPermissionArchivesMechanismConfigEdit  = "archives:mechanismConfig:edit" // 编辑档案配置
+	MechanismStaffPermissionDataView                     = "data:view"                     // 查看数据
+	MechanismStaffPermissionDataEdit                     = "data:edit"                     // 编辑数据
+	MechanismStaffPermissionDataUpload                   = "data:upload"                   // 上传数据
+	MechanismStaffPermissionDataUploadVisitRecord        = "data:upload:visitRecord"       // 上传数据(巡访)
+	MechanismStaffPermissionDataUploadDemand             = "data:upload:demand"            // 上传数据(生活需求)
+	MechanismStaffPermissionDataUploadDailyMonitor       = "data:upload:dailyMonitor"      // 上传数据(日常监测数据)
+	MechanismStaffPermissionDataUploadDiseaseVisit       = "data:upload:diseaseVisit"      // 上传数据(疾病回访数据)
+	MechanismStaffPermissionDataUploadInspectData        = "data:upload:inspectData"       // 上传数据(检查数据)
+	MechanismStaffPermissionDataUploadMedicalReport      = "data:upload:medicalReport"     // 上传数据(体检报告)
+	MechanismStaffPermissionDataExportVisitRecord        = "data:export:visitRecord"       // 导出数据(巡访)
+	MechanismStaffPermissionDataDashboard                = "data:dashboard"                // 数据看板
+	MechanismStaffPermissionSurveyView                   = "survey:view"                   // 查看问卷
+	MechanismStaffPermissionSurveyEdit                   = "survey:edit"                   // 编辑问卷
+	MechanismStaffPermissionSurveyResultView             = "surveyResult:view"             // 查看问卷结果
+	MechanismStaffPermissionSurveyResultEdit             = "surveyResult:edit"             // 编辑问卷结果基础信息
+	MechanismStaffPermissionSurveyResultDelete           = "surveyResult:delete"           // 删除问卷结果
+	MechanismStaffPermissionSurveyResultUpdateData       = "surveyResult:updateData"       // 添加问卷结果
+	MechanismStaffPermissionArticleView                  = "article:view"                  // 知识库(文章)查看
+	MechanismStaffPermissionArchivesTagCalcTaskView      = "archivesTagCalcTask:view"      // 查看档案标签计算任务
+	MechanismStaffPermissionArchivesTagCalcTaskEdit      = "archivesTagCalcTask:edit"      // 编辑档案标签计算任务
+	MechanismStaffPermissionMall                         = "mall"                          // 商城-商品管理
+	MechanismStaffPermissionMallSwiper                   = "mall:swiper"                   // 商城-轮播图管理
+	MechanismStaffPermissionMallRecommend                = "mall:recommend"                // 商城-推荐管理
+	MechanismStaffPermissionMallStore                    = "mall:store"                    // 商城-店铺管理
+	MechanismStaffPermissionMallOrder                    = "mall:order"                    // 商城-订单管理
+	MechanismStaffPermissionMallCategory                 = "mall:category"                 // 商城-分类管理
+	MechanismStaffPermissionMallRemark                   = "mall:remark"                   // 商城-下单须知
+	MechanismStaffPermissionMallFeedback                 = "mall:feedback"                 // 商城-申诉
+	MechanismStaffPermissionDepartmentView               = "department:view"               // 查看部门
+	MechanismStaffPermissionDepartmentEdit               = "department:edit"               // 编辑部门
+	MechanismStaffPermissionDepartmentDelete             = "department:delete"             // 删除部门
+	MechanismStaffPermissionChannelMedicalReportView     = "channelMedicalReport:view"     // 查看渠道医疗报告
+	MechanismStaffPermissionChannelMedicalReportEdit     = "channelMedicalReport:edit"     // 编辑渠道医疗报告
+	MechanismStaffPermissionChannelMedicalReportDelete   = "channelMedicalReport:delete"   // 删除渠道医疗报告
+	MechanismStaffPermissionChannelMedicalReportAnalysis = "channelMedicalReport:analysis" // 分析渠道医疗报告
+
+	MechanismStaffPermissionMedicalCareDemandView   = "medicalCare:demand:view"   // 医养:居民需求查看
+	MechanismStaffPermissionMedicalCareCategoryView = "medicalCare:category:view" // 医养:类别管理
+
+	MechanismStaffPermissionDataPrivacyArchivesInfo = "dataPrivacy:archivesInfo" // 查看档案信息中隐私数据
+
+	MechanismStaffMedicalDataGroup    = "medicalDataGroup"    // 医养数据集
+	MechanismStaffMedicalDataTemplate = "medicalDataTemplate" // 数据模板
+
+	MechanismStaffMerchantManage                               = "merchantManage"                     // 商户管理
+	MechanismStaffPermissionArchivesReportManage               = "archivesReportManage"               // 档案报告管理
+	MechanismStaffPermissionArchivesReportSuggestionManage     = "archivesReportSuggestionManage"     // 档案报告建议管理
+	MechanismStaffPermissionArchivesReportWarningMessageManage = "archivesReportWarningMessageManage" // 档案报告特别提醒管理
+	MechanismStaffPermissionArchivesReportPdfResult            = "archivesReportPdfResult"            // PDF报告
+
+	MechanismStaffPermissionCustomSurveyManage       = "customSurveyManage"       // 自定义问卷管理
+	MechanismStaffPermissionCustomSurveyResultManage = "customSurveyResultManage" // 自定义问卷结果管理
+
+	MechanismStaffPermissionHealthManage = "healthManage" // 健康管理
+	// 待办事项
+	MechanismStaffPermissionHealthManageTodoListView = "headlthManage:todoList:view" // 查看/处理待办事项
+	MechanismStaffPermissionHealthManageTodoListEdit = "headlthManage:todoList:edit" // 管理/新增待办事项
+	MechanismStaffPermissionHealthManageTodoListSms  = "headlthManage:todoList:sms"  // 待办事项短信管理
+	MechanismStaffPermissionHealthManageUserTag      = "healthManage:userTag"        // 用户标签管理
+
+	// 方案库
+	MechanismStaffPermissionHealthManageSuggestionView     = "healthManage:suggestion:view"     // 健康建议库查看
+	MechanismStaffPermissionHealthManageSuggestionEdit     = "healthManage:suggestion:edit"     // 健康建议库管理
+	MechanismStaffPermissionHealthManageTagView            = "healthManage:tag:view"            // 标签库查看
+	MechanismStaffPermissionHealthManageTagEdit            = "healthManage:tag:edit"            // 标签库管理
+	MechanismStaffPermissionHealthManageGroupView          = "healthManage:group:view"          // 管理分组库查看
+	MechanismStaffPermissionHealthManageGroupEdit          = "healthManage:group:edit"          // 管理分组库管理
+	MechanismStaffPermissionHealthManageVisitTemplateView  = "healthManage:visitTemplate:view"  // 回访模板库查看
+	MechanismStaffPermissionHealthManageVisitTemplateEdit  = "healthManage:visitTemplate:edit"  // 回访模板库管理
+	MechanismStaffPermissionHealthManageInspectProjectView = "healthManage:inspectProject:view" // 检查项目库查看
+	MechanismStaffPermissionHealthManageInspectProjectEdit = "healthManage:inspectProject:edit" // 检查项目库管理
+
+	MechanismStaffPermissionMembershipCardSet              = "membershipCard:set"              // 会员卡设置
+	MechanismStaffPermissionMembershipCardBindRecord       = "membershipCard:bindRecord"       // 会员卡绑定记录
+	MechanismStaffPermissionMembershipCardConsumeRecord    = "membershipCard:consumeRecord"    // 会员卡消费记录
+	MechanismStaffPermissionMembershipCardMemberSet        = "membershipCard:memberSet"        // 会员设置
+	MechanismStaffPermissionMembershipCardServiceSet       = "membershipCard:serviceSet"       // 服务设置
+	MechanismStaffPermissionMembershipCardMemberServiceSet = "membershipCard:memberServiceSet" // 服务记录设置
+	MechanismStaffPermissionMembershipCardCode             = "membershipCard:code"             // 会员卡激活码
+
+	MechanismStaffPermissionAgency       = "agency"        // 代理商管理
+	MechanismStaffPermissionAgencyView   = "agency:view"   // 代理商-查看
+	MechanismStaffPermissionAgencyEdit   = "agency:edit"   // 代理商-编辑
+	MechanismStaffPermissionAgencyDelete = "agency:delete" // 代理商-删除
+
+	MechanismStaffPermissionAgencySettingView          = "agency:setting:view"          // 代理商配置查看
+	MechanismStaffPermissionAgencySettingEdit          = "agency:setting:edit"          // 代理商配置修改
+	MechanismStaffPermissionAgencyDeveloperSettingView = "agency:developerSetting:view" // 代理商开发者设置查看
+	MechanismStaffPermissionAgencyDeveloperSettingEdit = "agency:developerSetting:edit" // 代理商开发者设置编辑
+	MechanismStaffPermissionAgencyPromotionGoodsView   = "agency:promotionGoods:view"   // 代理商-推广商品查看
+	MechanismStaffPermissionAgencyPromotionGoodsEdit   = "agency:promotionGoods:edit"   // 代理商-推广商品编辑
+	MechanismStaffPermissionAgencyPromotionGoodsDelete = "agency:promotionGoods:delete" // 代理商-推广商品删除
+
+	MechanismStaffPermissionAgencyPaymentSettingView   = "agency:paymentSetting:view"   // 代理商-支付设置查看
+	MechanismStaffPermissionAgencyPaymentSettingEdit   = "agency:paymentSetting:edit"   // 代理商-支付设置编辑
+	MechanismStaffPermissionAgencyPaymentSettingDelete = "agency:paymentSetting:delete" // 代理商-支付设置删除
+
+	MechanismStaffPermissionOrderView             = "order:view"              // 订单查看
+	MechanismStaffPermissionOrderProcessCallback  = "order:processCallback"   // 回调处理
+	MechanismStaffPermissionAgencyOrderBillView   = "agency:orderBill:view"   // 代理商-订单账单查看
+	MechanismStaffPermissionAgencyOrderBillEdit   = "agency:orderBill:edit"   // 代理商-订单账单查看
+	MechanismStaffPermissionAgencyOrderBillSettle = "agency:orderBill:settle" // 代理商-订单账单结算
+	MechanismStaffPermissionAgencyOrderBillExport = "agency:orderBill:export" // 代理商-订单账单导出
+)
+
+var MechanismStaffPermissionNames = map[string]*Permission{
+	MechanismStaffPermissionUserView: {
+		Name: "员工查看",
+	},
+	MechanismStaffPermissionUserEdit: {
+		Name: "员工编辑",
+	},
+	MechanismStaffPermissionUserDelete: {
+		Name: "员工删除",
+	},
+	MechanismStaffPermissionRoleView: {
+		Name: "角色查看",
+	},
+	MechanismStaffPermissionRoleEdit: {
+		Name: "角色编辑",
+	},
+	MechanismStaffPermissionRoleDelete: {
+		Name: "角色删除",
+	},
+	MechanismStaffPermissionArchivesView: {
+		Name: "查看档案",
+	},
+	MechanismStaffPermissionArchivesCreate: {
+		Name: "创建档案",
+	},
+	MechanismStaffPermissionArchivesEdit: {
+		Name: "编辑档案",
+	},
+	MechanismStaffPermissionArchivesExport: {
+		Name: "档案导出",
+	},
+	MechanismStaffPermissionArchivesTagCalcTaskView: {
+		Name: "查看档案标签计算任务",
+	},
+	MechanismStaffPermissionArchivesTagCalcTaskEdit: {
+		Name: "创建档案标签计算任务",
+	},
+	MechanismStaffPermissionArchivesMechanismConfigView: {
+		Name: "获取档案配置信息",
+	},
+	MechanismStaffPermissionArchivesMechanismConfigEdit: {
+		Name: "编辑档案配置",
+	},
+
+	MechanismStaffPermissionDataPrivacyArchivesInfo: {
+		Name: "档案敏感数据查看",
+	},
+
+	MechanismStaffPermissionDepartmentView: {
+		Name: "部门查看",
+	},
+	MechanismStaffPermissionDepartmentEdit: {
+		Name: "部门编辑",
+	},
+	MechanismStaffPermissionDepartmentDelete: {
+		Name: "部门删除",
+	},
+
+	MechanismStaffPermissionSurveyView: {
+		Name: "查看体检问卷",
+	},
+	MechanismStaffPermissionSurveyEdit: {
+		Name: "编辑体检问卷",
+	},
+	MechanismStaffPermissionSurveyResultView: {
+		Name: "查看体检问卷结果",
+	},
+	MechanismStaffPermissionSurveyResultEdit: {
+		Name: "编辑体检问卷结果基础信息",
+	},
+	MechanismStaffPermissionSurveyResultDelete: {
+		Name: "删除体检体检问卷结果",
+	},
+	MechanismStaffPermissionSurveyResultUpdateData: {
+		Name: "答题、创建体检问卷结果",
+	},
+
+	MechanismStaffPermissionArchivesReportManage: {
+		Name: "查看健康风险结果",
+	},
+	MechanismStaffPermissionArchivesReportSuggestionManage: {
+		Name: "编辑健康风险健康建议",
+	},
+	MechanismStaffPermissionArchivesReportWarningMessageManage: {
+		Name: "编辑特别提醒",
+	},
+	MechanismStaffPermissionArchivesReportPdfResult: {
+		Name: "PDF报告",
+	},
+
+	MechanismStaffPermissionArchivesManagePlan: {
+		Name: "查看管理计划",
+	},
+	MechanismStaffPermissionArchivesManagePlanHealth: {
+		Name: "查看管理计划(功能医学)",
+	},
+	MechanismStaffPermissionHealthManage: {
+		Name: "健康管理",
+	},
+	MechanismStaffPermissionHealthManageTodoListView: {
+		Name: "查看/处理待办事项",
+	},
+	MechanismStaffPermissionHealthManageTodoListEdit: {
+		Name: "管理/新增待办事项",
+	},
+	MechanismStaffPermissionHealthManageTodoListSms: {
+		Name: "待办事项短信管理",
+	},
+	MechanismStaffPermissionHealthManageUserTag: {
+		Name: "用户标签管理",
+	},
+
+	MechanismStaffPermissionHealthManageSuggestionView: {
+		Name: "健康建议库查看",
+	},
+	MechanismStaffPermissionHealthManageSuggestionEdit: {
+		Name: "健康建议库管理",
+	},
+	MechanismStaffPermissionHealthManageTagView: {
+		Name: "标签库查看",
+	},
+	MechanismStaffPermissionHealthManageTagEdit: {
+		Name: "标签库管理",
+	},
+	MechanismStaffPermissionHealthManageGroupView: {
+		Name: "管理分组库查看",
+	},
+	MechanismStaffPermissionHealthManageGroupEdit: {
+		Name: "管理分组库管理",
+	},
+	MechanismStaffPermissionHealthManageVisitTemplateView: {
+		Name: "回访模板库查看",
+	},
+	MechanismStaffPermissionHealthManageVisitTemplateEdit: {
+		Name: "回访模板库管理",
+	},
+	MechanismStaffPermissionHealthManageInspectProjectView: {
+		Name: "检查项目库查看",
+	},
+	MechanismStaffPermissionHealthManageInspectProjectEdit: {
+		Name: "检查项目库管理",
+	},
+
+	MechanismStaffPermissionCustomSurveyManage: {
+		Name: "问卷管理",
+	},
+	MechanismStaffPermissionCustomSurveyResultManage: {
+		Name: "问卷结果管理",
+	},
+
+	MechanismStaffPermissionDataView: {
+		Name: "查看数据",
+	},
+	MechanismStaffPermissionDataEdit: {
+		Name: "编辑数据",
+	},
+	MechanismStaffPermissionDataUpload: {
+		Name: "上传数据",
+	},
+	MechanismStaffPermissionDataUploadVisitRecord: {
+		Name: "上传数据(巡访)",
+	},
+	MechanismStaffPermissionDataUploadDemand: {
+		Name: "上传数据(生活需求)",
+	},
+	MechanismStaffPermissionDataUploadDailyMonitor: {
+		Name: "上传数据(日常监测)",
+	},
+	MechanismStaffPermissionDataUploadDiseaseVisit: {
+		Name: "上传数据(疾病回访)",
+	},
+	MechanismStaffPermissionDataUploadInspectData: {
+		Name: "上传数据(检查数据)",
+	},
+	MechanismStaffPermissionDataUploadMedicalReport: {
+		Name: "上传数据(体检报告)",
+	},
+	MechanismStaffPermissionDataExportVisitRecord: {
+		Name: "导出数据(巡访)",
+	},
+	MechanismStaffMedicalDataGroup: {
+		Name: "数据集管理",
+	},
+	MechanismStaffMedicalDataTemplate: {
+		Name: "数据模板管理",
+	},
+
+	MechanismStaffPermissionChannelMedicalReportView: {
+		Name: "团检分析查看",
+	},
+	MechanismStaffPermissionChannelMedicalReportEdit: {
+		Name: "团检分析编辑",
+	},
+	MechanismStaffPermissionChannelMedicalReportDelete: {
+		Name: "团检分析删除",
+	},
+	MechanismStaffPermissionChannelMedicalReportAnalysis: {
+		Name: "创建团检分析",
+	},
+
+	MechanismStaffPermissionDataDashboard: {
+		Name: "数据概览查看",
+	},
+
+	MechanismStaffPermissionArticleView: {
+		Name: "知识库",
+	},
+	MechanismStaffMerchantManage: {
+		Name: "服务商管理",
+	},
+
+	MechanismStaffPermissionArchivesRunAlgor: {
+		Name: "档案综合分析",
+	},
+
+	MechanismStaffPermissionMall: {
+		Name: "商城管理",
+	},
+	MechanismStaffPermissionMallSwiper: {
+		Name: "商城-轮播图管理",
+	},
+	MechanismStaffPermissionMallRecommend: {
+		Name: "商城-推荐管理",
+	},
+	MechanismStaffPermissionMallStore: {
+		Name: "商城-店铺管理",
+	},
+	MechanismStaffPermissionMallOrder: {
+		Name: "商城-订单管理",
+	},
+	MechanismStaffPermissionMallCategory: {
+		Name: "商城-分类管理",
+	},
+	MechanismStaffPermissionMallRemark: {
+		Name: "商城-下单须知",
+	},
+	MechanismStaffPermissionMallFeedback: {
+		Name: "商城-申诉",
+	},
+
+	MechanismStaffPermissionMedicalCareDemandView: {
+		Name: "居民需求查看",
+	},
+	MechanismStaffPermissionMedicalCareCategoryView: {
+		Name: "类别管理",
+	},
+	MechanismStaffPermissionMembershipCardSet: {
+		Name: "会员卡设置",
+	},
+	MechanismStaffPermissionMembershipCardBindRecord: {
+		Name: "会员卡绑定记录",
+	},
+	MechanismStaffPermissionMembershipCardConsumeRecord: {
+		Name: "会员卡消费记录",
+	},
+	MechanismStaffPermissionMembershipCardCode: {
+		Name: "会员卡激活码",
+	},
+	MechanismStaffPermissionMembershipCardMemberSet: {
+		Name: "会员设置",
+	},
+	MechanismStaffPermissionMembershipCardServiceSet: {
+		Name: "服务设置",
+	},
+	MechanismStaffPermissionMembershipCardMemberServiceSet: {
+		Name: "服务记录设置",
+	},
+	MechanismStaffPermissionAgency: {
+		Name: "第三方管理",
+	},
+	MechanismStaffPermissionAgencyView: {
+		Name: "第三方查看",
+	},
+	MechanismStaffPermissionAgencyEdit: {
+		Name: "第三方编辑",
+	},
+	MechanismStaffPermissionAgencyDelete: {
+		Name: "第三方删除",
+	},
+	MechanismStaffPermissionAgencySettingView: {
+		Name: "第三方配置查看",
+	},
+	MechanismStaffPermissionAgencySettingEdit: {
+		Name: "第三方配置修改",
+	},
+	MechanismStaffPermissionAgencyDeveloperSettingView: {
+		Name: "第三方开发者设置查看",
+	},
+	MechanismStaffPermissionAgencyDeveloperSettingEdit: {
+		Name: "第三方开发者设置编辑",
+	},
+	MechanismStaffPermissionAgencyPromotionGoodsView: {
+		Name: "第三方-推广商品查看",
+	},
+	MechanismStaffPermissionAgencyPromotionGoodsEdit: {
+		Name: "第三方-推广商品编辑",
+	},
+	MechanismStaffPermissionAgencyPromotionGoodsDelete: {
+		Name: "第三方-推广商品删除",
+	},
+	MechanismStaffPermissionAgencyPaymentSettingView: {
+		Name: "第三方-支付设置查看",
+	},
+	MechanismStaffPermissionAgencyPaymentSettingEdit: {
+		Name: "第三方-支付设置编辑",
+	},
+	MechanismStaffPermissionAgencyPaymentSettingDelete: {
+		Name: "第三方-支付设置删除",
+	},
+	MechanismStaffPermissionAgencyOrderBillView: {
+		Name: "第三方-订单账单查看",
+	},
+	MechanismStaffPermissionAgencyOrderBillEdit: {
+		Name: "第三方-订单账单编辑",
+	},
+	MechanismStaffPermissionAgencyOrderBillSettle: {
+		Name: "第三方-订单账单结算",
+	},
+	MechanismStaffPermissionAgencyOrderBillExport: {
+		Name: "第三方-订单账单导出",
+	},
+	MechanismStaffPermissionOrderView: {
+		Name: "订单查看",
+	},
+	MechanismStaffPermissionOrderProcessCallback: {
+		Name: "手动处理回调",
+	},
+}

+ 151 - 0
constants/user_permission.go

@@ -0,0 +1,151 @@
+package constants
+
+type Permission struct {
+	Name   string `json:"name"`
+	Remark string `json:"remark"`
+}
+
+const (
+	// ------------------- 用户系统User的权限 -------------------
+	UserPermissionMechanismView               = "user:mechanism:view"              // 机构查看
+	UserPermissionMechanismEdit               = "user:mechanism:edit"              // 机构编辑
+	UserPermissionMechanismDelete             = "user:mechanism:delete"            // 机构删除
+	UserPermissionMedicalDataView             = "user:medicalData:view"            // 查看医疗数据
+	UserPermissionMedicalDataEdit             = "user:medicalData:edit"            // 编辑医疗数据
+	UserPermissionMedicalDataAbandon          = "user:medicalData:abandon"         // 作废医疗数据
+	UserPermissionMedicalDataAnalysis         = "user:medicalData:analysis"        // 分析医疗数据
+	UserPermissionMedicalDataRawDataView      = "user:medicalData:rawData:view"    // 查看医疗数据原始数据
+	UserPermissionMedicalDataConfirm          = "user:medicalData:confirm"         // 确认医疗报告
+	UserPermissionMedicalCompareReportView    = "user:medicalCompareReport:view"   // 横向对比报告查看
+	UserPermissionArchivesView                = "user:archive:view"                // 档案查看
+	UserPermissionArchivesEdit                = "user:archive:edit"                // 档案编辑
+	UserPermissionArchivesRunAlgor            = "user:archives:runAlgor"           // 运行算法
+	UserPermissionArchivesFormTemplateView    = "user:archiveFormTemplate:delete"  // 档案表单模板查看
+	UserPermissionArchivesFormTemplateEdit    = "user:archiveFormTemplate:edit"    // 档案表单模板编辑
+	UserPermissionArchivesMechanismConfigView = "user:archiveMechanismConfig:view" // 档案机构配置查看
+	UserPermissionArchivesMechanismConfigEdit = "user:archiveMechanismConfig:edit" // 档案机构配置编辑
+	UserPermissionFormView                    = "user:form:view"                   // 表单查看
+	UserPermissionFormEdit                    = "user:form:edit"                   // 表单编辑
+	UserPermissionFormFieldEdit               = "user:formField:edit"              // 表单字段编辑
+	UserPermissionFormFieldDelete             = "user:formField:delete"            // 表单字段删除
+	UserPermissionSurveyView                  = "user:survey:view"                 // 查看问卷信息
+	UserPermissionSurveyEdit                  = "user:survey:edit"                 // 编辑问卷信息
+	UserPermissionSurveyAuthorizeView         = "user:surveyAuthorize:view"        // 问卷授权查看
+	UserPermissionSurveyAuthorizeEdit         = "user:surveyAuthorize:edit"        // 问卷授权编辑
+	UserPermissionSurveyResultView            = "user:surveyResult:view"           // 问卷结果查看
+	UserPermissionSurveyResultEdit            = "user:surveyResult:edit"           // 问卷结果编辑
+	UserPermissionAlgorAuthorizeView          = "user:algorAuthorize:view"         // 算法授权查看
+	UserPermissionWallet                      = "user:wallet"                      // 算法授权查看
+	UserPermissionGroupMedicalReportView      = "user:groupMedicalReport:view"     // 查看群体医疗报告
+	UserPermissionGroupMedicalReportEdit      = "user:groupMedicalReport:edit"     // 编辑群体医疗报告
+	UserPermissionGroupMedicalReportDelete    = "user:groupMedicalReport:delete"   // 删除群体医疗报告
+	UserPermissionGroupMedicalReportAnalysis  = "user:groupMedicalReport:analysis" // 分析群体医疗报告
+
+	UserPermissionDataPrivacyArchivesInfo = "user:dataPrivacy:archivesInfo" // 查看档案信息中隐私数据
+)
+
+var UserPermissionNames = map[string]*Permission{
+	UserPermissionMechanismView: {
+		Name: "机构查看",
+	},
+	UserPermissionMechanismEdit: {
+		Name: "机构编辑",
+	},
+	UserPermissionMechanismDelete: {
+		Name: "机构删除",
+	},
+	UserPermissionMedicalDataView: {
+		Name: "查看医疗数据",
+	},
+	UserPermissionMedicalDataEdit: {
+		Name: "编辑医疗数据",
+	},
+	UserPermissionMedicalDataAbandon: {
+		Name: "作废医疗数据",
+	},
+	UserPermissionMedicalDataAnalysis: {
+		Name: "分析医疗数据",
+	},
+	UserPermissionMedicalDataRawDataView: {
+		Name: "查看医疗数据原始数据",
+	},
+	UserPermissionMedicalDataConfirm: {
+		Name: "确认医疗报告",
+	},
+	UserPermissionMedicalCompareReportView: {
+		Name: "用户数据",
+	},
+	UserPermissionArchivesView: {
+		Name: "档案查看",
+	},
+	UserPermissionArchivesEdit: {
+		Name: "档案编辑",
+	},
+	UserPermissionArchivesRunAlgor: {
+		Name: "档案综合分析",
+	},
+	UserPermissionArchivesFormTemplateView: {
+		Name: "档案表单模板查看",
+	},
+	UserPermissionArchivesFormTemplateEdit: {
+		Name: "档案表单模板编辑",
+	},
+	UserPermissionArchivesMechanismConfigView: {
+		Name: "档案机构配置查看",
+	},
+	UserPermissionArchivesMechanismConfigEdit: {
+		Name: "档案机构配置编辑",
+	},
+	UserPermissionFormView: {
+		Name: "表单查看",
+	},
+	UserPermissionFormEdit: {
+		Name: "表单编辑",
+	},
+	UserPermissionFormFieldEdit: {
+		Name: "表单字段编辑",
+	},
+	UserPermissionFormFieldDelete: {
+		Name: "表单字段删除",
+	},
+	UserPermissionSurveyView: {
+		Name: "查看问卷信息",
+	},
+	UserPermissionSurveyEdit: {
+		Name: "编辑问卷信息",
+	},
+	UserPermissionSurveyAuthorizeView: {
+		Name: "问卷授权查看",
+	},
+	UserPermissionSurveyAuthorizeEdit: {
+		Name: "问卷授权编辑",
+	},
+	UserPermissionSurveyResultView: {
+		Name: "问卷结果查看",
+	},
+	UserPermissionSurveyResultEdit: {
+		Name: "问卷结果编辑",
+	},
+	UserPermissionAlgorAuthorizeView: {
+		Name: "算法授权查看",
+	},
+
+	UserPermissionDataPrivacyArchivesInfo: {
+		Name: "档案敏感数据查看",
+	},
+	UserPermissionWallet: {
+		Name: "钱包管理",
+	},
+	UserPermissionGroupMedicalReportView: {
+		Name: "查看团体报告",
+	},
+	UserPermissionGroupMedicalReportEdit: {
+		Name: "创建和编辑团体报告",
+	},
+	UserPermissionGroupMedicalReportDelete: {
+		Name: "删除团体报告",
+	},
+	UserPermissionGroupMedicalReportAnalysis: {
+		Name: "分析团体报告",
+	},
+}

+ 98 - 0
form/main.go

@@ -0,0 +1,98 @@
+package form
+
+import (
+	"fmt"
+
+	"github.com/guonaihong/gout"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+)
+
+// 获取表单列表
+func ListForm(ids []string) (*sdk.BaseResponse[sdk.ListResponse[*sdk.Form]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[*sdk.Form]]
+	if len(ids) == 0 {
+		return resp, nil
+	}
+	resp, err := postReq[*sdk.BaseResponse[sdk.ListResponse[*sdk.Form]]]("/formService/openapi/form/listByIds", gout.H{
+		"ids": ids,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取表单数据
+func DetailForm(id string, needCheckItemId bool) (*sdk.BaseResponse[sdk.DetailResponse[*sdk.Form]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.DetailResponse[*sdk.Form]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.DetailResponse[*sdk.Form]]]("/formService/openapi/form/detail", gout.H{
+		"id":              id,
+		"needCheckItemId": needCheckItemId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取表单数据
+func DetailFormByCustomFields(customFields []*sdk.FormCustomField) (*sdk.BaseResponse[sdk.FormFieldsResponse[[]*sdk.FormField]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.FormFieldsResponse[[]*sdk.FormField]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.FormFieldsResponse[[]*sdk.FormField]]]("/formService/openapi/form/detailByCustomFields", gout.H{
+		"customFields": customFields,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// postReq 发送post请求
+func postReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.POST(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetJSON(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}

+ 58 - 0
form/main_test.go

@@ -0,0 +1,58 @@
+package form_test
+
+import (
+	"fmt"
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/form"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/utils"
+)
+
+func TestList(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		response, err := form.ListForm([]string{
+			"4ZP4Zy52", "pOkrdWA1",
+		})
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		list := response.Data.List
+		t.Logf("list len: %d", len(list))
+	})
+}
+
+func TestDetail(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		response, err := form.DetailForm("4ZP4Zy52", false)
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		detail := response.Data.Detail
+		t.Logf("list len: %v", detail)
+	})
+}
+
+func TestDetailByCustomFields(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.hhmdtech.com",
+			AppDebug:  true,
+		})
+		response, err := form.DetailFormByCustomFields([]*sdk.FormCustomField{
+			{
+				Type: 2,
+				Key:  "PsyConditions",
+			},
+		})
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		detail := response.Data.FormFields
+		fmt.Println(utils.JsonEncode(detail))
+	})
+}

+ 40 - 0
go.mod

@@ -0,0 +1,40 @@
+module gogs.uu.mdfitnesscao.com/Algor/sdk
+
+go 1.19
+
+require github.com/guonaihong/gout v0.3.8
+
+require (
+	github.com/gobuffalo/envy v1.7.0 // indirect
+	github.com/gobuffalo/packd v0.3.0 // indirect
+	github.com/gobuffalo/packr v1.30.1 // indirect
+	github.com/joho/godotenv v1.3.0 // indirect
+	github.com/rogpeppe/go-internal v1.3.0 // indirect
+	golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
+)
+
+require (
+	github.com/andybalholm/brotli v1.0.4 // indirect
+	github.com/bytedance/sonic v1.7.0 // indirect
+	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
+	github.com/go-playground/locales v0.13.0 // indirect
+	github.com/go-playground/universal-translator v0.17.0 // indirect
+	github.com/go-playground/validator/v10 v10.4.1 // indirect
+	github.com/goccy/go-json v0.10.0 // indirect
+	github.com/golang-module/carbon v1.7.3
+	github.com/json-iterator/go v1.1.9 // indirect
+	github.com/klauspost/cpuid/v2 v2.0.9 // indirect
+	github.com/leodido/go-urn v1.2.0 // indirect
+	github.com/mattn/go-isatty v0.0.19 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
+	github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/samber/lo v1.38.1
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
+	golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
+	golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect
+	golang.org/x/sys v0.6.0 // indirect
+	google.golang.org/protobuf v1.26.0 // indirect
+	gopkg.in/yaml.v2 v2.2.8 // indirect
+)

+ 201 - 0
go.sum

@@ -0,0 +1,201 @@
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
+github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
+github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.7.0 h1:P7DyGrkLbVDzcuqagPsSFnAwwljjhmB3qVF5wzmHOxE=
+github.com/bytedance/sonic v1.7.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
+github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
+github.com/bytedance/sonic v1.10.0 h1:qtNZduETEIWJVIyDl01BeNxur2rW9OwTQ/yBqFRkKEk=
+github.com/bytedance/sonic v1.10.0/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
+github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
+github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
+github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
+github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
+github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
+github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
+github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
+github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
+github.com/go-playground/validator/v10 v10.15.3 h1:S+sSpunYjNPDuXkWbK+x+bA7iXiW296KG4dL3X7xUZo=
+github.com/go-playground/validator/v10 v10.15.3/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU=
+github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
+github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4=
+github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
+github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg=
+github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIaviy289eRuk=
+github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw=
+github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
+github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/golang-module/carbon v1.7.3 h1:p5mUZj7Tg62MblrkF7XEoxVPvhVs20N/kimqsZOQ+/U=
+github.com/golang-module/carbon v1.7.3/go.mod h1:nUMnXq90Rv8a7h2+YOo2BGKS77Y0w/hMPm4/a8h19N8=
+github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
+github.com/guonaihong/gout v0.3.8 h1:t0yjR0DgwVX6L4Zf/gv7ZVUcVPMicEpnnWjk3XxFTKA=
+github.com/guonaihong/gout v0.3.8/go.mod h1:wDXeuyeZR6MtaHbytO9RLcKW4iCDrWD6/KF1QwDtbRc=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
+github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
+github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
+github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
+github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
+github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
+github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
+github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
+github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
+github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y=
+golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
+golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
+golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCTu3mcIURZfNkVweuRKA=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
+golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
+golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

+ 420 - 0
graph/helper.go

@@ -0,0 +1,420 @@
+package graph
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/golang-module/carbon"
+	"github.com/samber/lo"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/utils"
+)
+
+// 获取节点列表,并转成问题模板的格式返回
+func ListNodeToQuestionTemplate(ids []string, needCheckItemId bool) ([]*sdk.QuestionnaireTemplate, *response.ErrCode) {
+	response, err := ListNode(ids)
+	if err != nil {
+		return nil, err
+	}
+	list := response.Data.List
+	var questionTemplates []*sdk.QuestionnaireTemplate = make([]*sdk.QuestionnaireTemplate, 0)
+	for _, item := range list {
+		questionTemplates = append(questionTemplates, FormatNodeToSurveyQuestionTemplate(item, needCheckItemId))
+	}
+
+	return questionTemplates, nil
+}
+
+func GetNodeRelationShipsToStruct(id, name string) ([]*sdk.QuestionnaireSubjectSelectValue, []*sdk.QuestionnaireSubjectSelectValue) {
+	response, err := GetNodeRelationShips(id, name)
+	if err != nil {
+		return nil, nil
+	}
+	relationShips := response.Data
+	// 单位列表
+	var unitValues []*sdk.QuestionnaireSubjectSelectValue = make([]*sdk.QuestionnaireSubjectSelectValue, 0)
+	// 范围列表
+	var rangeValues []*sdk.QuestionnaireSubjectSelectValue = make([]*sdk.QuestionnaireSubjectSelectValue, 0)
+	for _, relation := range relationShips {
+		unitValues = append(unitValues, &sdk.QuestionnaireSubjectSelectValue{
+			Value: relation["mProperties"].(map[string]any)["name"].(string),
+			Label: relation["mProperties"].(map[string]any)["name"].(string),
+		})
+		// 判断properties是否有“参考范围”这个属性
+		if _, ok := relation["properties"].(map[string]any)["参考范围"]; ok {
+			rangeValues = append(rangeValues, &sdk.QuestionnaireSubjectSelectValue{
+				Value: relation["properties"].(map[string]any)["参考范围"].(string),
+				Label: relation["properties"].(map[string]any)["参考范围"].(string),
+			})
+		}
+	}
+
+	return unitValues, rangeValues
+}
+
+func FormatNodeToSurveyQuestionTemplate(graphNode *sdk.GraphNode, needCheckItemId bool) *sdk.QuestionnaireTemplate {
+
+	unitValues, rangeValues := GetNodeRelationShipsToStruct(graphNode.ID, "默认单位与范围")
+
+	questionaireTemplate := &sdk.QuestionnaireTemplate{
+		SN:           graphNode.ID,
+		Title:        graphNode.Properties.Name,
+		SubjectTotal: 4,
+		SubjectIds: []string{
+			fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorValueFlag),
+			fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorRangeFlag),
+			fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorUnitFlag),
+			fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorTimeFlag),
+		},
+		Subjects: []*sdk.QuestionnaireSubject{
+			{
+				SN:           fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorValueFlag),
+				Type:         sdk.QuestionSubjectTypeInput,
+				Title:        "检查结果",
+				SelectValues: make([]*sdk.QuestionnaireSubjectSelectValue, 0),
+				Validator: utils.JsonEncode(map[string]any{
+					"type":        sdk.QuestionSubjectTypeInputFlag,
+					"edit":        true,
+					"attr":        fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorValueFlag),
+					"sn":          fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorValueFlag),
+					"remark":      "",
+					"combination": "",
+					"isRepeat":    false,
+					"config": map[string]any{
+						"desc":          "",
+						"rule":          "",
+						"type":          "",
+						"regexRule":     "",
+						"regexRuleName": "",
+					},
+					"choices":  []any{},
+					"children": []any{},
+				}),
+			},
+			{
+				SN:           fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorRangeFlag),
+				Type:         sdk.QuestionSubjectTypeInput,
+				Title:        "参考范围",
+				SelectValues: rangeValues,
+				Validator: utils.JsonEncode(map[string]any{
+					"type":        sdk.QuestionSubjectTypeInputFlag,
+					"edit":        true,
+					"attr":        fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorRangeFlag),
+					"sn":          fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorRangeFlag),
+					"remark":      "",
+					"combination": "",
+					"isRepeat":    false,
+					"config": map[string]any{
+						"desc":          "",
+						"rule":          "",
+						"type":          "",
+						"regexRule":     "",
+						"regexRuleName": "",
+					},
+					"choices":  []any{},
+					"children": []any{},
+				}),
+			},
+			{
+				SN:           fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorUnitFlag),
+				Type:         sdk.QuestionSubjectTypeInput,
+				Title:        "单位",
+				SelectValues: unitValues,
+				Validator: utils.JsonEncode(map[string]any{
+					"type":        sdk.QuestionSubjectTypeInputFlag,
+					"edit":        true,
+					"attr":        fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorUnitFlag),
+					"sn":          fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorUnitFlag),
+					"remark":      "",
+					"combination": "",
+					"isRepeat":    false,
+					"config": map[string]any{
+						"desc":          "",
+						"rule":          "",
+						"type":          "",
+						"regexRule":     "",
+						"regexRuleName": "",
+					},
+					"choices":  []any{},
+					"children": []any{},
+				}),
+			},
+			{
+				SN:           fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorTimeFlag),
+				Type:         sdk.QuestionSubjectTypeDate,
+				Title:        "检查时间",
+				SelectValues: make([]*sdk.QuestionnaireSubjectSelectValue, 0),
+				Validator: utils.JsonEncode(map[string]any{
+					"type":        sdk.QuestionSubjectTypeDateFlag,
+					"edit":        true,
+					"attr":        fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorTimeFlag),
+					"sn":          fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorTimeFlag),
+					"remark":      "",
+					"combination": "",
+					"isRepeat":    false,
+					"config": map[string]any{
+						"desc":          "",
+						"rule":          "",
+						"type":          "",
+						"regexRule":     "",
+						"regexRuleName": "",
+					},
+					"choices":  []any{},
+					"children": []any{},
+				}),
+			},
+		},
+	}
+
+	if needCheckItemId {
+		questionaireTemplate.SubjectTotal++
+		questionaireTemplate.SubjectIds = append(questionaireTemplate.SubjectIds, fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorCheckItemIdFlag))
+		questionaireTemplate.Subjects = append(questionaireTemplate.Subjects, &sdk.QuestionnaireSubject{
+			SN:           fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorCheckItemIdFlag),
+			Type:         sdk.QuestionSubjectTypeInput,
+			Title:        "检查项目",
+			SelectValues: make([]*sdk.QuestionnaireSubjectSelectValue, 0),
+			Validator: utils.JsonEncode(map[string]any{
+				"type":        sdk.QuestionSubjectTypeInputFlag,
+				"edit":        true,
+				"attr":        fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorCheckItemIdFlag),
+				"sn":          fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, graphNode.ID, sdk.IndicatorCheckItemIdFlag),
+				"remark":      "",
+				"combination": "",
+				"isRepeat":    false,
+				"isHidden":    true,
+				"config": map[string]any{
+					"desc":          "",
+					"rule":          "",
+					"type":          "",
+					"regexRule":     "",
+					"regexRuleName": "",
+				},
+				"choices":  []any{},
+				"children": []any{},
+			}),
+		})
+	}
+	return questionaireTemplate
+}
+
+// 提供问题答案列表,过滤出指标的问题答案(返回不是指标的问题,返回指标数据)
+func FilterArchivesValues(archivesValuesList []*sdk.ArchivesValues) ([]*sdk.ArchivesValues, []*sdk.Indicator) {
+	var indicators []*sdk.Indicator = make([]*sdk.Indicator, 0)
+	var surveyAnswers []*sdk.ArchivesValues = make([]*sdk.ArchivesValues, 0)
+	var indicatorAnswers []*sdk.ArchivesValues = make([]*sdk.ArchivesValues, 0)
+	var nodeIds []string = make([]string, 0)
+	for _, archivesValues := range archivesValuesList {
+		var answer *sdk.SurveyAnswer
+		if archivesValues.ReturnAnswer == nil {
+			answer = archivesValues.Answer
+		} else {
+			answer = archivesValues.ReturnAnswer
+		}
+		if answer == nil {
+			continue
+		}
+
+		// 判断是否包含前缀
+		if !strings.Contains(answer.QuestionNo, sdk.IndicatorQuestionSubjectPrefix) {
+			surveyAnswers = append(surveyAnswers, archivesValues)
+			continue
+		} else {
+			// 将所有属于指标的问题答案过滤出来
+			indicatorAnswers = append(indicatorAnswers, archivesValues)
+			// 将指标的问题答案的编号过滤出来
+			indicatorStrings := strings.Split(answer.QuestionNo, ":")
+			if len(indicatorStrings) == 5 {
+				nodeIds = append(nodeIds, strings.Join(indicatorStrings[1:4], ":"))
+			}
+		}
+	}
+
+	nodeIds = lo.Uniq(nodeIds)
+
+	// 获取节点列表
+	nodeResponse, err := ListNode(nodeIds)
+	var nodeList []*sdk.GraphNode = make([]*sdk.GraphNode, 0)
+	if err == nil {
+		nodeList = nodeResponse.Data.List
+	}
+
+	// 遍历所有的指标问题答案,将其转换成指标数据
+	for _, nodeId := range nodeIds {
+		var value string    // 指标值
+		var rangeStr string // 指标范围
+		var unit string     // 指标单位
+		var time string     // 指标检查时间
+		var name string     // 指标名称
+		var itemName string // 指标名称
+		var itemId string   // 指标ID
+		// 找到对应的节点
+		node, finded := lo.Find(nodeList, func(graphNode *sdk.GraphNode) bool {
+			return graphNode.ID == nodeId
+		})
+		if finded {
+			name = node.Properties.Name
+		}
+
+		// 查询ItemId
+		// 检查值
+		checkItemValues, finded := lo.Find(indicatorAnswers, func(archivesValues *sdk.ArchivesValues) bool {
+			var answer *sdk.SurveyAnswer
+			if archivesValues.ReturnAnswer == nil {
+				answer = archivesValues.Answer
+			} else {
+				answer = archivesValues.ReturnAnswer
+			}
+			if answer == nil {
+				return false
+			}
+			return answer.QuestionNo == fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, nodeId, sdk.IndicatorCheckItemIdFlag)
+		})
+		if finded {
+			var answer *sdk.SurveyAnswer
+			if checkItemValues.ReturnAnswer == nil {
+				answer = checkItemValues.Answer
+			} else {
+				answer = checkItemValues.ReturnAnswer
+			}
+			if answer != nil && len(answer.InputAnswers.Value) > 0 {
+				itemId = answer.InputAnswers.Value[0]
+				// 查询名称
+				response, err := ListNode([]string{itemId})
+				if err == nil {
+					itemName = response.Data.List[0].Properties.Name
+				}
+			}
+		} else {
+			// 获取节点列表
+			nodeRelationResponse, err := GetNodeRelationd(nodeId, "可检测")
+			if err == nil {
+				if len(nodeRelationResponse.Data) > 0 {
+					itemName = nodeRelationResponse.Data[0]["properties"].(map[string]any)["name"].(string)
+					itemId = nodeRelationResponse.Data[0]["id"].(string)
+				}
+			}
+		}
+
+		// 检查值
+		valueValues, finded := lo.Find(indicatorAnswers, func(archivesValues *sdk.ArchivesValues) bool {
+			var answer *sdk.SurveyAnswer
+			if archivesValues.ReturnAnswer == nil {
+				answer = archivesValues.Answer
+			} else {
+				answer = archivesValues.ReturnAnswer
+			}
+			if answer == nil {
+				return false
+			}
+			return answer.QuestionNo == fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, nodeId, sdk.IndicatorValueFlag)
+		})
+		if finded {
+			var answer *sdk.SurveyAnswer
+			if valueValues.ReturnAnswer == nil {
+				answer = valueValues.Answer
+			} else {
+				answer = valueValues.ReturnAnswer
+			}
+			if answer != nil && len(answer.InputAnswers.Value) > 0 {
+				value = answer.InputAnswers.Value[0]
+			}
+		}
+
+		// 检查范围
+		rangeValues, finded := lo.Find(indicatorAnswers, func(archivesValues *sdk.ArchivesValues) bool {
+			var answer *sdk.SurveyAnswer
+			if archivesValues.ReturnAnswer == nil {
+				answer = archivesValues.Answer
+			} else {
+				answer = archivesValues.ReturnAnswer
+			}
+			if answer == nil {
+				return false
+			}
+			return answer.QuestionNo == fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, nodeId, sdk.IndicatorRangeFlag)
+		})
+		if finded {
+			var answer *sdk.SurveyAnswer
+			if rangeValues.ReturnAnswer == nil {
+				answer = rangeValues.Answer
+			} else {
+				answer = rangeValues.ReturnAnswer
+			}
+			if answer != nil && len(answer.InputAnswers.Value) > 0 {
+				rangeStr = answer.InputAnswers.Value[0]
+			}
+		}
+		// 检查单位
+		unitValues, finded := lo.Find(indicatorAnswers, func(archivesValues *sdk.ArchivesValues) bool {
+			var answer *sdk.SurveyAnswer
+			if archivesValues.ReturnAnswer == nil {
+				answer = archivesValues.Answer
+			} else {
+				answer = archivesValues.ReturnAnswer
+			}
+			if answer == nil {
+				return false
+			}
+			return answer.QuestionNo == fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, nodeId, sdk.IndicatorUnitFlag)
+		})
+		if finded {
+			var answer *sdk.SurveyAnswer
+			if unitValues.ReturnAnswer == nil {
+				answer = unitValues.Answer
+			} else {
+				answer = unitValues.ReturnAnswer
+			}
+			if answer != nil && len(answer.InputAnswers.Value) > 0 {
+				unit = answer.InputAnswers.Value[0]
+			}
+		}
+
+		// 检查时间
+		timeValues, finded := lo.Find(indicatorAnswers, func(archivesValues *sdk.ArchivesValues) bool {
+			var answer *sdk.SurveyAnswer
+			if archivesValues.ReturnAnswer == nil {
+				answer = archivesValues.Answer
+			} else {
+				answer = archivesValues.ReturnAnswer
+			}
+			if answer == nil {
+				return false
+			}
+			return answer.QuestionNo == fmt.Sprintf("%s:%s:%s", sdk.IndicatorQuestionSubjectPrefix, nodeId, sdk.IndicatorTimeFlag)
+		})
+		if finded {
+			var answer *sdk.SurveyAnswer
+			if timeValues.ReturnAnswer == nil {
+				answer = timeValues.Answer
+			} else {
+				answer = timeValues.ReturnAnswer
+			}
+			if answer != nil {
+				time = answer.Answer.Value
+			}
+		}
+
+		// 检查是否有任意一个参数有值
+		if value != "" || rangeStr != "" || unit != "" || time != "" {
+			date := 0
+			if time != "" {
+				date = int(carbon.Parse(time).Carbon2Time().Unix())
+			}
+			// 开始拼装指标数据
+			indicators = append(indicators, &sdk.Indicator{
+				ID:        nodeId,
+				Name:      name,
+				Value:     value,
+				Unit:      unit,
+				ItemName:  itemName,
+				ItemID:    itemId,
+				Reference: rangeStr,
+				Date:      date,
+			})
+		}
+	}
+
+	return surveyAnswers, indicators
+}

+ 144 - 0
graph/main.go

@@ -0,0 +1,144 @@
+package graph
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/guonaihong/gout"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+)
+
+// 获取节点列表
+func PaginateNode(ids []string, name string, tags []string, pageSize int64) (*sdk.BaseResponse[sdk.PaginateResponse[*sdk.GraphNode]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.PaginateResponse[*sdk.GraphNode]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.PaginateResponse[*sdk.GraphNode]]]("/graphService/open/node/paginate", gout.H{
+		"id":       strings.Join(ids, ","),
+		"pageSize": pageSize,
+		"name":     name,
+		"tag":      strings.Join(tags, ","),
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取节点列表
+func ListNode(ids []string) (*sdk.BaseResponse[sdk.PaginateResponse[*sdk.GraphNode]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.PaginateResponse[*sdk.GraphNode]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.PaginateResponse[*sdk.GraphNode]]]("/graphService/open/node/paginate", gout.H{
+		"id":       strings.Join(ids, ","),
+		"pageSize": len(ids),
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取节点关系
+func GetNodeRelationShips(id, relationName string) (*sdk.BaseResponse[[]map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[[]map[string]any]
+	resp, err := getReq[*sdk.BaseResponse[[]map[string]any]]("/graphService/open/node/relationship", gout.H{
+		"id":    id,
+		"rName": relationName,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取节点关系
+func GetNodeRelationd(id, relationName string) (*sdk.BaseResponse[[]map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[[]map[string]any]
+	resp, err := getReq[*sdk.BaseResponse[[]map[string]any]]("/graphService/open/node/related", gout.H{
+		"id":           id,
+		"relationship": relationName,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// postReq 发送post请求
+func postReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().AlgorApiDomain == "" {
+		return res, fmt.Errorf("请先配置请求域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().AlgorApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.POST(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetJSON(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}
+
+// postReq 发送post请求
+func getReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().AlgorApiDomain == "" {
+		return res, fmt.Errorf("请先配置请求域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().AlgorApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.GET(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetQuery(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}

+ 223 - 0
graph/main_test.go

@@ -0,0 +1,223 @@
+package graph_test
+
+import (
+	"encoding/json"
+	"fmt"
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/graph"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/utils"
+)
+
+func TestList(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			AlgorApiDomain: "https://api.mdfitnesscao.com",
+			AppDebug:       true,
+		})
+		response, err := graph.ListNode([]string{
+			"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:1378",
+		})
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		list := response.Data.List
+		node := list[0]
+		fmt.Println(node.Properties.Tags)
+		t.Logf("list len: %v", utils.JsonEncode(list))
+	})
+}
+
+func TestListTemplate(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			AlgorApiDomain: "https://api.mdfitnesscao.com",
+			AppDebug:       true,
+		})
+		templates, err := graph.ListNodeToQuestionTemplate([]string{
+			"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:989", "4:b8fbfa26-3437-4bbb-8349-96abd14851ea:93",
+		}, false)
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("list len: %d", len(templates))
+		t.Logf("list: %s", utils.JsonEncode(templates))
+	})
+}
+
+func TestGetNodeRelationShip(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			AlgorApiDomain: "https://api.hhmdtech.com",
+			AppDebug:       true,
+		})
+
+		relationResponse, relationErr := graph.GetNodeRelationd("4:aad18a76-6ee3-48a0-bec9-4f7e0bb822dc:357", "可检测")
+		if relationErr == nil && len(relationResponse.Data) > 0 {
+			bloodPressureItemGroupId := relationResponse.Data[0]["id"].(string)
+			bloodPressureItemGroupName := relationResponse.Data[0]["properties"].(map[string]any)["name"].(string)
+			fmt.Println(bloodPressureItemGroupId, bloodPressureItemGroupName)
+		}
+	})
+}
+
+func TestFilterArchivesValues(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			AlgorApiDomain: "https://api.mdfitnesscao.com",
+			AppDebug:       true,
+		})
+		var jsonStr = `[
+				{
+						"answer": {
+								"checkboxAnswers": null,
+								"groupAnswers": null,
+								"inputAnswers": {
+										"key": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:189:value",
+										"value": [
+												"111"
+										]
+								},
+								"linkAnswers": null,
+								"matrixAnswers": null,
+								"multipleAnswers": false,
+								"questionNo": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:189:value",
+								"type": "input"
+						},
+						"extraType": 4
+				},
+				{
+						"answer": {
+								"checkboxAnswers": null,
+								"groupAnswers": null,
+								"inputAnswers": {
+										"key": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:189:range",
+										"value": [
+												""
+										]
+								},
+								"linkAnswers": null,
+								"matrixAnswers": null,
+								"multipleAnswers": false,
+								"questionNo": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:189:range",
+								"type": "input"
+						},
+						"extraType": 4
+				},
+				{
+						"answer": {
+								"checkboxAnswers": null,
+								"groupAnswers": null,
+								"inputAnswers": {
+										"key": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:189:unit",
+										"value": [
+												""
+										]
+								},
+								"linkAnswers": null,
+								"matrixAnswers": null,
+								"multipleAnswers": false,
+								"questionNo": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:189:unit",
+								"type": "input"
+						},
+						"extraType": 4
+				},
+				{
+						"answer": {
+								"answer": {
+										"key": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:189:time",
+										"value": ""
+								},
+								"checkboxAnswers": null,
+								"groupAnswers": null,
+								"inputAnswers": null,
+								"linkAnswers": null,
+								"matrixAnswers": null,
+								"multipleAnswers": false,
+								"questionNo": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:189:time",
+								"type": "date"
+						},
+						"extraType": 4
+				},
+				{
+						"answer": {
+								"checkboxAnswers": null,
+								"groupAnswers": null,
+								"inputAnswers": {
+										"key": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:190:value",
+										"value": [
+												"66"
+										]
+								},
+								"linkAnswers": null,
+								"matrixAnswers": null,
+								"multipleAnswers": false,
+								"questionNo": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:190:value",
+								"type": "input"
+						},
+						"extraType": 4
+				},
+				{
+						"answer": {
+								"checkboxAnswers": null,
+								"groupAnswers": null,
+								"inputAnswers": {
+										"key": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:190:range",
+										"value": [
+												""
+										]
+								},
+								"linkAnswers": null,
+								"matrixAnswers": null,
+								"multipleAnswers": false,
+								"questionNo": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:190:range",
+								"type": "input"
+						},
+						"extraType": 4
+				},
+				{
+						"answer": {
+								"checkboxAnswers": null,
+								"groupAnswers": null,
+								"inputAnswers": {
+										"key": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:190:unit",
+										"value": [
+												""
+										]
+								},
+								"linkAnswers": null,
+								"matrixAnswers": null,
+								"multipleAnswers": false,
+								"questionNo": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:190:unit",
+								"type": "input"
+						},
+						"extraType": 4
+				},
+				{
+						"answer": {
+								"answer": {
+										"key": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:190:time",
+										"value": ""
+								},
+								"checkboxAnswers": null,
+								"groupAnswers": null,
+								"inputAnswers": null,
+								"linkAnswers": null,
+								"matrixAnswers": null,
+								"multipleAnswers": false,
+								"questionNo": "b8fbfa26.indicator:4:b8fbfa26-3437-4bbb-8349-96abd14851ea:190:time",
+								"type": "date"
+						},
+						"extraType": 4
+				}
+		]`
+		var values []*sdk.ArchivesValues
+		json.Unmarshal([]byte(jsonStr), &values)
+		unit, rangeValues := graph.FilterArchivesValues(
+			values,
+		)
+		t.Log("list", utils.JsonEncode(unit))
+		t.Log("list", utils.JsonEncode(rangeValues))
+	})
+}

+ 13 - 0
helper.go

@@ -0,0 +1,13 @@
+package sdk
+
+var config *ClientConfig = &ClientConfig{}
+
+// 初始化配置
+func InitConfig(c *ClientConfig) {
+	config = c
+}
+
+// 获取配置
+func GetConfig() ClientConfig {
+	return *config
+}

+ 39 - 0
idc/helper.go

@@ -0,0 +1,39 @@
+package idc
+
+import (
+	"fmt"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+)
+
+type ArchivesMedicalData struct {
+	*sdk.ArchivesMedicalData
+}
+
+// 获取档案所有的数据
+func GetMedicalData(archivesId string) (*ArchivesMedicalData, error) {
+	response, respErr := GetAllValuesByArchivesId(archivesId)
+	if respErr != nil {
+		return nil, fmt.Errorf("获取档案数据失败: %s", respErr.Msg)
+	}
+
+	return &ArchivesMedicalData{response.Data}, nil
+}
+
+// 给定指标ID获取指标的所有的历史记录(倒序排列)
+func (archivesMedicalData *ArchivesMedicalData) GetArchivesDataByIndicatorId(indicatorId string) []*sdk.Indicator {
+	var indicators []*sdk.Indicator = make([]*sdk.Indicator, 0)
+	if len(archivesMedicalData.Indicators[indicatorId]) > 0 {
+		indicators = archivesMedicalData.Indicators[indicatorId]
+	}
+	return indicators
+}
+
+// 给定问题的编号获取问题的所有的历史记录(倒序排列)
+func (archivesMedicalData *ArchivesMedicalData) GetArchivesDataByQuestionNo(questionSn string) []*sdk.ArchivesValues {
+	var archivesValuesList []*sdk.ArchivesValues = make([]*sdk.ArchivesValues, 0)
+	if len(archivesMedicalData.ArchivesValues[questionSn]) > 0 {
+		archivesValuesList = archivesMedicalData.ArchivesValues[questionSn]
+	}
+	return archivesValuesList
+}

+ 235 - 0
idc/main.go

@@ -0,0 +1,235 @@
+package idc
+
+import (
+	"fmt"
+
+	"github.com/guonaihong/gout"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/utils"
+)
+
+// 同步回调数据中心的转译结果
+func CallbackResult(sn string, dataStr map[string]any) (string, *response.ErrCode) {
+	var resp string
+	resp, err := postReqStr[string]("/idcService/callback/medicalData/result/algor", gout.H{
+		"sn":    sn,
+		"extra": sn,
+		"data":  dataStr,
+		"type":  2,
+	})
+	if err != nil {
+		return "", &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == "" {
+		return "", response.ErrPlatform
+	}
+	return resp, nil
+}
+
+// 获取某个档案的所有数据(指标、档案数据【问题答案】)
+func GetAllValuesByArchivesId(archivesId string) (*sdk.BaseResponse[*sdk.ArchivesMedicalData], *response.ErrCode) {
+	var resp *sdk.BaseResponse[*sdk.ArchivesMedicalData]
+	resp, err := postReq[*sdk.BaseResponse[*sdk.ArchivesMedicalData]]("/idcService/openapi/medicalData/allValuesByArchivesId", gout.H{
+		"archivesId": archivesId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	return resp, nil
+}
+
+// 根据档案编号获取已确认的报告数量
+func TotalMedicalReportChartsByArchivesIds(archivesIds []string) (*sdk.BaseResponse[*sdk.DetailResponse[map[string]*sdk.MedicalReportCharts]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[*sdk.DetailResponse[map[string]*sdk.MedicalReportCharts]]
+	resp, err := postReq[*sdk.BaseResponse[*sdk.DetailResponse[map[string]*sdk.MedicalReportCharts]]]("/idcService/openapi/medicalData/totalChartsByArchivesId", gout.H{
+		"archivesIds": archivesIds,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	return resp, nil
+}
+
+// 创建报告
+func Create(medicalDataForm *sdk.MedicalDataCreateFormByOpenAPI) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/idcService/openapi/medicalData/create", utils.StructToGoutH(medicalDataForm))
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	return resp, nil
+}
+
+// 创建报告
+func UpdateArchives(medicalDataForm *sdk.MedicalDataBindArchivesFormByOpenAPI) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/idcService/openapi/medicalData/update/archives", utils.StructToGoutH(medicalDataForm))
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	return resp, nil
+}
+
+// 获取某个档案最新的一份报告
+func GetLatestMedicalReportByArchivesId(archivesId string) (*sdk.BaseResponse[*sdk.DetailResponse[*sdk.MedicalData]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[*sdk.DetailResponse[*sdk.MedicalData]]
+	resp, err := getReq[*sdk.BaseResponse[*sdk.DetailResponse[*sdk.MedicalData]]]("/idcService/openapi/medicalData/detailByArchivesId", gout.H{
+		"archivesId": archivesId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	return resp, nil
+}
+
+// 获取某个档案的对比报告
+func GetCompareReportByArchivesId(archivesId string) (*sdk.BaseResponse[*sdk.DetailResponse[*sdk.MedicalCompareReport]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[*sdk.DetailResponse[*sdk.MedicalCompareReport]]
+	resp, err := getReq[*sdk.BaseResponse[*sdk.DetailResponse[*sdk.MedicalCompareReport]]]("/idcService/openapi/medicalData/compareReport/detailByArchivesId", gout.H{
+		"archivesId": archivesId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	return resp, nil
+}
+
+// 获取某个档案所有报告的指标数据列表
+func QueryIndicatorDataByParams(queryData *sdk.QueryIDCIndicatorDataQuery) (*sdk.BaseResponse[*sdk.ListResponse[*sdk.MedicalDateTransferResultQueryResultItemBody]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[*sdk.ListResponse[*sdk.MedicalDateTransferResultQueryResultItemBody]]
+	resp, err := postReq[*sdk.BaseResponse[*sdk.ListResponse[*sdk.MedicalDateTransferResultQueryResultItemBody]]]("/idcService/openapi/medicalData/values/query", utils.StructToGoutH(queryData))
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	return resp, nil
+}
+
+// 获取某个档案所有报告的指标数据列表
+func GetArchivesCreatedMapByMemberCardId(memberCardId int64) (*sdk.BaseResponse[map[string]map[string]string], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]map[string]string]
+	resp, err := postReq[*sdk.BaseResponse[map[string]map[string]string]]("/idcService/openapi/medicalData/archivesCreatedMapByMemberCardId", gout.H{
+		"memberCardId": memberCardId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	return resp, nil
+}
+
+// postReq 发送post请求(响应为string的)
+func postReqStr[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.POST(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetJSON(data).
+		BindBody(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}
+
+// postReq 发送post请求
+func postReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.POST(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetJSON(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}
+
+// getReq 发送post请求
+func getReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.GET(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetQuery(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}

+ 617 - 0
idc/main_test.go

@@ -0,0 +1,617 @@
+package idc_test
+
+import (
+	"encoding/json"
+	"fmt"
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/idc"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/utils"
+)
+
+func TestList(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		var jsonStr = `
+{
+    "result":{
+    "assessmentDate":"2023-09-18",
+    "calErr":null,
+    "debugInfo":null,
+    "examDate":1693152000,
+    "majorDisease":[
+        {
+         
+            "name":"乳腺癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["乳腺彩超"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":1,
+            "department":["乳腺外科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":[
+                {
+                    "diseaseRelationName":[
+                        "双侧乳腺囊性占位性病变",
+                        "C-BI-RADS分类:2类"
+                    ],
+                    "itemName":"乳房",
+                    "mark":1,
+                    "value":[
+                        "双侧乳腺囊性占位性病变",
+                        "C-BI-RADS分类:2类"
+                    ]
+                }
+            ],
+            "medDatas":null
+        },
+
+        {
+         
+            "name":"肺癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["胸部CT"],
+            "riskDegree":0,
+            "riskDesc":"无法评估",
+            "classification":1,
+            "department":["呼吸内科"],
+            "followUpTime":"近期",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+
+        {
+         
+            "name":"结直肠癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["肠镜","粪便隐血试验"],
+            "riskDegree":0,
+            "riskDesc":"无法评估",
+            "classification":1,
+            "department":["消化内科"],
+            "followUpTime":"近期",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+
+        {
+         
+            "name":"甲状腺癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["甲状腺功能"],
+            "riskDegree":0,
+            "riskDesc":"无法评估",
+            "classification":1,
+            "department":["内分泌科"],
+            "followUpTime":"近期",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+
+        {
+         
+            "name":"胃癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["胃镜"],
+            "riskDegree":0,
+            "riskDesc":"无法评估",
+            "classification":1,
+            "department":["消化内科"],
+            "followUpTime":"近期",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+
+        {
+         
+            "name":"宫颈癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["TCT检查","HPV检查"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":1,
+            "department":["妇科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":[
+                {
+                    "diseaseRelationName":[
+                        "宫颈潴留囊肿"
+                        
+                    ],
+                    "itemName":"宫颈",
+                    "mark":1,
+                    "value":[
+                        "宫颈潴留囊肿"
+                        
+                    ]
+                }
+            ],
+            "medDatas":null
+        },
+
+        {
+         
+            "name":"肝癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["肝脏彩超/腹部彩超"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":1,
+            "department":["消化内科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+
+        {
+         
+            "name":"子宫内膜癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["子宫附件彩超"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":1,
+            "department":["妇科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"食管癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["食管内镜/胃镜"],
+            "riskDegree":0,
+            "riskDesc":"无法评估",
+            "classification":1,
+            "department":["消化内科"],
+            "followUpTime":"近期",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"卵巢癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["子宫附件彩超"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":1,
+            "department":["妇科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"肾癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["肾脏彩超","尿常规"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":1,
+            "department":["肾内科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"胰腺癌",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["胰腺彩超"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":1,
+            "department":["消化内科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"高血压",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["血压检查","一般检查","同型半胱氨酸检查","心脏彩超"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":3,
+            "department":["心血管内科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+
+        {
+         
+            "name":"血脂异常",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["血脂检查","一般检查"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":3,
+            "department":["心血管内科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"心律失常",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["心电图"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":3,
+            "department":["心血管内科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"慢性阻塞性肺疾病",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["肺功能"],
+            "riskDegree":0,
+            "riskDesc":"无法评估",
+            "classification":3,
+            "department":["呼吸内科"],
+            "followUpTime":"近期",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"慢性胃炎",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["胃镜","幽门螺杆菌检查","胃蛋白酶原I","胃蛋白酶原II","胃蛋白酶原比值","胃泌素17"],
+            "riskDegree":0,
+            "riskDesc":"无法评估",
+            "classification":3,
+            "department":["消化内科"],
+            "followUpTime":"近期",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"慢性乙型病毒性肝炎",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["乙肝两对半"],
+            "riskDegree":0,
+            "riskDesc":"无法评估",
+            "classification":3,
+            "department":["消化内科"],
+            "followUpTime":"近期",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+
+        {
+         
+            "name":"肝硬化",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["乙肝两对半","乙肝DNA定量检测","甲胎蛋白","肝脏彩超","肝功能"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":3,
+            "department":["消化内科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"糖尿病",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["糖化血红蛋白","糖化血清蛋白","餐后血糖","尿常规"],
+            "riskDegree":0,
+            "riskDesc":"无法评估",
+            "classification":3,
+            "department":["内分泌科"],
+            "followUpTime":"近期",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"肾功能损伤",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["肾功能检查","尿微量白蛋白","肾脏彩超","尿常规"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":3,
+            "department":["肾内科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"骨质疏松",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["骨密度检查"],
+            "riskDegree":0,
+            "riskDesc":"无法评估",
+            "classification":3,
+            "department":["内分泌科"],
+            "followUpTime":"近期",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"冠心病",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["血压检查","血脂检查","空腹血糖检查","糖化血清蛋白","糖化血红蛋白","颈动脉彩超"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":2,
+            "department":["心血管内科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        },
+        {
+         
+            "name":"脑卒中",
+            "nodeId":"4:b8fbfa26-3437-4bbb-8349-96abd14851ea:633",
+            "notificationTime":"365",
+            "recommendItems":["血压检查","血脂检查","空腹血糖检查","颈动脉彩超","颅脑CT","颅脑MRI"],
+            "riskDegree":1,
+            "riskDesc":"低风险",
+            "classification":2,
+            "department":["心血管内科"],
+            "followUpTime":"每年",
+            "abnormalDatas":null,
+            "knownFactors":null,
+            "medDatas":null
+        }
+        
+       
+    ],
+    "reportConfig":{
+        "reportCancerCfg":{
+            "sectionContent":[
+                {
+                    "note":"",
+                    "rank":1,
+                    "title":"您的疾病与主要风险因素"
+                },
+                {
+                    "note":"",
+                    "rank":2,
+                    "title":"疾病风险评估及建议"
+                },
+                {
+                    "note":"",
+                    "rank":3,
+                    "title":"该板块疾病主要风险因素及建议"
+                },
+                {
+                    "note":"",
+                    "rank":4,
+                    "title":"相关数据结果汇总"
+                }
+            ],
+            "sectionName":"肿瘤风险评估"
+        },
+        "reportCardiovascularCfg":{
+            "sectionContent":[
+                {
+                    "note":"",
+                    "rank":1,
+                    "title":"您的疾病与主要风险因素"
+                },
+                {
+                    "note":"",
+                    "rank":2,
+                    "title":"疾病风险评估及建议"
+                },
+                {
+                    "note":"",
+                    "rank":3,
+                    "title":"该板块疾病主要风险因素及建议"
+                },
+                {
+                    "note":"",
+                    "rank":4,
+                    "title":"相关数据结果汇总"
+                }
+            ],
+            "sectionName":"急性心脑血管事件风险评估"
+        },
+        "reportPersonaliseCfg":{
+            "sectionContent":[
+                {
+                    "note":"",
+                    "rank":2,
+                    "title":"疾病风险评估及建议"
+                },
+                {
+                    "note":"",
+                    "rank":3,
+                    "title":"该板块疾病主要风险因素及建议"
+                },
+                {
+                    "note":"",
+                    "rank":4,
+                    "title":"相关数据结果汇总"
+                }
+            ],
+            "sectionName":"个性化疾病风险评估"
+        },
+        "reportPreviewCfg":{
+            "sectionContent":[
+                {
+                    "note":"本版块的疾病需要您高度重视,因为他们已经开始或者很快就会开始对您的身体造成严重的伤害,需要您尽快至医院治疗,减少伤害,降低经济损失。注意,进一步的检查项目有助于更详细的知晓您的身体状况,更准确的评估疾病的风险。",
+                    "rank":1,
+                    "title":"建议立即或尽快就医"
+                },
+                {
+                    "note":"本版块的疾病需要您密切关注,某些风险因素需要您按照医生建议定期复查,监测他们的变化趋势,同时也要对不良的生化习惯进行调整,降低疾病的发生概率。注意,进一步的检查项目有助于更详细的知晓您的身体状况,更准确的评估疾病的风险。",
+                    "rank":2,
+                    "title":"建议近期就医"
+                },
+                {
+                    "note":"以下内容是基于您上传的数据整理出的复查建议,请您定期复查,监测您的风险因素变化或者对低风险疾病进行定期复查",
+                    "rank":3,
+                    "title":"您的复查建议"
+                }
+            ],
+            "sectionName":"重大疾病风险概览"
+        }
+    },
+    "userInfo":{
+        "currentAge":"",
+        "examAge":"38",
+        "gender":"女",
+        "name":"匿名用户"
+    }
+},
+"type":2
+}`
+		var requestJson map[string]any
+		json.Unmarshal([]byte(jsonStr), &requestJson)
+		fmt.Println(requestJson)
+		response, err := idc.CallbackResult("20230828000004", requestJson)
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("推送结果: %v", response)
+	})
+}
+
+func TestGetAllValues(t *testing.T) {
+	sdk.InitConfig(&sdk.ClientConfig{
+		ApiDomain: "https://mcapi.mdfitnesscao.com",
+		AppDebug:  true,
+	})
+	m, err := idc.GetMedicalData("Ydm62mB8")
+	fmt.Println(utils.JsonEncode(m), err)
+	// r := m.GetArchivesDataByIndicatorId("4:b8fbfa26-3437-4bbb-8349-96abd14851ea:830")
+	// fmt.Println(utils.JsonEncode(r))
+	// s := m.GetArchivesDataByQuestionNo("QUshijianxuanze")
+	// fmt.Println(utils.JsonEncode(s))
+}
+
+func TestTotalConfirmByArchivesIds(t *testing.T) {
+	sdk.InitConfig(&sdk.ClientConfig{
+		ApiDomain: "https://mcapi.mdfitnesscao.com",
+		AppDebug:  true,
+	})
+	m, err := idc.TotalMedicalReportChartsByArchivesIds([]string{"Ydm62mB8", "WNm0dm07", "111"})
+	fmt.Println(utils.JsonEncode(m), err)
+	// r := m.GetArchivesDataByIndicatorId("4:b8fbfa26-3437-4bbb-8349-96abd14851ea:830")
+	// fmt.Println(utils.JsonEncode(r))
+	// s := m.GetArchivesDataByQuestionNo("QUshijianxuanze")
+	// fmt.Println(utils.JsonEncode(s))
+}
+
+func TestGetLatestMedicalReportByArchivesId(t *testing.T) {
+	sdk.InitConfig(&sdk.ClientConfig{
+		ApiDomain: "https://mcapi.mdfitnesscao.com",
+		AppDebug:  true,
+	})
+	m, err := idc.GetLatestMedicalReportByArchivesId("GdJGwYJK")
+	fmt.Println(utils.JsonEncode(m), err)
+}
+
+func TestGetCompareReportByArchivesId(t *testing.T) {
+	sdk.InitConfig(&sdk.ClientConfig{
+		ApiDomain: "https://mcapi.mdfitnesscao.com",
+		AppDebug:  true,
+	})
+	m, _ := idc.GetCompareReportByArchivesId("GdJGwYJK")
+	fmt.Println(utils.JsonEncode(m))
+}
+
+func TestUpdateArchives(t *testing.T) {
+	sdk.InitConfig(&sdk.ClientConfig{
+		ApiDomain: "https://mcapi.mdfitnesscao.com",
+		AppDebug:  true,
+	})
+	m, _ := idc.UpdateArchives(&sdk.MedicalDataBindArchivesFormByOpenAPI{
+		ArchivesId:    "DRzxXazy",
+		MedicalDataId: "2024031400040010",
+		MechanismId:   "Xwlg97rP",
+	})
+	fmt.Println(utils.JsonEncode(m), "23")
+}
+
+func TestQueryIndicatorDataByParams(t *testing.T) {
+	sdk.InitConfig(&sdk.ClientConfig{
+		ApiDomain: "https://mcapi.mdfitnesscao.com",
+		AppDebug:  true,
+	})
+	m, _ := idc.QueryIndicatorDataByParams(&sdk.QueryIDCIndicatorDataQuery{
+		ArchivesId: "DRzxXazy",
+		QueryData: []*sdk.QueryIDCIndicatorDataQueryData{
+			{
+				BodyDataId: "4:b8fbfa26-3437-4bbb-8349-96abd14851ea:1142",
+			},
+		},
+	})
+	fmt.Println(utils.JsonEncode(m), "23")
+}
+
+func TestGetArchivesCreatedMapByMemberCardId(t *testing.T) {
+	sdk.InitConfig(&sdk.ClientConfig{
+		ApiDomain: "https://mcapi.mdfitnesscao.com",
+		AppDebug:  true,
+	})
+	m, _ := idc.GetArchivesCreatedMapByMemberCardId(1)
+	fmt.Println(utils.JsonEncode(m), "23")
+}

+ 19 - 0
mechanism/helper.go

@@ -0,0 +1,19 @@
+package mechanism
+
+import (
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+)
+
+// 通过ID列表获取机构列表
+func ListMechanismByIds(mechanismIds []string) ([]*sdk.Mechanism, *response.ErrCode) {
+	var mechanisms = make([]*sdk.Mechanism, 0)
+	if len(mechanismIds) == 0 {
+		return mechanisms, nil
+	}
+	resp, responseErr := ListMechanism(mechanismIds)
+	if responseErr == nil && len(resp.Data.List) > 0 {
+		mechanisms = resp.Data.List
+	}
+	return mechanisms, responseErr
+}

+ 126 - 0
mechanism/main.go

@@ -0,0 +1,126 @@
+package mechanism
+
+import (
+	"fmt"
+
+	"github.com/guonaihong/gout"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+)
+
+// 获取机构列表
+func GetAuthMechanism(mechanismId, staffId string) (*sdk.BaseResponse[sdk.DetailResponse[*sdk.AuthMechanism]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.DetailResponse[*sdk.AuthMechanism]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.DetailResponse[*sdk.AuthMechanism]]]("/mechanismService/openapi/mechanism/getAuthMechanism", gout.H{
+		"mechanismId": mechanismId,
+		"staffId":     staffId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取机构列表
+func ListMechanism(ids []string) (*sdk.BaseResponse[sdk.ListResponse[*sdk.Mechanism]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[*sdk.Mechanism]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.ListResponse[*sdk.Mechanism]]]("/mechanismService/openapi/mechanism/listByIds", gout.H{
+		"mechanismIds": ids,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取机构列表
+func ListMechanismList() (*sdk.BaseResponse[sdk.ListResponse[*sdk.Mechanism]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[*sdk.Mechanism]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.ListResponse[*sdk.Mechanism]]]("/mechanismService/openapi/mechanism/list", gout.H{})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 通过AppKey获取机构信息
+func DetailByAppKey(appKey string) (*sdk.BaseResponse[sdk.DetailResponse[*sdk.Mechanism]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.DetailResponse[*sdk.Mechanism]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.DetailResponse[*sdk.Mechanism]]]("/mechanismService/openapi/mechanism/detailByAppKey", gout.H{
+		"appKey": appKey,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// postReq 发送post请求
+func postReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.POST(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetJSON(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}

+ 20 - 0
mechanism/main_test.go

@@ -0,0 +1,20 @@
+package mechanism_test
+
+import (
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/mechanism"
+)
+
+func TestList(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		response, err := mechanism.ListMechanism([]string{
+			"M57wVRNZ",
+		})
+		list := response.Data.List
+		if err != nil {
+			t.Errorf("err: %v", err)
+		}
+		t.Logf("list: %d", len(list))
+	})
+}

+ 80 - 0
pdf_template/main.go

@@ -0,0 +1,80 @@
+package pdf_template
+
+import (
+	"fmt"
+
+	"github.com/guonaihong/gout"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+)
+
+// 获取模板列表
+func ListByIds(ids []int64) (*sdk.BaseResponse[sdk.ListResponse[*sdk.PdfTemplate]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[*sdk.PdfTemplate]]
+	resp, err := getReq[*sdk.BaseResponse[sdk.ListResponse[*sdk.PdfTemplate]]]("/pdfTemplateService/openapi/pdfTemplate/list", gout.H{
+		"ids[]": ids,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 通过机构编号获取模板列表
+func ListByMechanismId(mechanismId string, authorizeType int64) (*sdk.BaseResponse[sdk.ListResponse[*sdk.PdfTemplateMechanism]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.ListResponse[*sdk.PdfTemplateMechanism]]
+	resp, err := getReq[*sdk.BaseResponse[sdk.ListResponse[*sdk.PdfTemplateMechanism]]]("/pdfTemplateService/openapi/pdfTemplateMechanism/list", gout.H{
+		"mechanismId": mechanismId,
+		"type":        authorizeType,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// postReq 发送post请求
+func getReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.GET(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetQuery(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}

+ 22 - 0
pdf_template/main_test.go

@@ -0,0 +1,22 @@
+package pdf_template_test
+
+import (
+	"fmt"
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/pdf_template"
+)
+
+func TestList(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		// pdfTemplates, err := pdf_template.ListByIds([]int64{15, 16})
+		// fmt.Println(pdfTemplates, err)
+		pdfTemplates, err := pdf_template.ListByMechanismId("M57wVRNZ", 1)
+		fmt.Println(pdfTemplates, err)
+	})
+}

+ 63 - 0
response/errcode.go

@@ -0,0 +1,63 @@
+package response
+
+type ErrCode struct {
+	Code int
+	Msg  string
+}
+
+const (
+	SUCCESS               = 200
+	AUTHORIZATION_EXPIRED = 401
+	INVALID_TOKEN         = 403
+	NOT_FOUND             = 404
+	ERROR                 = 500
+
+	PLATFORM_ERROR         = 1001 // 第三方错误
+	REDIS_ERROR            = 1002 // 缓存错误
+	VALIDATOR_ERROR        = 1003 // validator校验器错误
+	DEBUG_ERROR            = 1004 // DEBUG的错误信息
+	DB_ERROR               = 1005 // DB异常
+	PERMISSION_NOT_ALLOWED = 1006
+	DATA_NOT_FOUND         = 9000
+	NEED_REGIST            = 9001
+	SIGN_ERROR             = 9002
+	ACCOUNT_FORBID         = 9003
+
+	USER_MOBILE_NOT_BIND = 10002
+)
+
+var ErrorCodeMessage = map[int]string{
+	SUCCESS:                "操作成功",
+	ERROR:                  "服务器异常",
+	NOT_FOUND:              "无操作权限",
+	AUTHORIZATION_EXPIRED:  "凭证已失效,请重新登录",
+	INVALID_TOKEN:          "凭证无效,请重新登录",
+	PLATFORM_ERROR:         "第三方调用异常",
+	REDIS_ERROR:            "服务器异常[1002]",
+	VALIDATOR_ERROR:        "参数输入错误,请仔细检查",
+	DEBUG_ERROR:            "服务器异常",
+	DB_ERROR:               "服务器异常[1005]",
+	PERMISSION_NOT_ALLOWED: "您没有权限进行该操作",
+	DATA_NOT_FOUND:         "该项不存在",
+	NEED_REGIST:            "服务人员不存在,请先补充资料",
+	SIGN_ERROR:             "签名错误",
+	ACCOUNT_FORBID:         "您的账号已被禁用",
+}
+
+var (
+	ErrSuccess              = &ErrCode{Code: SUCCESS, Msg: ErrorCodeMessage[SUCCESS]}
+	Err                     = &ErrCode{Code: ERROR, Msg: ErrorCodeMessage[ERROR]}
+	ErrNotFound             = &ErrCode{Code: NOT_FOUND, Msg: ErrorCodeMessage[NOT_FOUND]}
+	ErrAuthorizationExpired = &ErrCode{Code: AUTHORIZATION_EXPIRED, Msg: ErrorCodeMessage[AUTHORIZATION_EXPIRED]}
+	ErrInvalidToken         = &ErrCode{Code: INVALID_TOKEN, Msg: ErrorCodeMessage[INVALID_TOKEN]}
+	ErrPlatform             = &ErrCode{Code: PLATFORM_ERROR, Msg: ErrorCodeMessage[PLATFORM_ERROR]}
+	ErrRedis                = &ErrCode{Code: REDIS_ERROR, Msg: ErrorCodeMessage[REDIS_ERROR]}
+	ErrValidator            = &ErrCode{Code: VALIDATOR_ERROR, Msg: ErrorCodeMessage[VALIDATOR_ERROR]}
+	ErrDebug                = &ErrCode{Code: DEBUG_ERROR, Msg: ErrorCodeMessage[DEBUG_ERROR]}
+	ErrDatabase             = &ErrCode{Code: DB_ERROR, Msg: ErrorCodeMessage[DB_ERROR]}
+	ErrPermissionNotAllowed = &ErrCode{Code: PERMISSION_NOT_ALLOWED, Msg: ErrorCodeMessage[PERMISSION_NOT_ALLOWED]}
+	ErrDataNotFound         = &ErrCode{Code: DATA_NOT_FOUND, Msg: ErrorCodeMessage[DATA_NOT_FOUND]}
+	ErrNeedRegist           = &ErrCode{Code: NEED_REGIST, Msg: ErrorCodeMessage[NEED_REGIST]}
+	ErrSign                 = &ErrCode{Code: SIGN_ERROR, Msg: ErrorCodeMessage[SIGN_ERROR]}
+	ErrAccountForbid        = &ErrCode{Code: ACCOUNT_FORBID, Msg: ErrorCodeMessage[ACCOUNT_FORBID]}
+)

+ 23 - 0
response/response.go

@@ -0,0 +1,23 @@
+package response
+
+type JSONResult[T any] struct {
+	Code int    `json:"code"`
+	Msg  string `json:"message"`
+	Data T      `json:"data"`
+}
+type ListResponse[T any] struct {
+	List []*T `json:"list"`
+}
+type PaginateResponse[T any] struct {
+	List  []*T `json:"list"`
+	Total int  `json:"total"`
+}
+type OffsetResponse[T any] struct {
+	List   []*T `json:"list"`
+	Offset any  `json:"offset"`
+}
+type OffsetTotalResponse[T any] struct {
+	List   []*T  `json:"list"`
+	Total  int64 `json:"total"`
+	Offset any   `json:"offset"`
+}

+ 770 - 0
structs.go

@@ -0,0 +1,770 @@
+package sdk
+
+type ClientConfig struct {
+	ApiDomain      string // API域名
+	AppDebug       bool   // 是否开启调试模式
+	AlgorApiDomain string // Algor API域名
+}
+
+type BaseResponse[T any] struct {
+	Code    int    `json:"code"`
+	Data    T      `json:"data"`
+	Message string `json:"message"`
+	Success bool   `json:"success"`
+}
+
+type ListResponse[T any] struct {
+	List []T `json:"list"`
+}
+
+type PaginateResponse[T any] struct {
+	List  []T   `json:"list"`
+	Total int64 `json:"total"`
+}
+type PaginateTotalSumResponse[T any] struct {
+	List     []T   `json:"list"`
+	Total    int64 `json:"total"`
+	TotalSum int64 `json:"totalSum"`
+}
+type DetailResponse[T any] struct {
+	Detail T `json:"detail"`
+}
+type FormFieldsResponse[T any] struct {
+	FormFields T `json:"formFields"`
+}
+
+type Tag struct {
+	ID            string            `json:"id" form:"id" binding:"omitempty"`
+	Name          string            `json:"name" form:"name" binding:"required,max=20"`
+	VisibleConfig *TagVisibleConfig `json:"visibleConfig" form:"visibleConfig" binding:"omitempty,required_if=Type 2"`
+	Type          int               `json:"type" form:"type" binding:"required"`
+	CategoryId    string            `json:"categoryId" form:"categoryId" binding:"required"`
+	Category      *TagCategory      `json:"tagCategory" form:"-" binding:"-"`
+	CreatedAt     string            `json:"createdAt" form:"-" binding:"-"`
+	UpdatedAt     string            `json:"updatedAt" form:"-" binding:"-"`
+}
+
+type TagVisibleConfig struct {
+	Gender     int   `json:"gender" form:"gender" binding:"omitempty,oneof=0 1 2"` // 性别,0:全部,1:男,2:女
+	StartAge   int64 `json:"startAge" form:"startAge" binding:"omitempty,number,gte=0"`
+	StartMonth int64 `json:"startMonth" form:"startMonth" binding:"omitempty,number,gte=0"`
+	StartDay   int64 `json:"startDay" form:"startDay" binding:"omitempty,number,gte=0"`
+	EndAge     int64 `json:"endAge" form:"endAge" binding:"omitempty,number,gte=0"`
+	EndMonth   int64 `json:"endMonth" form:"endMonth" binding:"omitempty,number,gte=0"`
+	EndDay     int64 `json:"endDay" form:"endDay" binding:"omitempty,number,gte=0"`
+	AgeType    int64 `json:"ageType" form:"ageType" binding:"required,oneof=1 2 3"`
+}
+
+type Mechanism struct {
+	ID                   string   `json:"id" form:"-" binding:"-"`
+	Account              string   `json:"account" form:"account" binding:"required_unless=ID 0,omitempty,alphanum,min=4,max=20"`
+	Nickname             string   `json:"nickname" form:"nickname" binding:"required"`
+	Status               int      `json:"status" form:"status" binding:"omitempty,oneof=1 2"`
+	Permissions          []string `json:"permissions" form:"-" binding:"-"`
+	Remark               string   `json:"remark" form:"remark" binding:"omitempty,max=255"`
+	DefaultWebTemplateId string   `json:"defaultWebTemplateId" form:"defaultWebTemplateId" binding:"required"`
+	RawId                int64    `json:"rawId" form:"-" binding:"-"`
+	AppKey               string   `json:"appKey" form:"-" binding:"-"`
+	AppSecret            string   `json:"appSecret" form:"-" binding:"-"`
+	IpWhiteList          string   `json:"ipWhiteList" form:"-" binding:"-"`
+	CallbackUrlList      string   `json:"callbackUrlList" form:"-" binding:"-"`
+	MemberCanRegist      bool     `json:"memberCanRegist" form:"memberCanRegist" binding:"omitempty"`
+	Logo                 string   `json:"logo" form:"logo" binding:"omitempty"`
+	SmsSignName          string   `json:"smsSignName" form:"smsSignName" binding:"omitempty"`
+	SmsTemplateCode      string   `json:"smsTemplateCode" form:"smsTemplateCode" binding:"omitempty"`
+}
+
+type Form struct {
+	ID        string       `json:"id" form:"id" binding:"omitempty"`         // 编号
+	Name      string       `json:"name" form:"name" binding:"required"`      // 名称
+	Icon      string       `json:"icon" form:"icon" binding:"omitempty,url"` // 图标
+	TagIds    []string     `json:"tagIds" form:"tagIds" binding:"omitempty"` // 标签ID列表
+	Tags      []*Tag       `json:"tags" form:"tags" binding:"omitempty"`     // 标签
+	Remark    string       `json:"remark" form:"remark" binding:"omitempty"` // 备注
+	Fields    []*FormField `json:"fields" form:"-" binding:"-"`              // 字段列表
+	CreatedAt string       `json:"createdAt" form:"-" binding:"-"`           // 创建时间
+	UpdatedAt string       `json:"updatedAt" form:"-" binding:"-"`           // 更新时间
+}
+
+type FormField struct {
+	ID          int64        `json:"id" form:"id" binding:"omitempty"`                                   // 编号
+	FormId      string       `json:"formId" form:"formId" binding:"required"`                            // 表单编号
+	Name        string       `json:"name" form:"name" binding:"omitempty,required_if=Type 1"`            // 名称
+	Type        int          `json:"type" form:"type" binding:"required"`                                // 类型
+	ExtraId     string       `json:"extraId" form:"extraId" binding:"omitempty,required_without=Type 1"` // 数据ID
+	Extra       any          `json:"extra" form:"-" binding:"-"`                                         // 数据
+	TagIds      []string     `json:"tagIds" form:"tagIds" binding:"omitempty"`                           // 标签ID列表
+	Tags        []*Tag       `json:"tags" form:"tags" binding:"omitempty"`                               // 标签
+	Remark      string       `json:"remark" form:"remark" binding:"omitempty"`                           // 备注
+	ParentId    int64        `json:"parentId" form:"parentId" binding:"omitempty"`                       // 父级编号
+	Parent      *FormField   `json:"parent" form:"-" binding:"-"`                                        // 父级
+	Fields      []*FormField `json:"fields" form:"-" binding:"-"`                                        // 子级列表
+	CheckItemId string       `json:"checkItemId" form:"checkItemId" binding:"omitempty"`                 // 检查项ID
+	CreatedAt   string       `json:"createdAt" form:"-" binding:"-"`                                     // 创建时间
+	UpdatedAt   string       `json:"updatedAt" form:"-" binding:"-"`                                     // 更新时间
+}
+
+type FormCustomField struct {
+	Type int    `json:"type" binding:"required"`
+	Key  string `json:"key" binding:"required"`
+}
+
+// 知识图谱节点
+type GraphNode struct {
+	ID         string   `json:"id"`
+	Labels     []string `json:"labels"`
+	Properties struct {
+		CreatedAt float64  `json:"createdAt"`
+		Aliases   []string `json:"aliases"`
+		Name      string   `json:"name"`
+		UUID      string   `json:"uuid"`
+		Tags      []string `json:"tags"`
+		Props     string   `json:"props"`
+	} `json:"properties"`
+}
+
+const (
+	IndicatorQuestionSubjectPrefix = "b8fbfa26.indicator" // 指标题目前缀
+	IndicatorValueFlag             = "value"              // 检查结果
+	IndicatorRangeFlag             = "range"              // 范围
+	IndicatorUnitFlag              = "unit"               // 单位
+	IndicatorTimeFlag              = "time"               // 检查时间
+	IndicatorCheckItemIdFlag       = "checkItemId"        // 检查项目ID
+)
+
+const (
+	QuestionSubjectTypeRadio          = 1 // 单选题
+	QuestionSubjectTypeCheckbox       = 2 // 多选题
+	QuestionSubjectTypeInput          = 3 // 单行文本题
+	QuestionSubjectTypeMatrixCheckbox = 4 // 矩阵多选题
+	QuestionSubjectTypeDate           = 5 // 日期选择题
+	QuestionSubjectTypeGroup          = 6 // 组合题
+
+	QuestionSubjectTypeInputFlag          = "input"           // 单行文本题
+	QuestionSubjectTypeRadioFlag          = "radio"           // 单选题
+	QuestionSubjectTypeCheckboxFlag       = "checkbox"        // 多选题
+	QuestionSubjectTypeMatrixCheckboxFlag = "matrix_checkbox" // 矩阵多选题
+	QuestionSubjectTypeDateFlag           = "date"            // 日期选择题
+	QuestionSubjectTypeGroupFlag          = "group"           // 组合题
+)
+
+// 问题库
+type QuestionnaireSubject struct {
+	ID           int64                              `json:"id" form:"id"`
+	SN           string                             `json:"sn" form:"sn"`
+	Type         int                                `json:"type" form:"type"`
+	Title        string                             `json:"title" form:"title"`
+	Validator    string                             `json:"validator" form:"validator"`
+	Remark       string                             `json:"remark" form:"remark"`
+	Mark         string                             `json:"mark" form:"mark"`
+	CreatedAt    string                             `json:"createdAt" form:"-"`
+	SelectValues []*QuestionnaireSubjectSelectValue `json:"selectValues" form:"-"`
+}
+
+type QuestionnaireSubjectSelectValue struct {
+	Label string `json:"label" form:"label"`
+	Value string `json:"value" form:"value"`
+}
+
+// 问题模板
+type QuestionnaireTemplate struct {
+	ID           int64                   `json:"id" form:"id"`
+	SN           string                  `json:"sn" form:"sn"`
+	Title        string                  `json:"title" form:"title"`
+	Peg          string                  `json:"peg" form:"peg"`
+	SubjectTotal int                     `json:"subjectTotal" form:"-"` // 关联的题目数
+	SubjectIds   []string                `json:"subjectIds" form:"-"`   // 关联的题目ID列表
+	Subjects     []*QuestionnaireSubject `json:"subjects" form:"-"`     // 关联的题目列表
+	CreatedAt    string                  `json:"createdAt" form:"-"`
+}
+
+type Province struct {
+	ID    string  `json:"id" binding:"required"`
+	Name  string  `json:"name" binding:"required"`
+	Citys []*City `json:"citys" binding:"-"`
+}
+
+type City struct {
+	ID         string    `json:"id" binding:"required"`
+	Name       string    `json:"name" binding:"required"`
+	ProvinceId string    `json:"provinceId" binding:"required"`
+	Countys    []*County `json:"countys" binding:"-"`
+}
+
+type County struct {
+	ID     string `json:"id" binding:"required"`
+	Name   string `json:"name" binding:"required"`
+	CityId string `json:"cityId" binding:"required"`
+}
+
+type Archives struct {
+	ID                        string                 `json:"id" form:"id" binding:"omitempty"`
+	Name                      string                 `json:"name" form:"name" binding:"required_without=ID,omitempty"`
+	Avatar                    string                 `json:"avatar" form:"avatar" binding:"omitempty"`
+	Gender                    int                    `json:"gender" form:"gender" binding:"required_without=ID,omitempty"`
+	Birthday                  string                 `json:"birthday" form:"birthday" binding:"required_without=ID,omitempty"`
+	RegisterAddress           string                 `json:"registerAddress" form:"registerAddress" binding:"omitempty"`
+	EmergencyContactName      string                 `json:"emergencyContactName" form:"emergencyContactName" binding:"omitempty"`
+	EmergencyContactPhone     string                 `json:"emergencyContactPhone" form:"emergencyContactPhone" binding:"omitempty"`
+	Address                   string                 `json:"address" form:"address" binding:"omitempty"`
+	Province                  string                 `json:"province" form:"province" binding:"omitempty"`
+	ProvinceText              string                 `json:"provinceText" form:"-" binding:"-"`
+	City                      string                 `json:"city" form:"city" binding:"omitempty"`
+	CityText                  string                 `json:"cityText" form:"-" binding:"-"`
+	Area                      string                 `json:"area" form:"area" binding:"omitempty"`
+	AreaText                  string                 `json:"areaText" form:"-" binding:"-"`
+	SubDistrict               string                 `json:"subDistrict" form:"subDistrict" binding:"omitempty"`
+	Community                 string                 `json:"community" form:"community" binding:"omitempty"`
+	Village                   string                 `json:"village" form:"village" binding:"omitempty"`
+	Building                  string                 `json:"building" form:"building" binding:"omitempty"`
+	HouseNumber               string                 `json:"houseNumber" form:"houseNumber" binding:"omitempty"`
+	MainArchivesId            string                 `json:"mainArchivesId" form:"mainArchivesId" binding:"omitempty"` // 主档案编号
+	ArchivesRelation          int                    `json:"archivesRelation" form:"archivesRelation" binding:"omitempty"`
+	ArchivesRelationText      string                 `json:"archivesRelationText" form:"-" binding:"-"`
+	CreatedAt                 string                 `json:"createdAt" form:"-" binding:"-"`
+	UpdatedAt                 string                 `json:"updatedAt" form:"-" binding:"-"`
+	DepartmentId              int64                  `json:"departmentId" form:"departmentId" binding:"omitempty"`
+	DepartmentName            string                 `json:"departmentName" form:"departmentName" binding:"omitempty"`
+	ParentDepartmentName      string                 `json:"parentDepartmentName" form:"parentDepartmentName" binding:"omitempty"`
+	AssociatArchives          []*Archives            `json:"associatArchives" form:"-" binding:"-"`
+	Tags                      []*Tag                 `json:"tags" form:"-" binding:"-"`
+	Accounts                  []*Account             `json:"accounts" form:"accounts" binding:"required_without=ID,dive"`
+	IsCompletePassword        bool                   `json:"isCompletePassword" form:"-" binding:"-"`
+	IsCompleteInfo            bool                   `json:"isCompleteInfo" form:"-" binding:"-"`
+	MedicalReportConfirmTotal *MedicalReportCharts   `json:"medicalReportConfirmTotal" form:"-" binding:"-"`                 // 已确认的报告数量
+	CreateMechanismId         string                 `json:"createMechanismId" form:"createMechanismId" binding:"omitempty"` // 注册档案机构ID
+	HasArchivesReport         bool                   `json:"hasArchivesReport" form:"hasArchivesReport" binding:"omitempty"` // 是否有档案报告
+	ArchivesChannels          []*ArchivesChannelInfo `json:"archivesChannels" form:"archivesChannels" binding:"omitempty"`
+}
+
+type ArchivesAttachForm struct {
+	ChannelId int64 `json:"channelId" form:"channelId" binding:"omitempty"`
+	// DepartmentName       string `json:"departmentName" form:"departmentName" binding:"omitempty"`
+	// ParentDepartmentName string `json:"parentDepartmentName" form:"parentDepartmentName" binding:"omitempty"`
+}
+
+type ArchivesChannelInfo struct {
+	ID             int64  `json:"id" form:"id" binding:"omitempty"`
+	Name           string `json:"name" form:"name" binding:"omitempty"`
+	DepartmentId   int64  `json:"departmentId" form:"departmentId" binding:"omitempty"`
+	DepartmentName string `json:"departmentName" form:"departmentName" binding:"omitempty"`
+	CreatedAt      string `json:"createdAt" form:"-" binding:"-"`
+}
+type Account struct {
+	Account   string `json:"account" form:"account" binding:"required"`
+	Type      int    `json:"type" form:"type" binding:"required"`
+	Code      string `json:"code" form:"code" binding:"omitempty"`
+	IsValid   bool   `json:"isValid" form:"-" binding:"-"`
+	CreatedAt string `json:"createdAt" form:"-" binding:"-"`
+	UpdatedAt string `json:"updatedAt" form:"-" binding:"-"`
+}
+
+type ArchivesMedicalData struct {
+	LastUpdatedAt  string                       `json:"lastUpdatedAt"`  // 最后更新时间
+	Indicators     map[string][]*Indicator      `json:"indicators"`     // 指标数据
+	ArchivesValues map[string][]*ArchivesValues `json:"archivesValues"` // 档案数据(问卷答案)
+}
+
+type ArchivesValues struct {
+	ExtraType    int           `json:"extraType"` // 数据类型
+	UpdatedAt    string        `json:"updatedAt"`
+	ReturnAnswer *SurveyAnswer `json:"returnAnswer"`
+	Answer       *SurveyAnswer `json:"answer"` // 请求时要传这个
+}
+
+type ArchivesPaginateQuery struct {
+	Page                  int      `json:"page" form:"page" binding:"omitempty"`
+	PageSize              int      `json:"pageSize" form:"pageSize" binding:"omitempty"`
+	Name                  string   `json:"name" form:"name" binding:"omitempty"`
+	Gender                int      `json:"gender" form:"gender" binding:"omitempty"`
+	ArchivesId            string   `json:"archivesId" form:"archivesId" binding:"omitempty"`
+	Phone                 string   `json:"phone" form:"phone" binding:"omitempty"`
+	IdCard                string   `json:"idCard" form:"idCard" binding:"omitempty"`
+	Account               string   `json:"account" form:"account" binding:"omitempty"`
+	RegistMechanismId     string   `json:"registMechanismId" form:"registMechanismId" binding:"omitempty"`
+	ProvinceId            string   `json:"provinceId" form:"provinceId" binding:"omitempty"`
+	CityId                string   `json:"cityId" form:"cityId" binding:"omitempty"`
+	AreaId                string   `json:"areaId" form:"areaId" binding:"omitempty"`
+	SubDistrict           string   `json:"subDistrict" form:"subDistrict" binding:"omitempty"`
+	Community             string   `json:"community" form:"community" binding:"omitempty"`
+	SubDistricts          []string `json:"subDistricts" form:"subDistricts" binding:"omitempty"`
+	Communities           []string `json:"communities" form:"communities" binding:"omitempty"`
+	TagIds                []string `json:"tagIds[]" form:"tagIds[]" binding:"omitempty"`
+	TagIdList             []string `json:"tagIdList" form:"tagIdList" binding:"omitempty"`
+	Keyword               string   `json:"keyword" form:"keyword" binding:"omitempty"`                             // 聚合搜索
+	CreatedStartDate      string   `json:"createdStartDate" form:"createdStartDate" binding:"omitempty"`           // 建档开始时间
+	CreatedEndDate        string   `json:"createdEndDate" form:"createdEndDate" binding:"omitempty"`               // 建档结束时间
+	NeedSubArchives       int64    `json:"needSubArchives" form:"needSubArchives" binding:"omitempty"`             // 是否需要子档案
+	InDepartment          int64    `json:"inDepartment" form:"inDepartment" binding:"omitempty"`                   // 是否在部门中
+	DepartmentId          int64    `json:"departmentId" form:"departmentId" binding:"omitempty"`                   // 部门ID
+	ArchivesValuesDataIds []string `json:"archivesValuesDataIds" form:"archivesValuesDataIds" binding:"omitempty"` // 档案值数据ID
+	AgeStart              int64    `json:"ageStart" form:"ageStart" binding:"omitempty"`                           // 年龄开始
+	AgeEnd                int64    `json:"ageEnd" form:"ageEnd" binding:"omitempty"`                               // 年龄结束
+	HasArchivesReport     int64    `json:"hasArchivesReport" form:"hasArchivesReport" binding:"omitempty"`         // 是否有档案报告
+	ChannelId             int64    `json:"channelId" form:"channelId" binding:"omitempty"`                         // 渠道ID
+	ChannelIds            string   `json:"channelIds" form:"channelIds" binding:"omitempty"`                       // 渠道ID列表
+}
+
+type FormAnswer struct {
+	ExtraType    int            `json:"extraType" form:"extraType" binding:"required"` // 数据类型
+	Answer       *SurveyAnswer  `json:"answer"`
+	UpdatedAt    string         `json:"updatedAt"`
+	ReturnAnswer map[string]any `json:"returnAnswer"`
+}
+
+// 指标数据
+type Indicator struct {
+	Name              string          `json:"name"`              //身体名称
+	ID                string          `json:"id"`                //身体ID
+	Value             string          `json:"value"`             //身体值
+	Unit              string          `json:"unit"`              //身体单位
+	Reference         string          `json:"reference"`         //参考范围
+	ReferStart        string          `json:"referStart"`        //参考范围低值
+	ReferEnd          string          `json:"referEnd"`          //参考范围高值
+	ItemName          string          `json:"itemName"`          //检查项目名称
+	ItemID            string          `json:"itemId"`            //检查项目ID
+	AbnormalDatas     []*AbnormalData `json:"abnormalDatas"`     //异常数据
+	Date              int             `json:"date"`              //检查时间
+	OriginalName      string          `json:"originalName"`      //原始名称
+	Mark              int             `json:"mark"`              //标记
+	IsAbnormal        bool            `json:"isAbnormal"`        //是否异常
+	IsHideInCheckData bool            `json:"isHideInCheckData"` //是否在检查数据中隐藏
+}
+
+// 异常数据
+type AbnormalData struct {
+	Name  string            `json:"name"`  //异常名称
+	ID    string            `json:"id"`    //异常ID
+	Value map[string]string `json:"value"` //异常值
+}
+
+// 普通答案
+type QuestionAnswerModel struct {
+	Key   string `json:"key"`   // 答案key
+	Value string `json:"value"` // 答案value
+}
+
+// 单行文本题答案
+type QuestionInputAnswerModel struct {
+	Key   string   `json:"key"`   // 答案key
+	Value []string `json:"value"` // 答案value
+}
+
+// 链接答案
+type LinkAnswerModel struct {
+	Key   string       `json:"key"`   // 答案key
+	Value []LinkAnswer `json:"value"` // 答案value
+}
+
+type LinkAnswer struct {
+	Url  string `json:"url"`  // 链接地址
+	Name string `json:"name"` // 链接名称
+}
+
+// 矩阵答案
+type QuestionMatrixAnswerModel struct {
+	XKey  string `json:"xKey"`  // X轴key
+	XText string `json:"xText"` // X轴文本
+	YKey  string `json:"yKey"`  // Y轴key
+	YText string `json:"yText"` // Y轴文本
+}
+
+// 问卷答案
+type SurveyAnswer struct {
+	Type            string                      `json:"type" form:"type" binding:"required"`                                           // 问题类型
+	QuestionNo      string                      `json:"questionNo" form:"questionNo" binding:"required"`                               // 问题编号
+	MultipleAnswers bool                        `json:"multipleAnswers" form:"multipleAnswers" binding:"omitempty"`                    // 是否多答
+	InputAnswers    QuestionInputAnswerModel    `json:"inputAnswers" form:"inputAnswers" binding:"required_if=Type input"`             // 答案(单行文本题)支持多答
+	LinkAnswers     LinkAnswerModel             `json:"linkAnswers" form:"linkAnswers" binding:"required_if=Type upload"`              // 答案(链接题)支持多答
+	Answer          QuestionAnswerModel         `json:"answer" form:"answer" binding:"-"`                                              // 答案(单选题、时间选择题)
+	CheckboxAnswers []QuestionAnswerModel       `json:"checkboxAnswers" form:"checkboxAnswers" binding:"required_if=Type checkbox"`    // 答案(多选题)
+	MatrixAnswers   []QuestionMatrixAnswerModel `json:"matrixAnswers" form:"matrixAnswers" binding:"required_if=Type matrix_checkbox"` // 答案(矩阵多选题)
+	GroupAnswers    [][]SurveyAnswer            `json:"groupAnswers" form:"groupAnswers" binding:"required_if=Type group"`             // 答案(组合题)支持多答
+}
+
+type AlgorAppAuth struct {
+	ID              int64          `json:"id" form:"id" binding:"omitempty,numeric"`
+	AppId           int64          `json:"appId" form:"appId" binding:"omitempty,numeric"`
+	DecisionModelId int64          `json:"decisionModelId" form:"decisionModelId" binding:"required,numeric"`
+	DecisionModel   *DecisionModel `json:"decisionModel" form:"decisionModel" binding:"-"`
+	Remark          string         `json:"remark" form:"remark" binding:"omitempty,min=1,max=100"`
+	UsedTotal       int            `json:"usedTotal" form:"usedTotal" binding:"-"`
+	Status          int            `json:"status" form:"status" binding:"oneof=1 2"`
+	CreatedAt       string         `json:"createdAt" binding:"-"`
+}
+type DecisionModel struct {
+	ID        int64  `json:"id" form:"id" binding:"omitempty,number"`
+	Name      string `json:"name" form:"name" binding:"required,min=1,max=20"`
+	SN        string `json:"sn" form:"sn" binding:"required,alphanum,min=1,max=20"`
+	CreatedAt string `json:"createdAt" form:"-" binding:"-"`
+}
+
+type ExecuteRequest struct {
+	Type               int                         `json:"type" form:"type" binding:"required"`                                       // 处理类型,1:问卷,2:ocr
+	SurveyData         map[string]map[string]any   `json:"surveyData" form:"surveyData" binding:"required_if=Type 1"`                 // 问卷数据
+	OcrData            *OCRDataList                `json:"ocrData" form:"ocrData" binding:"required_if=Type 2"`                       // ocr数据
+	MultiOcrData       map[string]*OCRDataList     `json:"multiOcrData" form:"multiOcrData" binding:"required_if=Type 6"`             // ocr数据
+	DecisionModelSN    string                      `json:"decisionModelSn" form:"decisionModelSn" binding:"required"`                 // 决策模型编号
+	Extra              string                      `json:"extra" form:"extra" binding:"omitempty"`                                    // 额外数据
+	ArchivesData       *ExecuteRequestArchivesData `json:"archivesData" form:"archivesData" binding:"required_if=Type 3"`             // 档案数据
+	ChronicDiseaseData any                         `json:"chronicDiseaseData" form:"chronicDiseaseData" binding:"required_if=Type 4"` // 慢病数据
+	// ChronicDiseaseData *ChronicDiseaseRequestData  `json:"chronicDiseaseData" form:"chronicDiseaseData" binding:"required_if=Type 4"` // 慢病数据
+}
+
+type ExecuteRequestArchivesData struct {
+	ArchivesId     string            `json:"archivesId" form:"archivesId" binding:"required"`
+	Name           string            `json:"name" form:"name" binding:"required"`
+	Gender         string            `json:"gender" form:"gender" binding:"required"`
+	Age            int               `json:"age" form:"age" binding:"required"`
+	Indicators     []*Indicator      `json:"indicators" form:"indicators" binding:"omitempty"`
+	ArchivesValues []*ArchivesValues `json:"archivesValues" form:"archivesValues" binding:"omitempty"`
+}
+
+type OCRDataList struct {
+	UserName     string                   `json:"userName"`     //用户姓名
+	UserAge      int                      `json:"userAge"`      //用户年龄
+	UserBirthday string                   `json:"userBirthday"` //用户生日
+	UserSex      string                   `json:"userSex"`      //用户性别
+	OCRData      []map[string]any         `json:"ocrData"`      //OCR数据
+	SurveyData   map[string]*SurveyAnswer `json:"surveyData"`   // 问卷数据
+}
+
+type AuthMechanism struct {
+	ID             string             `json:"id"`             // 用户ID
+	Account        string             `json:"account"`        // 账号
+	Nickname       string             `json:"nickname"`       // 昵称
+	LoginAt        int64              `json:"loginAt"`        // 当前Token派发登录时间
+	IsMechanism    bool               `json:"isMechanism"`    // 是否是机构
+	FullPermission bool               `json:"fullPermission"` // 是否全权限覆盖
+	Permissions    []string           `json:"permissions"`    // 权限KEY列表
+	RoleIds        []int64            `json:"roleIds"`        // 角色ID列表
+	Mechanism      *AuthBaseMechanism `json:"mechanism"`      // 机构信息
+}
+type AuthBaseMechanism struct {
+	ID              string `json:"id"`              // 用户ID
+	Account         string `json:"account"`         // 账号
+	Nickname        string `json:"nickname"`        // 昵称
+	RawId           int64  `json:"rawId"`           // 原始ID
+	AppKey          string `json:"appKey"`          // appKey
+	AppSecret       string `json:"appSecret"`       // appSecret
+	IpWhiteList     string `json:"ipWhiteList"`     // ip白名单
+	CallbackUrlList string `json:"callbackUrlList"` // 回调地址列表
+}
+
+type AuthUser struct {
+	ID             int64    `json:"id"`             // 用户ID
+	Account        string   `json:"account"`        // 账号
+	Nickname       string   `json:"nickname"`       // 昵称
+	FullPermission bool     `json:"fullPermission"` // 是否全权限覆盖
+	RoleIds        []int64  `json:"roleIds"`        // 角色ID列表
+	Permissions    []string `json:"permissions"`    // 权限KEY列表
+	LoginAt        int64    `json:"loginAt"`        // 当前Token派发登录时间
+}
+
+type AuthMember struct {
+	ID                     string `json:"id"`                     // 档案编号
+	Name                   string `json:"name"`                   // 档案姓名
+	Gender                 int    `json:"gender"`                 // 档案性别
+	MainArchivesId         string `json:"mainArchivesId"`         // 主档案编号
+	IsCompletePassword     bool   `json:"isFullPassword"`         // 是否完善了密码
+	IsCompleteArchivesInfo bool   `json:"isCompleteArchivesInfo"` // 是否完善了档案信息
+	LoginAt                int64  `json:"loginAt"`                // 当前Token派发登录时间
+}
+
+type PdfTemplate struct {
+	ID              int64  `json:"id"`
+	Type            int64  `json:"type"`
+	SortRule        int64  `json:"sortRule"`
+	Name            string `json:"name"`
+	IsDefault       int64  `json:"isDefault"`
+	Config          string `json:"config"`
+	Remark          string `json:"remark"`
+	Logo            string `json:"logo"`
+	IsAttachRawPdf  int64  `json:"isAttachRawPdf"`
+	IsFilterDisease int64  `json:"isFilterDisease"` // 是否过滤疾病
+	CreatedAt       string `json:"createdAt"`
+}
+
+type PdfTemplateMechanism struct {
+	ID          int64        `json:"id"`
+	MechanismId string       `json:"mechanismId"`
+	IsMember    bool         `json:"isMember"`
+	TemplateId  int64        `json:"templateId"`
+	Template    *PdfTemplate `json:"template"`
+	CreatedAt   string       `json:"createdAt"`
+}
+
+type TagCategory struct {
+	ID           string                         `json:"id" form:"id" binding:"omitempty"`
+	RawId        int64                          `json:"rawId" form:"-" binding:"-"`
+	Name         string                         `json:"name" form:"name" binding:"required,max=20"`
+	Purpose      string                         `json:"purpose" form:"purpose"`
+	ModelSn      string                         `json:"modelSn" form:"-" binding:"-"`
+	ReturnFields []*TagCategoryModelReturnField `json:"returnFields" form:"-" binding:"-"`
+	CreatedAt    string                         `json:"createdAt" form:"-" binding:"-"`
+	UpdatedAt    string                         `json:"updatedAt" form:"-" binding:"-"`
+}
+
+type TagCategoryModelReturnField struct {
+	Value string `json:"value" form:"value" binding:"required"` // 字段value
+	Label string `json:"label" form:"-" binding:"-"`            // 字段名称
+	TagId string `json:"tagId" form:"tagId" binding:"required"` // 标签ID
+	Tag   *Tag   `json:"tag" form:"-" binding:"-"`              // 标签
+}
+
+type Street struct {
+	ID       string      `json:"id" binding:"required"`
+	Name     string      `json:"name" binding:"required"`
+	CountyId string      `json:"countyId" binding:"required"`
+	Villages []*Villages `json:"villages" binding:"-"`
+}
+type Villages struct {
+	ID       string `json:"id" binding:"required"`
+	Name     string `json:"name" binding:"required"`
+	StreetId string `json:"streetId" binding:"required"`
+}
+
+type MedicalReportCharts struct {
+	ArchivesId       string    `json:"archivesId"`
+	Archives         *Archives `json:"archives"`
+	AwaitTotal       int64     `json:"awaitTotal"`
+	ProcessTotal     int64     `json:"processTotal"`
+	SuccessTotal     int64     `json:"successTotal"`
+	DoneTotal        int64     `json:"doneTotal"`
+	ConfirmTotal     int64     `json:"confirmTotal"`
+	SuggestionStatus int64     `json:"suggestionStatus"`
+	LastTime         string    `json:"lastTime"`
+}
+
+type MedicalDataCreateFormByOpenAPI struct {
+	FileBase64     string           `json:"fileBase64" form:"fileBase64" binding:"omitempty"`         // 文件base64
+	FileName       string           `json:"fileName" form:"fileName" binding:"omitempty"`             // 文件名
+	FileUrl        string           `json:"fileUrl" form:"fileUrl" binding:"omitempty,url"`           // 文件地址
+	FileRemark     string           `json:"fileRemark" form:"fileRemark" binding:"omitempty"`         // 文件备注
+	MedicalDate    string           `json:"medicalDate" form:"medicalDate" binding:"required"`        // 体检日期
+	MechanismId    string           `json:"mechanismId" form:"mechanismId" binding:"required"`        // 机构ID
+	TransferResult []map[string]any `json:"transferResult" form:"transferResult" binding:"omitempty"` // 转换结果
+}
+
+type MedicalDataBindArchivesFormByOpenAPI struct {
+	ArchivesId    string `json:"archivesId" form:"archivesId" binding:"required"`       // 档案编号
+	MedicalDataId string `json:"medicalDataId" form:"medicalDataId" binding:"required"` // 数据ID
+	MechanismId   string `json:"mechanismId" form:"mechanismId" binding:"required"`     // 机构ID
+}
+
+type MedicalData struct {
+	// ID          int64              `json:"id" form:"id" binding:"omitempty,min=1"`                      // 数据ID
+	SN                     string                          `json:"sn" form:"-" binding:"-"`                                          // 批次号
+	ArchivesId             string                          `json:"archivesId" form:"archivesId" binding:"omitempty"`                 // 档案编号
+	Type                   int                             `json:"type" form:"type" binding:"required_if=ID 0,omitempty,min=1"`      // 类型
+	Remark                 string                          `json:"remark" form:"remark" binding:"omitempty"`                         // 备注
+	Files                  []*MedicalDataFile              `json:"files" form:"files" binding:"required,dive,min=1"`                 // 文件列表
+	MechanismId            string                          `json:"mechanismId" form:"-" binding:"-"`                                 // 机构ID
+	Mechanism              *Mechanism                      `json:"mechanism" form:"-" binding:"-"`                                   // 机构
+	FileName               string                          `json:"fileName" form:"fileName" binding:"omitempty"`                     // 文件名
+	Source                 int                             `json:"source" form:"-" binding:"-"`                                      // 来源
+	Status                 int                             `json:"status" form:"-" binding:"-"`                                      // 状态
+	IsAbandon              int                             `json:"isAbandon" form:"-" binding:"-"`                                   // 是否废弃
+	ResultRawJson          string                          `json:"resultRawJson" form:"-" binding:"-"`                               // 结果原始JSON
+	TransferRawJson        string                          `json:"transferRawJson" form:"transferRawJson" binding:"omitempty"`       // 转换原始JSON
+	Suggestion             string                          `json:"suggestion" form:"suggestion" binding:"omitempty"`                 // 个性化建议
+	PdfTransferStatus      int                             `json:"pdfTransferStatus" form:"-" binding:"-"`                           // PDF转换状态
+	PdfTransferMsg         string                          `json:"pdfTransferMsg" form:"-" binding:"-"`                              // PDF转换消息
+	PdfTransferResultUrl   string                          `json:"pdfTransferResultUrl" form:"-" binding:"-"`                        // PDF转换结果地址
+	PdfTransferStartTime   string                          `json:"pdfTransferStartTime" form:"-" binding:"-"`                        // PDF转换开始时间
+	PdfTransferEndTime     string                          `json:"pdfTransferEndTime" form:"-" binding:"-"`                          // PDF转换结束时间
+	Errors                 []string                        `json:"errors" form:"-" binding:"-"`                                      // 错误信息
+	Date                   string                          `json:"date" form:"date" binding:"omitempty"`                             // 日期
+	PdfResultTotalStatus   int                             `json:"pdfResultTotalStatus" form:"-" binding:"-"`                        // PDF转换结果总状态
+	PdfResultTemplateTotal int64                           `json:"pdfResultTemplateTotal" form:"-" binding:"-"`                      // PDF转换结果总数
+	PdfResultSuccessTotal  int64                           `json:"pdfResultSuccessTotal" form:"-" binding:"-"`                       // PDF转换结果成功数
+	PdfTemplateConfigs     []*MedicalDataPdfTemplateConfig `json:"pdfTemplateConfigs" form:"pdfTemplateConfigs" binding:"omitempty"` // PDF模板配置列表
+	CreatedAt              string                          `json:"createdAt" form:"-" binding:"-"`                                   // 创建时间
+	UpdatedAt              string                          `json:"updatedAt" form:"-" binding:"-"`                                   // 更新时间
+}
+type MedicalDataFile struct {
+	ID        int64  `json:"id" form:"id" binding:"omitempty,min=1"`                                    // 文件ID
+	DataId    int64  `json:"dataId" form:"-" binding:"-"`                                               // 数据ID
+	FileName  string `json:"fileName" form:"fileName" binding:"required_if=ID 0,omitempty"`             // 文件名
+	FileUrl   string `json:"fileUrl" form:"fileUrl" binding:"required_if=ID 0,omitempty,url"`           // 文件地址
+	Date      string `json:"date" form:"date" binding:"required_if=ID 0,omitempty,datetime=2006-01-02"` // 日期
+	Remark    string `json:"remark" form:"remark" binding:"omitempty"`                                  // 备注
+	CreatedAt string `json:"createdAt" form:"-" binding:"-"`                                            // 创建时间
+}
+
+type MedicalDataPdfTemplateConfig struct {
+	PdfTemplateId int64                               `json:"pdfTemplateId" form:"pdfTemplateId" binding:"required"` // PDF模板ID
+	Config        *MedicalDataPdfTemplateConfigStruct `json:"config" form:"config" binding:"required"`               // 配置信息
+}
+
+type MedicalDataPdfTemplateConfigStruct struct {
+	ShowDiseaseNames []string `json:"showDiseaseNames"` // 需要展示的疾病名称
+}
+
+type MedicalCompareReport struct {
+	ID                   string                    `json:"id" form:"id" binding:"required"`                  // 对比报告ID
+	ArchivesId           string                    `json:"archivesId" form:"archivesId" binding:"required"`  // 档案编号
+	Data                 *MedicalReportCompareData `json:"data" form:"data" binding:"required"`              // 对比报告的医疗数据
+	SuggestionStatus     int64                     `json:"suggestionStatus" form:"-" binding:"-"`            // 个性化建议状态
+	Suggestion           string                    `json:"suggestion" form:"suggestion" binding:"omitempty"` // 个性化建议
+	PdfTransferStatus    int                       `json:"pdfTransferStatus" form:"-" binding:"-"`           // PDF转换状态
+	PdfTransferMsg       string                    `json:"pdfTransferMsg" form:"-" binding:"-"`              // PDF转换消息
+	PdfTransferResultUrl string                    `json:"pdfTransferResultUrl" form:"-" binding:"-"`        // PDF转换结果地址
+	PdfTransferStartTime string                    `json:"pdfTransferStartTime" form:"-" binding:"-"`        // PDF转换开始时间
+	PdfTransferEndTime   string                    `json:"pdfTransferEndTime" form:"-" binding:"-"`          // PDF转换结束时间
+	CreatedAt            string                    `json:"createdAt" form:"-" binding:"-"`                   // 创建时间
+}
+
+type MedicalReportCompareData struct {
+	DiseaseList        []MedicalReportDisease `json:"diseaseList"`
+	MedDataList        []MedicalReportMedData `json:"medDataList"`
+	TableHeaderColumns []string               `json:"tableHeaderColumns"`
+	TableData          []FinalAnalysisResult  `json:"tableData"`
+	MedicalDataIds     []string               `json:"medicalDataIds"`
+}
+
+type MedicalReportDisease struct {
+	Name   string                     `json:"name"`
+	NodeId string                     `json:"nodeId"`
+	List   []MedicalReportDiseaseItem `json:"list"`
+}
+
+type MedicalReportDiseaseItem struct {
+	RiskDesc   string `json:"riskDesc"`   //风险描述词
+	RiskDegree int    `json:"riskDegree"` //风险程度 //0-无法评估 1-暂无风险 2-有一定风险 3-有明显风险 4-已确诊
+}
+
+type MedicalReportMedData struct {
+	Name   string      `json:"name"`
+	NodeId string      `json:"nodeId"`
+	Type   int         `json:"type"`
+	Sort   int         `json:"sort"`
+	List   [][]MedData `json:"list"`
+}
+
+// 医疗数据
+type MedData struct {
+	ItermName     string `json:"itermName"`     //医疗数据名称
+	NodeId        string `json:"nodeId"`        //医疗数据ID
+	Value         string `json:"value"`         //医疗数据值
+	Unit          string `json:"unit"`          //医疗数据单位
+	Reference     string `json:"reference"`     //参考范围
+	CheckTime     int    `json:"checkTime"`     //检查时间
+	CheckItemName string `json:"checkItemName"` //检查项目名称
+	CheckItemId   string `json:"checkItemId"`   //检查项目ID
+	Mark          int    `json:"mark"`          //异常标记 0-无标记 1-升高  -1-降低
+	IsAbnormal    bool   `json:"isAbnormal"`    //是否异常
+	Type          int    `json:"type"`          //类型 0-未定义 1-身体物质 2-身体部位 3-其他身体物质
+	Sort          int    `json:"sort"`          //排序
+}
+
+// 最终输出结果
+type FinalAnalysisResult struct {
+	ExamDate        int                               `json:"examDate"`       //检查日期
+	AssessmentDate  string                            `json:"assessmentDate"` //评估日期
+	DebugInfo       []string                          `json:"debugInfo"`      //调试信息
+	MajorDiseases   []MajorDisease                    `json:"majorDisease"`   //重大疾病
+	CalErr          []string                          `json:"calErr"`         //系统计算错误信息
+	AlTime          string                            `json:"alTime"`         //计算时间
+	UserInfo        FinalAnalysisResultUserInfo       `json:"userInfo"`       //用户信息
+	MedicalReportId string                            `json:"medicalReportId"`
+	AbnormalInfo    []FinalAnalysisResultAbnormalInfo `json:"abnormalInfo"` //异常信息
+}
+type FinalAnalysisResultAbnormalInfo struct {
+	AbnormalTypeName   string                         `json:"abnormalTypeName"`   //异常类型名称
+	AbnormalTypeNodeID string                         `json:"abnormalTypeNodeID"` //异常类型nodeid
+	ClassInfo          []FinalAnalysisResultClassInfo `json:"classInfo"`          //异常类别信息
+}
+type FinalAnalysisResultClassInfo struct {
+	AbnormalClassName   string `json:"abnormalClassName"`   //异常类别名称
+	AbnormalClassNodeID string `json:"abnormalClassNodeID"` //异常类别nodeid
+}
+
+type FinalAnalysisResultUserInfo struct {
+	CurrentAge string `json:"currentAge"` //当前年龄
+	ExamAge    string `json:"examAge"`    //检查时年龄
+	Gender     string `json:"gender"`     // 性别
+	Name       string `json:"name"`       //姓名
+}
+
+// 重大疾病
+type MajorDisease struct {
+	Name             string         `json:"name"`             //疾病名称
+	NodeId           string         `json:"nodeId"`           //疾病ID
+	RiskDesc         string         `json:"riskDesc"`         //风险描述词
+	RiskDegree       int            `json:"riskDegree"`       //风险程度 //0-无法评估 1-暂无风险 2-有一定风险 3-有明显风险 4-已确诊
+	Classification   int            `json:"classification"`   //疾病分类 	0-未分类  1-肿瘤  2-心脑血管	3-个性化疾病
+	RecommendItems   []string       `json:"recommendItems"`   //推荐检查项目
+	FollowUpTime     string         `json:"followUpTime"`     //随访时间
+	NotificationTime string         `json:"notificationTime"` //通知时间
+	Department       []string       `json:"department"`       //科室名称
+	MedDatas         []MedData      `json:"medDatas"`         //医疗数据
+	AbnormalDatas    []AbnormalData `json:"abnormalDatas"`    //异常检查结果
+}
+
+type QueryIDCIndicatorDataQuery struct {
+	ArchivesId string                            `json:"archivesId" form:"archivesId" binding:"required"`
+	QueryData  []*QueryIDCIndicatorDataQueryData `json:"queryData" form:"queryData" binding:"required,dive,min=1"`
+}
+type QueryIDCIndicatorDataQueryData struct {
+	BodyDataId string   `json:"bodyDataId" form:"bodyDataId" binding:"required"`
+	ItemId     string   `json:"itemId" form:"itemId" binding:"omitempty"`
+	CheckTime  []string `json:"checkTime" form:"checkTime" binding:"omitempty"`
+}
+
+type MedicalDateTransferResultQueryResultItemBody struct {
+	ID           string       `json:"id"`           // 检查内容ID
+	Name         string       `json:"name"`         // 检查内容名称
+	IsBodyMatter bool         `json:"isBodyMatter"` // 是否是身体物质
+	Tags         []string     `json:"tags"`         // 标签
+	List         []*Indicator `json:"list"`         // 检查内容的指标列表
+}
+
+// 慢病管理参数
+type ChronicDiseaseRequestData struct {
+	DiseaseId      string          `json:"diseaseId" form:"diseaseId" binding:"required"`                 // 疾病ID
+	UserId         string          `json:"userId" form:"userId" binding:"required"`                       // 用户ID
+	EvaluationsNum int             `json:"evaluationsNum" form:"evaluationsNum" binding:"required,min=0"` // 评估次数
+	AssessmentInfo *AssessmentInfo `json:"assessmentInfo" form:"assessmentInfo" binding:"omitempty"`      // 评估信息
+}
+
+type AssessmentInfo struct {
+	Result     string   `json:"result"`     //评估结果
+	Accordance []string `json:"accordance"` //评估依据
+	ErrInfo    []string `json:"errInfo"`    //错误信息
+}
+
+type Channel struct {
+	ID        int64  `json:"id"`
+	Name      string `json:"name"`
+	Remark    string `json:"remark"`
+	Sort      int64  `json:"sort"`
+	CreatedAt string `json:"createdAt"`
+}
+
+type Agency struct {
+	ID          int64      `json:"id" form:"id" binding:"omitempty"`
+	Nickname    string     `json:"nickname" form:"nickname" binding:"required"`
+	Account     string     `json:"account" form:"account" binding:"required"`
+	Password    string     `json:"password" form:"password" binding:"omitempty"`
+	Status      int64      `json:"status" form:"status" binding:"required"`
+	Remark      string     `json:"remark" form:"remark" binding:"omitempty"`
+	ChannelIds  []int64    `json:"channelIds" form:"channelIds" binding:"required"`
+	Channels    []*Channel `json:"channels" form:"channels" binding:"-"`
+	MechanismId string     `json:"mechanismId" form:"mechanismId" binding:"-"`
+	CreatedAt   string     `json:"createdAt" form:"createdAt" binding:"-"`
+}
+
+type AgencyDeveloperSettingForm struct {
+	AgencyId           int64   `json:"agencyId" form:"agencyId" binding:"required"`                     // 三方机构ID
+	MechanismId        string  `json:"mechanismId" form:"mechanismId" binding:"omitempty"`              // 机构ID
+	AppKey             string  `json:"appKey" form:"appKey" binding:"omitempty"`                        // appKey
+	AppSecret          string  `json:"appSecret" form:"appSecret" binding:"omitempty"`                  // appSecret
+	RegistChannelId    int64   `json:"registChannelId" form:"registChannelId" binding:"required"`       // 注册渠道ID
+	RegistDepartmentId int64   `json:"registDepartmentId" form:"registDepartmentId" binding:"required"` // 注册部门ID
+	CallbackUrl        string  `json:"callbackUrl" form:"callbackUrl" binding:"required"`               // 回调地址
+	WhiteIp            string  `json:"whiteIp" form:"whiteIp" binding:"omitempty"`                      // 白名单
+	UserAccountPrefix  string  `json:"userAccountPrefix" form:"userAccountPrefix" binding:"omitempty"`  // 用户账号前缀
+	PdfTemplateId      int64   `json:"pdfTemplateId" form:"pdfTemplateId" binding:"omitempty"`          // PDF模板ID
+	AgencyInfo         *Agency `json:"agencyInfo" form:"agencyInfo" binding:"-"`
+}

+ 388 - 0
survey/parse.go

@@ -0,0 +1,388 @@
+package survey
+
+import (
+	"fmt"
+
+	"github.com/golang-module/carbon"
+	"github.com/samber/lo"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+)
+
+const (
+	TYPE_INPUT           = "input"           // 单行文本题
+	TYPE_RADIO           = "radio"           // 单选题
+	TYPE_CHECKBOX        = "checkbox"        // 多选题
+	TYPE_DATE            = "date"            // 日期选择题
+	TYPE_GROUP           = "group"           // 组合题
+	TYPE_MATRIX_CHECKBOX = "matrix_checkbox" // 矩阵多选题
+	TYPE_LINK            = "upload"          // 链接题
+	TYPE_SELECT          = "select"          // 链接题
+)
+
+const (
+	DATE_TYPE_DATE     = "dateType:date"     // 日期类型:2022年01月01日
+	DATE_TYPE_DATETIME = "dateType:datetime" // 日期类型:2022年01月01日 12:00:00
+	DATE_TYPE_AGE      = "dateType:age"      // 日期类型:年龄值,向下取整
+	DATE_TYPE_DAY      = "dateType:day"      // 日期类型:距离某个日期的天数
+	DATE_TYPE_HOUR     = "dateType:hour"     // 日期类型:距离某个日期的小时数
+)
+
+/**
+ * 获取题目的有效答案的数量
+ *
+ * 适用于:单选题,多选题,单行文本题,时间选择题
+ *
+ * 1. 单选题(QuRadio)
+ * 您是否有疾病史?
+ * yes => 是
+ * no => 否
+ *
+ * 当用户选择了是或者否时:
+ * getValidAnswerCount(QuRadio)
+ * 返回值: 1
+ *
+ * 当用户跳过了该题:
+ *
+ * getValidAnswerCount(QuRadio)
+ * 返回值: 0
+ *
+ * @param sdk.SurveyAnswer question 题目内容
+ * @return int 有效答案的数量
+ **/
+// 获取题目的有效答案的数量(不支持组合题)
+func GetValidAnswerCount(question sdk.SurveyAnswer) int {
+	var total int = 0
+	// 除了组合题,其他都支持
+	switch question.Type {
+	case TYPE_GROUP:
+		for _, group := range question.GroupAnswers {
+			for _, item := range group {
+				total += GetValidAnswerCount(item)
+			}
+		}
+	case TYPE_MATRIX_CHECKBOX:
+		if len(question.MatrixAnswers) > 0 {
+			total = len(question.MatrixAnswers)
+		}
+	case TYPE_CHECKBOX:
+		if len(question.CheckboxAnswers) > 0 {
+			total = len(question.CheckboxAnswers)
+		}
+	case TYPE_INPUT:
+		if len(question.InputAnswers.Value) > 0 {
+			total = len(question.InputAnswers.Value)
+		}
+	case TYPE_LINK:
+		if len(question.LinkAnswers.Value) > 0 {
+			total = len(question.LinkAnswers.Value)
+		}
+	default:
+		if question.Answer.Value != "" {
+			total = 1
+		}
+	}
+
+	return total
+}
+
+/**
+ * 获取矩阵题的有效答案
+ *
+ * 仅适用于:矩阵题
+ *
+ * 有矩阵题如下
+ * |---------|高血压(g)|糖尿病(t)|癌症(a)|
+ * |父亲(dad)|     √   |    √   |      |
+ * |母亲(mom)|     √   |        |   √  |
+ *
+ * 当需要获取获取“父亲高血压”的答案时:
+ * getValidAnswerForMatrix(Question, 'dad', 'g');
+ * 返回值为: ['dad' => '父亲', 'g' => '高血压'] (数组)
+ *
+ **/
+// 获取矩阵题的有效答案
+func GetValidAnswerForMatrix(question sdk.SurveyAnswer, questionNo string, answerNo string) (*sdk.QuestionMatrixAnswerModel, error) {
+	// 仅支持矩阵题
+	if question.Type != TYPE_MATRIX_CHECKBOX {
+		return nil, fmt.Errorf("不支持非矩阵题")
+	}
+
+	// 遍历矩阵题的答案
+	for _, answer := range question.MatrixAnswers {
+		// 如果X轴和Y轴的key都匹配,则返回true
+		if answer.XKey == questionNo && answer.YKey == answerNo {
+			return &answer, nil
+		}
+	}
+
+	return nil, fmt.Errorf("没有符合要求的答案")
+}
+
+// 获取单选和多选题的有效答案KEY
+func GetValidAnswerKeysForRadioOrCheckbox(question sdk.SurveyAnswer) []string {
+	var keys []string
+	switch question.Type {
+	case TYPE_CHECKBOX:
+		for _, answer := range question.CheckboxAnswers {
+			if answer.Key != "" {
+				keys = append(keys, answer.Key)
+			}
+		}
+	case TYPE_SELECT:
+		for _, answer := range question.CheckboxAnswers {
+			if answer.Key != "" {
+				keys = append(keys, answer.Key)
+			}
+		}
+	case TYPE_RADIO:
+		if question.Answer.Value != "" && question.Answer.Key != "" {
+			keys = append(keys, question.Answer.Key)
+		}
+	}
+
+	return keys
+}
+
+// 获取单选和多选题的有效答案KEY
+func GetValidAnswerKeys(question sdk.SurveyAnswer) []string {
+	var keys []string
+	switch question.Type {
+	case TYPE_CHECKBOX:
+		for _, answer := range question.CheckboxAnswers {
+			if answer.Key != "" {
+				keys = append(keys, answer.Key)
+			}
+		}
+	case TYPE_SELECT:
+		for _, answer := range question.CheckboxAnswers {
+			if answer.Key != "" {
+				keys = append(keys, answer.Key)
+			}
+		}
+	case TYPE_RADIO:
+		if question.Answer.Value != "" && question.Answer.Key != "" {
+			keys = append(keys, question.Answer.Key)
+		}
+	case TYPE_LINK:
+		if len(question.LinkAnswers.Value) > 0 && question.LinkAnswers.Key != "" {
+			keys = append(keys, question.LinkAnswers.Key)
+		}
+	case TYPE_INPUT:
+		if len(question.InputAnswers.Value) > 0 && question.InputAnswers.Key != "" {
+			keys = append(keys, question.InputAnswers.Key)
+		}
+	case TYPE_DATE:
+		if len(question.InputAnswers.Value) > 0 && question.InputAnswers.Key != "" {
+			keys = append(keys, question.InputAnswers.Key)
+		}
+	}
+
+	return keys
+}
+
+func GetValidAnswerValues(question sdk.SurveyAnswer) []string {
+	var values []string
+	switch question.Type {
+	case TYPE_CHECKBOX:
+		for _, answer := range question.CheckboxAnswers {
+			if answer.Value != "" {
+				values = append(values, answer.Value)
+			}
+		}
+	case TYPE_SELECT:
+		for _, answer := range question.CheckboxAnswers {
+			if answer.Value != "" {
+				values = append(values, answer.Value)
+			}
+		}
+	case TYPE_RADIO:
+		if question.Answer.Value != "" && question.Answer.Key != "" {
+			values = append(values, question.Answer.Value)
+		}
+	case TYPE_LINK:
+		if len(question.LinkAnswers.Value) > 0 && question.LinkAnswers.Key != "" {
+			for _, value := range question.LinkAnswers.Value {
+				values = append(values, value.Url)
+			}
+		}
+	case TYPE_INPUT:
+		if len(question.InputAnswers.Value) > 0 && question.InputAnswers.Key != "" {
+			values = append(values, question.InputAnswers.Value...)
+		}
+	case TYPE_DATE:
+		if len(question.InputAnswers.Value) > 0 && question.InputAnswers.Key != "" {
+			values = append(values, question.InputAnswers.Value...)
+		}
+	}
+
+	return values
+}
+
+func GetValidAnswerKeyAndValues(question sdk.SurveyAnswer) []sdk.QuestionInputAnswerModel {
+	var values []sdk.QuestionInputAnswerModel
+	switch question.Type {
+	case TYPE_CHECKBOX:
+		for _, answer := range question.CheckboxAnswers {
+			if answer.Value != "" {
+				values = append(values, sdk.QuestionInputAnswerModel{
+					Key:   answer.Key,
+					Value: []string{answer.Value},
+				})
+			}
+		}
+	case TYPE_SELECT:
+		for _, answer := range question.CheckboxAnswers {
+			if answer.Value != "" {
+				values = append(values, sdk.QuestionInputAnswerModel{
+					Key:   answer.Key,
+					Value: []string{answer.Value},
+				})
+			}
+		}
+	case TYPE_RADIO:
+		if question.Answer.Value != "" && question.Answer.Key != "" {
+			values = append(values, sdk.QuestionInputAnswerModel{
+				Key:   question.Answer.Key,
+				Value: []string{question.Answer.Value},
+			})
+		}
+	case TYPE_LINK:
+		if len(question.LinkAnswers.Value) > 0 && question.LinkAnswers.Key != "" {
+			linkValues := make([]string, 0)
+			for _, value := range question.LinkAnswers.Value {
+				linkValues = append(linkValues, value.Url)
+			}
+			values = append(values, sdk.QuestionInputAnswerModel{
+				Key:   question.LinkAnswers.Key,
+				Value: linkValues,
+			})
+		}
+	case TYPE_INPUT:
+		if len(question.InputAnswers.Value) > 0 && question.InputAnswers.Key != "" {
+			values = append(values, question.InputAnswers)
+		}
+	case TYPE_DATE:
+		if len(question.InputAnswers.Value) > 0 && question.InputAnswers.Key != "" {
+			values = append(values, question.InputAnswers)
+		}
+	}
+
+	return values
+}
+
+// 获取组合题的有效答案Key和Value
+// question 问题答案实体
+// questionNo 组合题中单个问题的编号
+func GetValidAnswerKeyAndValuesForGroup(question sdk.SurveyAnswer, questionNo string) []sdk.QuestionInputAnswerModel {
+	var values []sdk.QuestionInputAnswerModel
+	switch question.Type {
+	case TYPE_GROUP:
+		for _, groupAnswer := range question.GroupAnswers {
+			for _, answer := range groupAnswer {
+				if answer.QuestionNo == questionNo {
+					values = append(values, GetValidAnswerKeyAndValues(answer)...)
+				}
+			}
+		}
+	}
+
+	return values
+}
+
+// 获取组合题的有效答案Value
+// question 问题答案实体
+// questionNo 组合题中单个问题的编号
+func GetValidAnswerValuesForGroup(question sdk.SurveyAnswer, questionNo string) []string {
+	var values []string
+	switch question.Type {
+	case TYPE_GROUP:
+		for _, groupAnswer := range question.GroupAnswers {
+			for _, answer := range groupAnswer {
+				if answer.QuestionNo == questionNo {
+					values = append(values, GetValidAnswerValues(answer)...)
+				}
+			}
+		}
+	}
+
+	return values
+}
+
+// 获取组合题的有效答案KEY
+// question 问题答案实体
+// questionNo 组合题中单个问题的编号
+func GetValidAnswerKeysForGroup(question sdk.SurveyAnswer, questionNo string) []string {
+	var keys []string
+	switch question.Type {
+	case TYPE_GROUP:
+		for _, groupAnswer := range question.GroupAnswers {
+			for _, answer := range groupAnswer {
+				if answer.QuestionNo == questionNo {
+					keys = append(keys, GetValidAnswerKeys(answer)...)
+				}
+			}
+		}
+	}
+
+	return keys
+}
+
+// 给定一个KEY获取单选和多选题的有效答案
+func GetValidAnswerForRadioOrCheckbox(question sdk.SurveyAnswer, answerKey string) (*sdk.QuestionAnswerModel, error) {
+	switch question.Type {
+	case TYPE_CHECKBOX:
+		for _, answer := range question.CheckboxAnswers {
+			if answer.Key == answerKey {
+				return &answer, nil
+			}
+		}
+	case TYPE_SELECT:
+		for _, answer := range question.CheckboxAnswers {
+			if answer.Key == answerKey {
+				return &answer, nil
+			}
+		}
+	case TYPE_RADIO:
+		if question.Answer.Key == answerKey {
+			return &question.Answer, nil
+		}
+	}
+
+	return nil, fmt.Errorf("没有符合要求的答案")
+}
+
+// 判断单选或多选题的答案是否有效
+func CheckAnswerKeysIsValid(question sdk.SurveyAnswer, answerKeys []string) bool {
+	// 获取有效答案的key
+	validAnswerKeys := GetValidAnswerKeysForRadioOrCheckbox(question)
+	// 判断两个字符串数组的交集
+	intersectAnswers := lo.Intersect(validAnswerKeys, answerKeys)
+	// 如果交集的数量和有效答案的数量相等,则表示答案有效
+	return len(intersectAnswers) == len(answerKeys)
+}
+
+// 日期格式化
+func TranslateDate(date string, translateType string, baseDate string) string {
+	if baseDate == "" {
+		baseDate = carbon.Now().Format("Y-m-d")
+	}
+	switch translateType {
+	case DATE_TYPE_AGE:
+		// 年龄值,向下取整
+		return fmt.Sprintf("%d", carbon.Parse(date).Age())
+	case DATE_TYPE_DATE:
+		// 日期类型:2022年01月01日
+		return carbon.Parse(date).Format("Y/m/d")
+	case DATE_TYPE_DATETIME:
+		// 日期类型:2022年01月01日 12:00:00
+		return carbon.Parse(date).Format("Y/m/d H:i:s")
+	case DATE_TYPE_DAY:
+		// 日期类型:距离某个日期的天数
+		return fmt.Sprintf("%d", carbon.Parse(baseDate).DiffInDays(carbon.Parse(date)))
+	case DATE_TYPE_HOUR:
+		// 日期类型:距离某个日期的小时数
+		return fmt.Sprintf("%d", carbon.Parse(baseDate).DiffInHours(carbon.Parse(date)))
+	}
+
+	return ""
+}

+ 151 - 0
survey/parse_test.go

@@ -0,0 +1,151 @@
+package survey_test
+
+import (
+	"encoding/json"
+	"fmt"
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/survey"
+)
+
+func TestTranslateDate(t *testing.T) {
+	// 年龄
+	age := survey.TranslateDate("1996-01-02 14:00:00", survey.DATE_TYPE_AGE, "")
+	fmt.Println("当前年龄", age)
+	age = survey.TranslateDate("2023-05-05 14:00:00", survey.DATE_TYPE_DATE, "")
+	fmt.Println("当前时间", age)
+	age = survey.TranslateDate("2023-05-05 14:00:00", survey.DATE_TYPE_DATETIME, "")
+	fmt.Println("当前时间分钟", age)
+	age = survey.TranslateDate("2023-05-05 14:00:00", survey.DATE_TYPE_DAY, "2000-01-01 00:00:00")
+	fmt.Println("距离天数", age)
+	age = survey.TranslateDate("2023-05-05 14:00:00", survey.DATE_TYPE_HOUR, "2000-01-01 00:00:00")
+	fmt.Println("距离小时", age)
+}
+
+func TestMockData(t *testing.T) {
+	var questions = map[string]sdk.SurveyAnswer{
+		"QUName": {
+			Type:            survey.TYPE_INPUT,
+			QuestionNo:      "QUName",
+			MultipleAnswers: true,
+			InputAnswers: sdk.QuestionInputAnswerModel{
+				Value: []string{"张三", "李四"},
+				Key:   "name",
+			},
+		},
+		"QUAddress": {
+			Type:            survey.TYPE_INPUT,
+			QuestionNo:      "QUAddress",
+			MultipleAnswers: false,
+			InputAnswers: sdk.QuestionInputAnswerModel{
+				Value: []string{"北京市朝阳区"},
+				Key:   "address",
+			},
+		},
+		"QUGender": {
+			Type:            survey.TYPE_RADIO,
+			QuestionNo:      "QUGender",
+			MultipleAnswers: false,
+			Answer: sdk.QuestionAnswerModel{
+				Value: "男",
+				Key:   "gender",
+			},
+		},
+		"QUBirthday": {
+			Type:            survey.TYPE_DATE,
+			QuestionNo:      "QUBirthday",
+			MultipleAnswers: false,
+			Answer: sdk.QuestionAnswerModel{
+				Value: "1990-01-01",
+				Key:   "birthday",
+			},
+		},
+		"QUDisease": {
+			Type:            survey.TYPE_CHECKBOX,
+			QuestionNo:      "QUDisease",
+			MultipleAnswers: false,
+			CheckboxAnswers: []sdk.QuestionAnswerModel{
+				{
+					Value: "高血压",
+					Key:   "hypertension",
+				},
+				{
+					Value: "糖尿病",
+					Key:   "diabetes",
+				},
+			},
+		},
+		"QUDiseaseFamily": {
+			Type:            survey.TYPE_MATRIX_CHECKBOX,
+			QuestionNo:      "QUDiseaseFamily",
+			MultipleAnswers: false,
+			MatrixAnswers: []sdk.QuestionMatrixAnswerModel{
+				{
+					XKey:  "dad",
+					XText: "父亲",
+					YKey:  "hypertension",
+					YText: "高血压",
+				},
+				{
+					XKey:  "dad",
+					XText: "父亲",
+					YKey:  "diabetes",
+					YText: "糖尿病",
+				},
+				{
+					XKey:  "mom",
+					XText: "母亲",
+					YKey:  "hypertension",
+					YText: "高血压",
+				},
+			},
+		},
+		"QUDiseaseHistory": {
+			Type:            survey.TYPE_GROUP,
+			QuestionNo:      "QUDiseaseHistory",
+			MultipleAnswers: true,
+			GroupAnswers: [][]sdk.SurveyAnswer{
+				{
+					{
+						Type:       survey.TYPE_RADIO,
+						QuestionNo: "QUDisease",
+						Answer: sdk.QuestionAnswerModel{
+							Value: "高血压",
+							Key:   "hypertension",
+						},
+					},
+					{
+						Type:       survey.TYPE_DATE,
+						QuestionNo: "QUDiseaseDate",
+						Answer: sdk.QuestionAnswerModel{
+							Value: "2020-01-01",
+							Key:   "hypertensionDate",
+						},
+					},
+				},
+				{
+					{
+						Type:       survey.TYPE_RADIO,
+						QuestionNo: "QUDisease",
+						Answer: sdk.QuestionAnswerModel{
+							Value: "糖尿病",
+							Key:   "diabetes",
+						},
+					},
+					{
+						Type:       survey.TYPE_DATE,
+						QuestionNo: "QUDiseaseDate",
+						Answer: sdk.QuestionAnswerModel{
+							Value: "2019-01-01",
+							Key:   "diabetesDate",
+						},
+					},
+				},
+			},
+		},
+	}
+	jsonText, _ := json.Marshal(questions)
+	fmt.Println(jsonText)
+
+}

+ 82 - 0
tag/main.go

@@ -0,0 +1,82 @@
+package tag
+
+import (
+	"fmt"
+
+	"github.com/guonaihong/gout"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+)
+
+// 获取标签分类信息
+func DetailTagCategory(id string) (*sdk.BaseResponse[sdk.DetailResponse[*sdk.TagCategory]], *response.ErrCode) {
+	var resp *sdk.BaseResponse[sdk.DetailResponse[*sdk.TagCategory]]
+	resp, err := postReq[*sdk.BaseResponse[sdk.DetailResponse[*sdk.TagCategory]]]("/tagService/openapi/tagCategory/detail", gout.H{
+		"id": id,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 获取标签分类信息
+func SetArchivesTag(tagId string, archivesId string, remarks string, operatorName string) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/tagService/openapi/archive/tag", gout.H{
+		"tagId":        tagId,
+		"archiveId":    archivesId,
+		"remarks":      remarks,
+		"operatorName": operatorName,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// postReq 发送post请求
+func postReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.POST(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetJSON(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}

+ 35 - 0
tag/main_test.go

@@ -0,0 +1,35 @@
+package tag_test
+
+import (
+	"fmt"
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/tag"
+)
+
+func TestList(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		// pdfTemplates, err := pdf_template.ListByIds([]int64{15, 16})
+		// fmt.Println(pdfTemplates, err)
+		pdfTemplates, err := tag.DetailTagCategory("OdGoZlD5")
+		fmt.Println(pdfTemplates, err)
+	})
+}
+
+func TestSetArchivesTag(t *testing.T) {
+	t.Run("test", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		// pdfTemplates, err := pdf_template.ListByIds([]int64{15, 16})
+		// fmt.Println(pdfTemplates, err)
+		pdfTemplates, err := tag.SetArchivesTag("2NmOBzxZ", "pWJM3jrG", "哈哈哈", "测试")
+		fmt.Println(pdfTemplates, err)
+	})
+}

+ 55 - 0
utils/main.go

@@ -0,0 +1,55 @@
+package utils
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+	"encoding/json"
+	"reflect"
+
+	"github.com/guonaihong/gout"
+)
+
+func JsonEncode(v interface{}) string {
+	jsonStr, _ := json.Marshal(v)
+	return string(jsonStr)
+}
+
+// MD5加密
+func Md5(src string) string {
+	m := md5.New()
+	m.Write([]byte(src))
+	res := hex.EncodeToString(m.Sum(nil))
+	return res
+}
+
+func StructToGoutH(item interface{}) gout.H {
+	result := make(gout.H)
+	itemValue := reflect.ValueOf(item)
+
+	// 如果传入的是指针,则获取其所指向的元素
+	if itemValue.Kind() == reflect.Ptr {
+		itemValue = itemValue.Elem()
+	}
+
+	// 确保传入的是结构体
+	if itemValue.Kind() != reflect.Struct {
+		return result
+	}
+
+	itemType := itemValue.Type()
+	for i := 0; i < itemValue.NumField(); i++ {
+		// 获取字段名和值
+		field := itemType.Field(i)
+		fieldValue := itemValue.Field(i).Interface()
+
+		// 获取json标签,如果存在则使用json标签作为字段名
+		jsonTag := field.Tag.Get("json")
+		if jsonTag != "" && jsonTag != "-" {
+			result[jsonTag] = fieldValue
+		} else {
+			result[field.Name] = fieldValue
+		}
+	}
+
+	return result
+}

+ 194 - 0
wallet/main.go

@@ -0,0 +1,194 @@
+package wallet
+
+import (
+	"fmt"
+
+	"github.com/guonaihong/gout"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/response"
+)
+
+const (
+	WalletTypeMedicalReport = 1 // 报告解读
+	WalletTypeArchives      = 2 // 家庭档案
+)
+
+// 钱包消费
+func Consume(orderSn string, archivesId string, mechanismId string, walletType int64, quantity int64, remark string) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/walletService/openapi/member/card/balance", gout.H{
+		"orderSn":     orderSn,
+		"archiveSn":   archivesId,
+		"mechanismId": mechanismId,
+		"type":        walletType,
+		"quantity":    quantity,
+		"remark":      remark,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 钱包消费
+func ConsumeRollback(orderSn string, remark string) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/walletService/openapi/member/card/balance/rollback", gout.H{
+		"orderSn": orderSn,
+		"remark":  remark,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 注册钱包
+func Regist(archivesId string) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/walletService/openapi/event/member/register", gout.H{
+		"archiveSn": archivesId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 检查是否已授权钱包
+func CheckMechanismAuthorize(mechanismId string, walletType int64) (*sdk.BaseResponse[bool], *response.ErrCode) {
+	var resp *sdk.BaseResponse[bool]
+	resp, err := getReq[*sdk.BaseResponse[bool]]("/walletService/openapi/walletType/mechanism", gout.H{
+		"mechanismId":  mechanismId,
+		"walletTypeId": walletType,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// 钱包消费
+func MemberCardBind(
+	cardId int64, archivesId string, channelName string, price int64, payType string, outTradeNo string, remark string, mechanismId string,
+) (*sdk.BaseResponse[map[string]any], *response.ErrCode) {
+	var resp *sdk.BaseResponse[map[string]any]
+	resp, err := postReq[*sdk.BaseResponse[map[string]any]]("/walletService/openapi/member/card/bind", gout.H{
+		"cardId":      cardId,
+		"archiveId":   archivesId,
+		"channelName": channelName,
+		"price":       price,
+		"payType":     payType,
+		"outTradeNo":  outTradeNo,
+		"remark":      remark,
+		"mechanismId": mechanismId,
+	})
+	if err != nil {
+		return nil, &response.ErrCode{
+			Code: response.PLATFORM_ERROR,
+			Msg:  err.Error(),
+		}
+	}
+	if resp == nil {
+		return nil, response.ErrPlatform
+	}
+	if resp.Code != 200 {
+		return nil, &response.ErrCode{
+			Code: resp.Code,
+			Msg:  resp.Message,
+		}
+	}
+	return resp, nil
+}
+
+// postReq 发送post请求
+func postReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.POST(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetJSON(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}
+
+// postReq 发送post请求
+func getReq[T any](path string, data gout.H) (T, error) {
+	var res T
+	fmt.Println(sdk.GetConfig())
+	// 检查配置
+	if sdk.GetConfig().ApiDomain == "" {
+		return res, fmt.Errorf("请先配置API域名")
+	}
+	url := fmt.Sprintf("%s%s", sdk.GetConfig().ApiDomain, path)
+	fmt.Println("请求地址 ===>", url)
+	err := gout.GET(url).Debug(sdk.GetConfig().AppDebug).
+		SetHeader(gout.H{}).
+		SetQuery(data).
+		BindJSON(&res).
+		Do()
+	if err != nil {
+		fmt.Println("请求失败: ", err)
+		return res, err
+	}
+	return res, nil
+}

+ 42 - 0
wallet/main_test.go

@@ -0,0 +1,42 @@
+package wallet_test
+
+import (
+	"fmt"
+	"testing"
+
+	"gogs.uu.mdfitnesscao.com/Algor/sdk"
+	"gogs.uu.mdfitnesscao.com/Algor/sdk/wallet"
+)
+
+func TestRegist(t *testing.T) {
+	t.Run("test1", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		pdfTemplates, err := wallet.Regist("RMzR6zvK")
+		fmt.Println(pdfTemplates, err)
+	})
+}
+
+func TestConsume(t *testing.T) {
+	t.Run("test1", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		pdfTemplates, err := wallet.Consume("RegistAAA", "RMzR6zvK", "M57wVRNZ", 1, 1, "")
+		fmt.Println(pdfTemplates, err)
+	})
+}
+
+func TestConsumeRollback(t *testing.T) {
+	t.Run("test12", func(t *testing.T) {
+		sdk.InitConfig(&sdk.ClientConfig{
+			ApiDomain: "https://mcapi.mdfitnesscao.com",
+			AppDebug:  true,
+		})
+		pdfTemplates, err := wallet.ConsumeRollback("RegistAAA", "")
+		fmt.Println(pdfTemplates, err)
+	})
+}