|
@@ -17,13 +17,9 @@
|
|
|
package av
|
|
|
|
|
|
import (
|
|
|
- "bytes"
|
|
|
- "github.com/siyuan-note/siyuan/kernel/util"
|
|
|
"math"
|
|
|
"sort"
|
|
|
"strconv"
|
|
|
- "strings"
|
|
|
- "time"
|
|
|
)
|
|
|
|
|
|
// LayoutTable 描述了表格布局的结构。
|
|
@@ -82,775 +78,6 @@ const (
|
|
|
CalcOperatorPercentUnchecked CalcOperator = "Percent unchecked"
|
|
|
)
|
|
|
|
|
|
-func (value *Value) Compare(other *Value) int {
|
|
|
- switch value.Type {
|
|
|
- case KeyTypeBlock:
|
|
|
- if nil != value.Block && nil != other.Block {
|
|
|
- ret := strings.Compare(value.Block.Content, other.Block.Content)
|
|
|
- if 0 == ret {
|
|
|
- ret = int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- return ret
|
|
|
- }
|
|
|
- case KeyTypeText:
|
|
|
- if nil != value.Text && nil != other.Text {
|
|
|
- ret := strings.Compare(value.Text.Content, other.Text.Content)
|
|
|
- if 0 == ret {
|
|
|
- ret = int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- return ret
|
|
|
- }
|
|
|
- case KeyTypeNumber:
|
|
|
- if nil != value.Number && nil != other.Number {
|
|
|
- if value.Number.IsNotEmpty {
|
|
|
- if !other.Number.IsNotEmpty {
|
|
|
- return 1
|
|
|
- }
|
|
|
-
|
|
|
- if value.Number.Content > other.Number.Content {
|
|
|
- return 1
|
|
|
- } else if value.Number.Content < other.Number.Content {
|
|
|
- return -1
|
|
|
- } else {
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- } else {
|
|
|
- if other.Number.IsNotEmpty {
|
|
|
- return -1
|
|
|
- }
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeDate:
|
|
|
- if nil != value.Date && nil != other.Date {
|
|
|
- if value.Date.IsNotEmpty {
|
|
|
- if !other.Date.IsNotEmpty {
|
|
|
- return 1
|
|
|
- }
|
|
|
- if value.Date.Content > other.Date.Content {
|
|
|
- return 1
|
|
|
- } else if value.Date.Content < other.Date.Content {
|
|
|
- return -1
|
|
|
- } else {
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- } else {
|
|
|
- if other.Date.IsNotEmpty {
|
|
|
- return -1
|
|
|
- }
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeCreated:
|
|
|
- if nil != value.Created && nil != other.Created {
|
|
|
- if value.Created.Content > other.Created.Content {
|
|
|
- return 1
|
|
|
- } else if value.Created.Content < other.Created.Content {
|
|
|
- return -1
|
|
|
- } else {
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeUpdated:
|
|
|
- if nil != value.Updated && nil != other.Updated {
|
|
|
- if value.Updated.Content > other.Updated.Content {
|
|
|
- return 1
|
|
|
- } else if value.Updated.Content < other.Updated.Content {
|
|
|
- return -1
|
|
|
- } else {
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeSelect, KeyTypeMSelect:
|
|
|
- if nil != value.MSelect && nil != other.MSelect {
|
|
|
- var v1 string
|
|
|
- for _, v := range value.MSelect {
|
|
|
- v1 += v.Content
|
|
|
- }
|
|
|
- var v2 string
|
|
|
- for _, v := range other.MSelect {
|
|
|
- v2 += v.Content
|
|
|
- }
|
|
|
- ret := strings.Compare(v1, v2)
|
|
|
- if 0 == ret {
|
|
|
- ret = int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- return ret
|
|
|
- }
|
|
|
- case KeyTypeURL:
|
|
|
- if nil != value.URL && nil != other.URL {
|
|
|
- ret := strings.Compare(value.URL.Content, other.URL.Content)
|
|
|
- if 0 == ret {
|
|
|
- ret = int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- return ret
|
|
|
- }
|
|
|
- case KeyTypeEmail:
|
|
|
- if nil != value.Email && nil != other.Email {
|
|
|
- ret := strings.Compare(value.Email.Content, other.Email.Content)
|
|
|
- if 0 == ret {
|
|
|
- ret = int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- return ret
|
|
|
- }
|
|
|
- case KeyTypePhone:
|
|
|
- if nil != value.Phone && nil != other.Phone {
|
|
|
- ret := strings.Compare(value.Phone.Content, other.Phone.Content)
|
|
|
- if 0 == ret {
|
|
|
- ret = int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- return ret
|
|
|
- }
|
|
|
- case KeyTypeMAsset:
|
|
|
- if nil != value.MAsset && nil != other.MAsset {
|
|
|
- var v1 string
|
|
|
- for _, v := range value.MAsset {
|
|
|
- v1 += v.Content
|
|
|
- }
|
|
|
- var v2 string
|
|
|
- for _, v := range other.MAsset {
|
|
|
- v2 += v.Content
|
|
|
- }
|
|
|
- ret := strings.Compare(v1, v2)
|
|
|
- if 0 == ret {
|
|
|
- ret = int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- return ret
|
|
|
- }
|
|
|
- case KeyTypeTemplate:
|
|
|
- if nil != value.Template && nil != other.Template {
|
|
|
- vContent := strings.TrimSpace(value.Template.Content)
|
|
|
- oContent := strings.TrimSpace(other.Template.Content)
|
|
|
- if util.IsNumeric(vContent) && util.IsNumeric(oContent) {
|
|
|
- v1, _ := strconv.ParseFloat(vContent, 64)
|
|
|
- v2, _ := strconv.ParseFloat(oContent, 64)
|
|
|
- if v1 > v2 {
|
|
|
- return 1
|
|
|
- }
|
|
|
- if v1 < v2 {
|
|
|
- return -1
|
|
|
- }
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- ret := strings.Compare(value.Template.Content, other.Template.Content)
|
|
|
- if 0 == ret {
|
|
|
- ret = int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- return ret
|
|
|
- }
|
|
|
- case KeyTypeCheckbox:
|
|
|
- if nil != value.Checkbox && nil != other.Checkbox {
|
|
|
- if value.Checkbox.Checked && !other.Checkbox.Checked {
|
|
|
- return 1
|
|
|
- }
|
|
|
- if !value.Checkbox.Checked && other.Checkbox.Checked {
|
|
|
- return -1
|
|
|
- }
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- case KeyTypeRelation:
|
|
|
- if nil != value.Relation && nil != other.Relation {
|
|
|
- vContentBuf := bytes.Buffer{}
|
|
|
- for _, c := range value.Relation.Contents {
|
|
|
- vContentBuf.WriteString(c.String())
|
|
|
- vContentBuf.WriteByte(' ')
|
|
|
- }
|
|
|
- vContent := strings.TrimSpace(vContentBuf.String())
|
|
|
- oContentBuf := bytes.Buffer{}
|
|
|
- for _, c := range other.Relation.Contents {
|
|
|
- oContentBuf.WriteString(c.String())
|
|
|
- oContentBuf.WriteByte(' ')
|
|
|
- }
|
|
|
- oContent := strings.TrimSpace(oContentBuf.String())
|
|
|
-
|
|
|
- if util.IsNumeric(vContent) && util.IsNumeric(oContent) {
|
|
|
- v1, _ := strconv.ParseFloat(vContent, 64)
|
|
|
- v2, _ := strconv.ParseFloat(oContent, 64)
|
|
|
- if v1 > v2 {
|
|
|
- return 1
|
|
|
- }
|
|
|
-
|
|
|
- if v1 < v2 {
|
|
|
- return -1
|
|
|
- }
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- ret := strings.Compare(vContent, oContent)
|
|
|
- if 0 == ret {
|
|
|
- ret = int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- return ret
|
|
|
- }
|
|
|
- case KeyTypeRollup:
|
|
|
- if nil != value.Rollup && nil != other.Rollup {
|
|
|
- vContentBuf := bytes.Buffer{}
|
|
|
- for _, c := range value.Rollup.Contents {
|
|
|
- vContentBuf.WriteString(c.String())
|
|
|
- vContentBuf.WriteByte(' ')
|
|
|
- }
|
|
|
- vContent := strings.TrimSpace(vContentBuf.String())
|
|
|
- oContentBuf := bytes.Buffer{}
|
|
|
- for _, c := range other.Rollup.Contents {
|
|
|
- oContentBuf.WriteString(c.String())
|
|
|
- oContentBuf.WriteByte(' ')
|
|
|
- }
|
|
|
- oContent := strings.TrimSpace(oContentBuf.String())
|
|
|
-
|
|
|
- if util.IsNumeric(vContent) && util.IsNumeric(oContent) {
|
|
|
- v1, _ := strconv.ParseFloat(vContent, 64)
|
|
|
- v2, _ := strconv.ParseFloat(oContent, 64)
|
|
|
- if v1 > v2 {
|
|
|
- return 1
|
|
|
- }
|
|
|
- if v1 < v2 {
|
|
|
- return -1
|
|
|
- }
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- ret := strings.Compare(vContent, oContent)
|
|
|
- if 0 == ret {
|
|
|
- ret = int(value.CreatedAt - other.CreatedAt)
|
|
|
- }
|
|
|
- return ret
|
|
|
- }
|
|
|
- }
|
|
|
- return int(value.CreatedAt - other.CreatedAt)
|
|
|
-}
|
|
|
-
|
|
|
-func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, rowID string) bool {
|
|
|
- if nil == filter || (nil == filter.Value && nil == filter.RelativeDate) {
|
|
|
- return true
|
|
|
- }
|
|
|
-
|
|
|
- if nil != filter.Value && value.Type != filter.Value.Type {
|
|
|
- // 由于字段类型被用户编辑过导致和过滤器值类型不匹配,该情况下不过滤
|
|
|
- return true
|
|
|
- }
|
|
|
-
|
|
|
- if nil != value.Rollup && KeyTypeRollup == value.Type && nil != filter && nil != filter.Value && KeyTypeRollup == filter.Value.Type &&
|
|
|
- nil != filter.Value.Rollup && 0 < len(filter.Value.Rollup.Contents) {
|
|
|
- // 单独处理汇总类型的比较
|
|
|
- key, _ := attrView.GetKey(value.KeyID)
|
|
|
- if nil == key {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- relKey, _ := attrView.GetKey(key.Rollup.RelationKeyID)
|
|
|
- if nil == relKey {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- relVal := attrView.GetValue(relKey.ID, rowID)
|
|
|
- if nil == relVal || nil == relVal.Relation {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- destAv, _ := ParseAttributeView(relKey.Relation.AvID)
|
|
|
- if nil == destAv {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- for _, blockID := range relVal.Relation.BlockIDs {
|
|
|
- destVal := destAv.GetValue(key.Rollup.KeyID, blockID)
|
|
|
- if nil == destVal {
|
|
|
- continue
|
|
|
- }
|
|
|
-
|
|
|
- if destVal.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) {
|
|
|
- return true
|
|
|
- }
|
|
|
- }
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- if nil != value.Relation && KeyTypeRelation == value.Type && 0 < len(value.Relation.Contents) && nil != filter && nil != filter.Value && KeyTypeRelation == filter.Value.Type &&
|
|
|
- nil != filter.Value.Relation && 0 < len(filter.Value.Relation.BlockIDs) {
|
|
|
- // 单独处理关联类型的比较
|
|
|
- for _, relationValue := range value.Relation.Contents {
|
|
|
- filterValue := &Value{Type: KeyTypeBlock, Block: &ValueBlock{Content: filter.Value.Relation.BlockIDs[0]}}
|
|
|
- if relationValue.filter(filterValue, filter.RelativeDate, filter.RelativeDate2, filter.Operator) {
|
|
|
- return true
|
|
|
- }
|
|
|
- }
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- return value.filter(filter.Value, filter.RelativeDate, filter.RelativeDate2, filter.Operator)
|
|
|
-}
|
|
|
-
|
|
|
-func (value *Value) filter(other *Value, relativeDate, relativeDate2 *RelativeDate, operator FilterOperator) bool {
|
|
|
- switch value.Type {
|
|
|
- case KeyTypeBlock:
|
|
|
- if nil != value.Block && nil != other && nil != other.Block {
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual:
|
|
|
- return value.Block.Content == other.Block.Content
|
|
|
- case FilterOperatorIsNotEqual:
|
|
|
- return value.Block.Content != other.Block.Content
|
|
|
- case FilterOperatorContains:
|
|
|
- return strings.Contains(value.Block.Content, other.Block.Content)
|
|
|
- case FilterOperatorDoesNotContain:
|
|
|
- return !strings.Contains(value.Block.Content, other.Block.Content)
|
|
|
- case FilterOperatorStartsWith:
|
|
|
- return strings.HasPrefix(value.Block.Content, other.Block.Content)
|
|
|
- case FilterOperatorEndsWith:
|
|
|
- return strings.HasSuffix(value.Block.Content, other.Block.Content)
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return "" == strings.TrimSpace(value.Block.Content)
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return "" != strings.TrimSpace(value.Block.Content)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeText:
|
|
|
- if nil != value.Text && nil != other && nil != other.Text {
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual:
|
|
|
- if "" == strings.TrimSpace(other.Text.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return value.Text.Content == other.Text.Content
|
|
|
- case FilterOperatorIsNotEqual:
|
|
|
- if "" == strings.TrimSpace(other.Text.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return value.Text.Content != other.Text.Content
|
|
|
- case FilterOperatorContains:
|
|
|
- if "" == strings.TrimSpace(other.Text.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return strings.Contains(value.Text.Content, other.Text.Content)
|
|
|
- case FilterOperatorDoesNotContain:
|
|
|
- if "" == strings.TrimSpace(other.Text.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return !strings.Contains(value.Text.Content, other.Text.Content)
|
|
|
- case FilterOperatorStartsWith:
|
|
|
- if "" == strings.TrimSpace(other.Text.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return strings.HasPrefix(value.Text.Content, other.Text.Content)
|
|
|
- case FilterOperatorEndsWith:
|
|
|
- if "" == strings.TrimSpace(other.Text.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return strings.HasSuffix(value.Text.Content, other.Text.Content)
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return "" == strings.TrimSpace(value.Text.Content)
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return "" != strings.TrimSpace(value.Text.Content)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeNumber:
|
|
|
- if nil != value.Number && nil != other && nil != other.Number {
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual:
|
|
|
- if !other.Number.IsNotEmpty {
|
|
|
- return true
|
|
|
- }
|
|
|
- return value.Number.Content == other.Number.Content
|
|
|
- case FilterOperatorIsNotEqual:
|
|
|
- if !other.Number.IsNotEmpty {
|
|
|
- return true
|
|
|
- }
|
|
|
- return value.Number.Content != other.Number.Content
|
|
|
- case FilterOperatorIsGreater:
|
|
|
- return value.Number.Content > other.Number.Content
|
|
|
- case FilterOperatorIsGreaterOrEqual:
|
|
|
- return value.Number.Content >= other.Number.Content
|
|
|
- case FilterOperatorIsLess:
|
|
|
- return value.Number.Content < other.Number.Content
|
|
|
- case FilterOperatorIsLessOrEqual:
|
|
|
- return value.Number.Content <= other.Number.Content
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return !value.Number.IsNotEmpty
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return value.Number.IsNotEmpty
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeDate:
|
|
|
- if nil != value.Date {
|
|
|
- if nil != relativeDate {
|
|
|
- // 使用相对时间比较
|
|
|
-
|
|
|
- count := relativeDate.Count
|
|
|
- unit := relativeDate.Unit
|
|
|
- direction := relativeDate.Direction
|
|
|
- relativeTimeStart, relativeTimeEnd := calcRelativeTimeRegion(count, unit, direction)
|
|
|
- _, relativeTimeEnd2 := calcRelativeTimeRegion(relativeDate2.Count, relativeDate2.Unit, relativeDate2.Direction)
|
|
|
- return filterTime(value.Date.Content, value.Date.IsNotEmpty, relativeTimeStart, relativeTimeEnd, relativeTimeEnd2, operator)
|
|
|
- } else { // 使用具体时间比较
|
|
|
- if nil == other.Date {
|
|
|
- return true
|
|
|
- }
|
|
|
-
|
|
|
- otherTime := time.UnixMilli(other.Date.Content)
|
|
|
- otherStart := time.Date(otherTime.Year(), otherTime.Month(), otherTime.Day(), 0, 0, 0, 0, otherTime.Location())
|
|
|
- otherEnd := time.Date(otherTime.Year(), otherTime.Month(), otherTime.Day(), 23, 59, 59, 999999999, otherTime.Location())
|
|
|
- return filterTime(value.Date.Content, value.Date.IsNotEmpty, otherStart, otherEnd, time.Now(), operator)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeCreated:
|
|
|
- if nil != value.Created {
|
|
|
- if nil != relativeDate {
|
|
|
- // 使用相对时间比较
|
|
|
-
|
|
|
- count := relativeDate.Count
|
|
|
- unit := relativeDate.Unit
|
|
|
- direction := relativeDate.Direction
|
|
|
- relativeTimeStart, relativeTimeEnd := calcRelativeTimeRegion(count, unit, direction)
|
|
|
- return filterTime(value.Created.Content, true, relativeTimeStart, relativeTimeEnd, time.Now(), operator)
|
|
|
- } else { // 使用具体时间比较
|
|
|
- if nil == other.Created {
|
|
|
- return true
|
|
|
- }
|
|
|
-
|
|
|
- otherTime := time.UnixMilli(other.Created.Content)
|
|
|
- otherStart := time.Date(otherTime.Year(), otherTime.Month(), otherTime.Day(), 0, 0, 0, 0, otherTime.Location())
|
|
|
- otherEnd := time.Date(otherTime.Year(), otherTime.Month(), otherTime.Day(), 23, 59, 59, 999999999, otherTime.Location())
|
|
|
- return filterTime(value.Created.Content, value.Created.IsNotEmpty, otherStart, otherEnd, time.Now(), operator)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeUpdated:
|
|
|
- if nil != value.Updated {
|
|
|
- if nil != relativeDate {
|
|
|
- // 使用相对时间比较
|
|
|
-
|
|
|
- count := relativeDate.Count
|
|
|
- unit := relativeDate.Unit
|
|
|
- direction := relativeDate.Direction
|
|
|
- relativeTimeStart, relativeTimeEnd := calcRelativeTimeRegion(count, unit, direction)
|
|
|
- return filterTime(value.Updated.Content, true, relativeTimeStart, relativeTimeEnd, time.Now(), operator)
|
|
|
- } else { // 使用具体时间比较
|
|
|
- if nil == other.Updated {
|
|
|
- return true
|
|
|
- }
|
|
|
-
|
|
|
- otherTime := time.UnixMilli(other.Updated.Content)
|
|
|
- otherStart := time.Date(otherTime.Year(), otherTime.Month(), otherTime.Day(), 0, 0, 0, 0, otherTime.Location())
|
|
|
- otherEnd := time.Date(otherTime.Year(), otherTime.Month(), otherTime.Day(), 23, 59, 59, 999999999, otherTime.Location())
|
|
|
- return filterTime(value.Updated.Content, value.Updated.IsNotEmpty, otherStart, otherEnd, time.Now(), operator)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeSelect, KeyTypeMSelect:
|
|
|
- if nil != value.MSelect {
|
|
|
- if nil != other && nil != other.MSelect {
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual, FilterOperatorContains:
|
|
|
- contains := false
|
|
|
- for _, v := range value.MSelect {
|
|
|
- for _, v2 := range other.MSelect {
|
|
|
- if v.Content == v2.Content {
|
|
|
- contains = true
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return contains
|
|
|
- case FilterOperatorIsNotEqual, FilterOperatorDoesNotContain:
|
|
|
- contains := false
|
|
|
- for _, v := range value.MSelect {
|
|
|
- for _, v2 := range other.MSelect {
|
|
|
- if v.Content == v2.Content {
|
|
|
- contains = true
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return !contains
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return 0 == len(value.MSelect) || 1 == len(value.MSelect) && "" == value.MSelect[0].Content
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return 0 != len(value.MSelect) && !(1 == len(value.MSelect) && "" == value.MSelect[0].Content)
|
|
|
- }
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- // 没有设置比较值
|
|
|
-
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual, FilterOperatorIsNotEqual, FilterOperatorContains, FilterOperatorDoesNotContain:
|
|
|
- return true
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return 0 == len(value.MSelect) || 1 == len(value.MSelect) && "" == value.MSelect[0].Content
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return 0 != len(value.MSelect) && !(1 == len(value.MSelect) && "" == value.MSelect[0].Content)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeURL:
|
|
|
- if nil != value.URL && nil != other && nil != other.URL {
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual:
|
|
|
- return value.URL.Content == other.URL.Content
|
|
|
- case FilterOperatorIsNotEqual:
|
|
|
- return value.URL.Content != other.URL.Content
|
|
|
- case FilterOperatorContains:
|
|
|
- return strings.Contains(value.URL.Content, other.URL.Content)
|
|
|
- case FilterOperatorDoesNotContain:
|
|
|
- return !strings.Contains(value.URL.Content, other.URL.Content)
|
|
|
- case FilterOperatorStartsWith:
|
|
|
- return strings.HasPrefix(value.URL.Content, other.URL.Content)
|
|
|
- case FilterOperatorEndsWith:
|
|
|
- return strings.HasSuffix(value.URL.Content, other.URL.Content)
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return "" == strings.TrimSpace(value.URL.Content)
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return "" != strings.TrimSpace(value.URL.Content)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeEmail:
|
|
|
- if nil != value.Email && nil != other && nil != other.Email {
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual:
|
|
|
- return value.Email.Content == other.Email.Content
|
|
|
- case FilterOperatorIsNotEqual:
|
|
|
- return value.Email.Content != other.Email.Content
|
|
|
- case FilterOperatorContains:
|
|
|
- return strings.Contains(value.Email.Content, other.Email.Content)
|
|
|
- case FilterOperatorDoesNotContain:
|
|
|
- return !strings.Contains(value.Email.Content, other.Email.Content)
|
|
|
- case FilterOperatorStartsWith:
|
|
|
- return strings.HasPrefix(value.Email.Content, other.Email.Content)
|
|
|
- case FilterOperatorEndsWith:
|
|
|
- return strings.HasSuffix(value.Email.Content, other.Email.Content)
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return "" == strings.TrimSpace(value.Email.Content)
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return "" != strings.TrimSpace(value.Email.Content)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypePhone:
|
|
|
- if nil != value.Phone && nil != other && nil != other.Phone {
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual:
|
|
|
- return value.Phone.Content == other.Phone.Content
|
|
|
- case FilterOperatorIsNotEqual:
|
|
|
- return value.Phone.Content != other.Phone.Content
|
|
|
- case FilterOperatorContains:
|
|
|
- return strings.Contains(value.Phone.Content, other.Phone.Content)
|
|
|
- case FilterOperatorDoesNotContain:
|
|
|
- return !strings.Contains(value.Phone.Content, other.Phone.Content)
|
|
|
- case FilterOperatorStartsWith:
|
|
|
- return strings.HasPrefix(value.Phone.Content, other.Phone.Content)
|
|
|
- case FilterOperatorEndsWith:
|
|
|
- return strings.HasSuffix(value.Phone.Content, other.Phone.Content)
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return "" == strings.TrimSpace(value.Phone.Content)
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return "" != strings.TrimSpace(value.Phone.Content)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeMAsset:
|
|
|
- if nil != value.MAsset && nil != other && nil != other.MAsset && 0 < len(value.MAsset) && 0 < len(other.MAsset) {
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual, FilterOperatorContains:
|
|
|
- contains := false
|
|
|
- for _, v := range value.MAsset {
|
|
|
- for _, v2 := range other.MAsset {
|
|
|
- if v.Content == v2.Content {
|
|
|
- contains = true
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return contains
|
|
|
- case FilterOperatorIsNotEqual, FilterOperatorDoesNotContain:
|
|
|
- contains := false
|
|
|
- for _, v := range value.MAsset {
|
|
|
- for _, v2 := range other.MAsset {
|
|
|
- if v.Content == v2.Content {
|
|
|
- contains = true
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return !contains
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return 0 == len(value.MAsset) || 1 == len(value.MAsset) && "" == value.MAsset[0].Content
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return 0 != len(value.MAsset) && !(1 == len(value.MAsset) && "" == value.MAsset[0].Content)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeTemplate:
|
|
|
- if nil != value.Template && nil != other && nil != other.Template {
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual:
|
|
|
- if "" == strings.TrimSpace(other.Template.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return value.Template.Content == other.Template.Content
|
|
|
- case FilterOperatorIsNotEqual:
|
|
|
- if "" == strings.TrimSpace(other.Template.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return value.Template.Content != other.Template.Content
|
|
|
- case FilterOperatorIsGreater:
|
|
|
- if "" == strings.TrimSpace(other.Template.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return value.Template.Content > other.Template.Content
|
|
|
- case FilterOperatorIsGreaterOrEqual:
|
|
|
- if "" == strings.TrimSpace(other.Template.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return value.Template.Content >= other.Template.Content
|
|
|
- case FilterOperatorIsLess:
|
|
|
- if "" == strings.TrimSpace(other.Template.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return value.Template.Content < other.Template.Content
|
|
|
- case FilterOperatorIsLessOrEqual:
|
|
|
- if "" == strings.TrimSpace(other.Template.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return value.Template.Content <= other.Template.Content
|
|
|
- case FilterOperatorContains:
|
|
|
- if "" == strings.TrimSpace(other.Template.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return strings.Contains(value.Template.Content, other.Template.Content)
|
|
|
- case FilterOperatorDoesNotContain:
|
|
|
- if "" == strings.TrimSpace(other.Template.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return !strings.Contains(value.Template.Content, other.Template.Content)
|
|
|
- case FilterOperatorStartsWith:
|
|
|
- if "" == strings.TrimSpace(other.Template.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return strings.HasPrefix(value.Template.Content, other.Template.Content)
|
|
|
- case FilterOperatorEndsWith:
|
|
|
- if "" == strings.TrimSpace(other.Template.Content) {
|
|
|
- return true
|
|
|
- }
|
|
|
- return strings.HasSuffix(value.Template.Content, other.Template.Content)
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return "" == strings.TrimSpace(value.Template.Content)
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return "" != strings.TrimSpace(value.Template.Content)
|
|
|
- }
|
|
|
- }
|
|
|
- case KeyTypeCheckbox:
|
|
|
- if nil != value.Checkbox {
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsTrue:
|
|
|
- return value.Checkbox.Checked
|
|
|
- case FilterOperatorIsFalse:
|
|
|
- return !value.Checkbox.Checked
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return false
|
|
|
-}
|
|
|
-
|
|
|
-func filterTime(valueMills int64, valueIsNotEmpty bool, otherValueStart, otherValueEnd, otherValueEnd2 time.Time, operator FilterOperator) bool {
|
|
|
- valueTime := time.UnixMilli(valueMills)
|
|
|
- switch operator {
|
|
|
- case FilterOperatorIsEqual:
|
|
|
- return (valueTime.After(otherValueStart) || valueTime.Equal(otherValueStart)) && valueTime.Before(otherValueEnd)
|
|
|
- case FilterOperatorIsNotEqual:
|
|
|
- return valueTime.Before(otherValueStart) || valueTime.After(otherValueEnd)
|
|
|
- case FilterOperatorIsGreater:
|
|
|
- return valueTime.After(otherValueEnd) || valueTime.Equal(otherValueEnd)
|
|
|
- case FilterOperatorIsGreaterOrEqual:
|
|
|
- return valueTime.After(otherValueStart) || valueTime.Equal(otherValueStart)
|
|
|
- case FilterOperatorIsLess:
|
|
|
- return valueTime.Before(otherValueStart)
|
|
|
- case FilterOperatorIsLessOrEqual:
|
|
|
- return valueTime.Before(otherValueEnd) || valueTime.Equal(otherValueEnd)
|
|
|
- case FilterOperatorIsBetween:
|
|
|
- return (valueTime.After(otherValueStart) || valueTime.Equal(otherValueStart)) && (valueTime.Before(otherValueEnd2) || valueTime.Equal(otherValueEnd2))
|
|
|
- case FilterOperatorIsEmpty:
|
|
|
- return !valueIsNotEmpty
|
|
|
- case FilterOperatorIsNotEmpty:
|
|
|
- return valueIsNotEmpty
|
|
|
- }
|
|
|
- return false
|
|
|
-}
|
|
|
-
|
|
|
-// 根据 Count、Unit 和 Direction 计算相对当前时间的开始时间和结束时间
|
|
|
-func calcRelativeTimeRegion(count int, unit RelativeDateUnit, direction RelativeDateDirection) (start, end time.Time) {
|
|
|
- now := time.Now()
|
|
|
- switch unit {
|
|
|
- case RelativeDateUnitDay:
|
|
|
- switch direction {
|
|
|
- case RelativeDateDirectionBefore:
|
|
|
- // 结束时间使用今天的开始时间
|
|
|
- end = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
|
|
- // 开始时间使用结束时间减去 count 天
|
|
|
- start = end.AddDate(0, 0, -count)
|
|
|
- case RelativeDateDirectionThis:
|
|
|
- // 开始时间使用今天的开始时间
|
|
|
- start = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
|
|
- // 结束时间使用开始时间加上 count 天
|
|
|
- end = start.AddDate(0, 0, count)
|
|
|
- case RelativeDateDirectionAfter:
|
|
|
- // 开始时间使用今天的结束时间
|
|
|
- start = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 999999999, now.Location())
|
|
|
- // 结束时间使用开始时间加上 count 天
|
|
|
- end = start.AddDate(0, 0, count)
|
|
|
- }
|
|
|
- case RelativeDateUnitWeek:
|
|
|
- weekday := int(now.Weekday())
|
|
|
- if 0 == weekday {
|
|
|
- weekday = 7
|
|
|
- }
|
|
|
- switch direction {
|
|
|
- case RelativeDateDirectionBefore:
|
|
|
- // 结束时间使用本周的开始时间
|
|
|
- end = time.Date(now.Year(), now.Month(), now.Day()-weekday, 0, 0, 0, 0, now.Location())
|
|
|
- // 开始时间使用结束时间减去 count*7 天
|
|
|
- start = end.AddDate(0, 0, -count*7)
|
|
|
- case RelativeDateDirectionThis:
|
|
|
- // 开始时间使用本周的开始时间
|
|
|
- start = time.Date(now.Year(), now.Month(), now.Day()-weekday, 0, 0, 0, 0, now.Location())
|
|
|
- // 结束时间使用开始时间加上 count*7 天
|
|
|
- end = start.AddDate(0, 0, count*7)
|
|
|
- case RelativeDateDirectionAfter:
|
|
|
- // 开始时间使用本周的结束时间
|
|
|
- start = time.Date(now.Year(), now.Month(), now.Day()-weekday+7, 23, 59, 59, 999999999, now.Location())
|
|
|
- // 结束时间使用开始时间加上 count*7 天
|
|
|
- end = start.AddDate(0, 0, count*7)
|
|
|
- }
|
|
|
- case RelativeDateUnitMonth:
|
|
|
- switch direction {
|
|
|
- case RelativeDateDirectionBefore:
|
|
|
- // 结束时间使用本月的开始时间
|
|
|
- end = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
|
|
- // 开始时间使用结束时间减去 count 个月
|
|
|
- start = end.AddDate(0, -count, 0)
|
|
|
- case RelativeDateDirectionThis:
|
|
|
- // 开始时间使用本月的开始时间
|
|
|
- start = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
|
|
- // 结束时间使用开始时间加上 count 个月
|
|
|
- end = start.AddDate(0, count, 0)
|
|
|
- case RelativeDateDirectionAfter:
|
|
|
- // 开始时间使用本月的结束时间
|
|
|
- start = time.Date(now.Year(), now.Month()+1, 1, 0, 0, 0, 0, now.Location()).Add(-time.Nanosecond)
|
|
|
- // 结束时间使用开始时间加上 count 个月
|
|
|
- end = start.AddDate(0, count, 0)
|
|
|
- }
|
|
|
- case RelativeDateUnitYear:
|
|
|
- switch direction {
|
|
|
- case RelativeDateDirectionBefore:
|
|
|
- // 结束时间使用今年的开始时间
|
|
|
- end = time.Date(now.Year(), 1, 1, 0, 0, 0, 0, now.Location())
|
|
|
- // 开始时间使用结束时间减去 count 年
|
|
|
- start = end.AddDate(-count, 0, 0)
|
|
|
- case RelativeDateDirectionThis:
|
|
|
- // 开始时间使用今年的开始时间
|
|
|
- start = time.Date(now.Year(), 1, 1, 0, 0, 0, 0, now.Location())
|
|
|
- // 结束时间使用开始时间加上 count 年
|
|
|
- end = start.AddDate(count, 0, 0)
|
|
|
- case RelativeDateDirectionAfter:
|
|
|
- // 开始时间使用今年的结束时间
|
|
|
- start = time.Date(now.Year()+1, 1, 1, 0, 0, 0, 0, now.Location()).Add(-time.Nanosecond)
|
|
|
- // 结束时间使用开始时间加上 count 年
|
|
|
- end = start.AddDate(count, 0, 0)
|
|
|
- }
|
|
|
- }
|
|
|
- return
|
|
|
-}
|
|
|
-
|
|
|
// Table 描述了表格实例的结构。
|
|
|
type Table struct {
|
|
|
ID string `json:"id"` // 表格布局 ID
|