| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 | package bootableimport (	"encoding/json"	"strconv"	"golib/features/mo"	"golib/infra/ii")func objectToStr(row mo.M) string {	b, err := json.Marshal(row)	if err != nil {		return err.Error()	}	return string(b)}func handleRow(info *ii.ItemInfo, row mo.M) {	handleTypeDateTime(info, row)	handleTypeFloat(info, row)	handleTypeArray(info, row)	handleFieldLookup(info, row)	handleTypeObject(info, row)}func handleTypeDateTime(info *ii.ItemInfo, row mo.M) {	for _, field := range info.FieldType(mo.TypeDate) {		oldValue, ok := row[field.Name].(mo.DateTime)		if !ok {			continue		}		if oldValue == 0 {			row[field.Name] = ""		}	}}func handleTypeFloat(info *ii.ItemInfo, row mo.M) {	for _, field := range info.FieldType(mo.TypeDouble) {		if field.Decimal <= 0 {			continue		}		oldValue, ok := row[field.Name].(float64)		if !ok {			continue		}		newValue, err := field.Convert(oldValue)		if err == nil {			row[field.Name] = newValue		}	}}func handleTypeObject(info *ii.ItemInfo, row mo.M) {	for _, field := range info.FieldType(mo.TypeObject) {		oldMap, ok := row[field.Name].(mo.M)		if !ok {			continue		}		for k, v := range oldMap {			row[field.Name+"."+k] = v		}		row[field.Name] = objectToStr(oldMap)	}}func handleTypeArray(info *ii.ItemInfo, row mo.M) {	for _, field := range info.FieldType(mo.TypeArray) {		if field.Items == ii.FieldItemsObject {			oldList, ok := row[field.Name].(mo.A)			if !ok {				continue			}			for i := 0; i < len(oldList); i++ {				oldMap, o := oldList[i].(mo.M)				if !o {					continue				}				m := make(mo.M, len(oldMap))				for k, v := range oldMap {					subField, fo := field.SubField(k)					if !fo {						continue					}					subFieldName := field.Name + "." + strconv.Itoa(i) + "." + subField.Name					subFieldLabel := subFieldName + "." + ii.FieldLabel					m[subFieldName] = v					row[subFieldName] = v					if subField.Label != "" {						m[subFieldLabel] = subField.Label						row[subFieldLabel] = subField.Label					}				}				oldList[i] = m			}			row[field.Name] = oldList		}	}}func handleFieldLookup(info *ii.ItemInfo, row mo.M) {	for _, field := range info.Fields {		if !field.HasLookup() {			continue		}		oldList, ok := row[field.Lookup.AS].(mo.A)		if !ok {			continue		}		// 仅 List == false 时才展开数据		if field.Lookup.List || len(oldList) == 0 {			continue		}		for k, v := range oldList[0].(mo.M) {			row[field.Name+"."+field.Lookup.AS+"."+k] = v		}	}}// getLookupResult 查询 rows 包含 asName 结果的数据的索引// MongoDB 会对 $lookup 指令始终返回 asName 字段, 该字段数据类型始终为 mo.Afunc getLookupResult(asName []string, resp *Response) {	row := make([]mo.M, 0, len(resp.Rows))	for _, as := range asName {		for i := 0; i < len(resp.Rows); i++ {			list, ok := resp.Rows[i][as]			if !ok {				panic("as name not found in row")			}			if len(list.(mo.A)) > 0 {				row = append(row, resp.Rows[i])			}		}	}	resp.Rows = row}
 |