package survey import ( "fmt" "github.com/golang-module/carbon" "github.com/samber/lo" "gogs.uu.mdfitnesscao.com/cuiguohai/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 "" }