作者 yangfu

Merge branch 'dev'

# Conflicts:
#	cmd/chart-server/api/etc/core.yaml
正在显示 66 个修改的文件 包含 3186 行增加122 行删除
... ... @@ -24,6 +24,7 @@ _testmain.go
.log
.idea
.vscode
cmd/chart-server/api/go_build_bchart
app.log
#go.sum
... ...
... ... @@ -6,6 +6,8 @@ ARG PROJECT=core
WORKDIR /build
COPY . .
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk update --no-cache && apk add --no-cache tzdata
RUN go env -w GO111MODULE=on \
&& go env -w GOPROXY=https://goproxy.cn,direct \
&& go env -w CGO_ENABLED=0 \
... ... @@ -28,7 +30,9 @@ LABEL org.opencontainers.image.authors=${AUTHOR}
WORKDIR /app
ENV PROJECT=${PROJECT}
ENV CONFIG_FILE=${CONFIG_FILE}
ENV TZ Asia/Shanghai
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
COPY --from=builder /build/api/${PROJECT} ./
COPY --from=builder /build/cmd/chart-server/api/etc/${CONFIG_FILE} ./etc/
COPY --from=builder /build/cmd/chart-server/api/public ./public/
... ...
... ... @@ -5,7 +5,8 @@ ARG PROJECT=core
WORKDIR /build
COPY . .
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk update --no-cache && apk add --no-cache tzdata
RUN go env -w GO111MODULE=on \
&& go env -w GOPROXY=https://goproxy.cn,direct \
&& go env -w CGO_ENABLED=0 \
... ... @@ -28,7 +29,9 @@ LABEL org.opencontainers.image.authors=${AUTHOR}
WORKDIR /app
ENV PROJECT=${PROJECT}
ENV CONFIG_FILE=${CONFIG_FILE}
ENV TZ Asia/Shanghai
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
COPY --from=builder /build/api/${PROJECT} ./
COPY --from=builder /build/cmd/chart-server/api/etc/${CONFIG_FILE} ./etc/
COPY --from=builder /build/cmd/chart-server/api/public ./public/
... ...
go_build_bchart
\ No newline at end of file
... ...
... ... @@ -2,17 +2,18 @@ package main
import (
"flag"
"github.com/golang-jwt/jwt/v4/request"
"github.com/zeromicro/go-queue/kq"
"github.com/zeromicro/go-zero/core/logx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/config"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/handler"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/logic/consumer"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"net/http"
"strings"
"github.com/golang-jwt/jwt/v4/request"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/config"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/handler"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
"time"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/rest"
... ... @@ -54,9 +55,33 @@ func main() {
ctx := svc.NewServiceContext(c)
handler.RegisterHandlers(server, ctx)
handler.RegisterExternalHandlers(server, ctx)
db.Migrate(ctx.DB)
//启动消费队列
startConsume(ctx)
logx.Infof("Starting server at %s:%d... \n", c.Host, c.Port)
server.Start()
}
func startConsume(svcCtx *svc.ServiceContext) {
//kafka消费队列 处理字库推送事件
go func() {
queue, err := kq.NewQueue(svcCtx.Config.KqConsumerConf, consumer.NewByteNoticeLogic(svcCtx))
if err != nil {
panic(err)
} else {
queue.Start()
}
}()
//redis消费队列 处理表数据存储到本地
go func() {
for {
str, err := svcCtx.Redis.Rpop(svcCtx.Config.Name + ":table_data")
if err == nil {
_ = consumer.NewByteTableDataLogic(svcCtx).Sync(str)
}
time.Sleep(3 * time.Second)
}
}()
}
... ...
Name: chart
Host: 0.0.0.0
Port: 8080
Verbose: true
Verbose: false
HostName: http://sumifcc-bchart-dev.sumifcc.com
Timeout: 30000
LogRequest: true # 记录详细请求日志
Log:
Mode: file
Encoding: plain
Level: debug # info
MaxSize: 1 # 2MB
TimeFormat: 2006-01-02 15:04:05.000
MaxContentLength: 5120 # 5KB
JwtAuth:
AccessSecret: digital-platform
Expire: 360000
ApiAuth:
Name: ApiAuth
Host: http://digital-platform-dev.fjmaimaimai.com
Timeout: 0s
Redis:
Host: 192.168.0.243:6379
Type: node
... ... @@ -24,3 +34,10 @@ ByteMetadata:
Name: ApiByteMetadata
Host: http://character-library-metadata-bastion-test.fjmaimaimai.com
Timeout: 0s
KqConsumerConf:
Name: KqConsumer
Brokers:
- 47.97.5.102:9092
Group: bchart_dev
Topic: allied_creation_metadata_table_sync_notice
Processors: 1
\ No newline at end of file
... ...
... ... @@ -3,6 +3,7 @@ Host: 0.0.0.0
Port: 8080
Verbose: false
HostName: http://sumifcc-bchart.sumifcc.com
LogRequest: true # 记录详细请求日志
Log:
Mode: file
... ... @@ -13,6 +14,11 @@ JwtAuth:
AccessSecret: digital-platform
Expire: 360000
ApiAuth:
Name: ApiAuth
Host: https://digital-platform.sumifcc.com
Timeout: 0s
Redis:
Host: 192.168.0.243:30379
Type: node
... ...
Name: chart
Host: 0.0.0.0
Port: 8081
Verbose: true
Verbose: false
HostName: http://sumifcc-bchart-dev.sumifcc.com
Timeout: 30000
LogRequest: true # 记录详细请求日志
Log:
#Mode: file
Mode: file
Encoding: plain
Level: debug # info
MaxSize: 1 # 2MB
TimeFormat: 2006-01-02 15:04:05.000
MaxContentLength: 5120 # 5KB
JwtAuth:
AccessSecret: digital-platform
Expire: 360000
ApiAuth:
Name: ApiAuth
Host: http://digital-platform-dev.fjmaimaimai.com
Timeout: 0s
Redis:
Host: 192.168.0.245:6379
Type: node
... ... @@ -27,3 +35,11 @@ ByteMetadata:
Host1: http://127.0.0.1:8080
Host: https://character-library-metadata-bastion-prd.fjmaimaimai.com
Timeout: 0s
KqConsumerConf:
Name: KqConsumer
Brokers:
- 47.97.5.102:9092
Group: bchart_local
Topic: allied_creation_metadata_table_sync_notice
Processors: 1
... ...
package config
import (
"github.com/zeromicro/go-queue/kq"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/rest"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/config"
... ... @@ -12,7 +13,10 @@ type Config struct {
config.Config
Redis redis.RedisConf `json:",optional"`
ByteMetadata ApiService
ApiAuth ApiService
LogRequest bool `json:",optional,default=true"`
HostName string // 服务域名
KqConsumerConf kq.KqConf
}
type ApiService struct {
... ...
package handler
import (
"github.com/zeromicro/go-zero/rest"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/openapi/rd"
)
func RegisterExternalHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(rd.Routers(serverCtx.Redis, serverCtx.Config.Name))
}
... ...
... ... @@ -16,6 +16,8 @@ import (
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.LoginStatusCheck, serverCtx.LogRequest},
[]rest.Route{
{
Method: http.MethodPost,
... ... @@ -57,12 +59,15 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/chart/components/search",
Handler: chart.SearchChartComponentsHandler(serverCtx),
},
},
}...,
),
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/v1"),
)
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.LogRequest},
[]rest.Route{
{
Method: http.MethodPost,
... ... @@ -74,7 +79,8 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/chart/:id",
Handler: chart.GetChartHandler(serverCtx),
},
},
}...,
),
rest.WithPrefix("/v1"),
)
... ... @@ -95,23 +101,33 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/table/data",
Handler: table.SearchTableDataHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/table/sync",
Handler: table.SyncTableHandler(serverCtx),
},
},
rest.WithPrefix("/v1"),
)
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.LoginStatusCheck, serverCtx.LogRequest},
[]rest.Route{
{
Method: http.MethodPost,
Path: "/table/search-by-module",
Handler: table.SearchTableByModuleHandler(serverCtx),
},
},
}...,
),
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/v1"),
)
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.LoginStatusCheck, serverCtx.LogRequest},
[]rest.Route{
{
Method: http.MethodPost,
... ... @@ -143,12 +159,15 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/app-page/create-share",
Handler: page.CreateAppPageShareUrlHandler(serverCtx),
},
},
}...,
),
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/v1"),
)
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.LogRequest},
[]rest.Route{
{
Method: http.MethodGet,
... ... @@ -160,7 +179,8 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/api/app-page/get-share-detail/:key",
Handler: page.GetAppPageShareDetailHandler(serverCtx),
},
},
}...,
),
rest.WithPrefix("/v1"),
)
... ...
package table
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/logic/table"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
)
func SyncTableHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := table.NewSyncTableLogic(r.Context(), svcCtx)
resp, err := l.SyncTable()
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}
... ...
... ... @@ -3,6 +3,7 @@ package chart
import (
"context"
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/contextdata"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/xerr"
... ... @@ -35,6 +36,7 @@ func (l *DeleteChartLogic) DeleteChart(req *types.ChartDeleteRequest) (resp *typ
appPage *domain.AppPage
)
resp = &types.ChartDeleteResponse{}
if chart, err = l.svcCtx.ChartRepository.FindOne(l.ctx, conn, req.Id); err != nil {
return nil, xerr.NewErrMsgErr("不存在", err)
}
... ... @@ -48,9 +50,29 @@ func (l *DeleteChartLogic) DeleteChart(req *types.ChartDeleteRequest) (resp *typ
if appPage.Identify() != nil {
return nil, xerr.NewErrMsgErr(fmt.Sprintf("该图表已被页面\"%v\"引用", appPage.Name), err)
}
err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, conn transaction.Conn) error {
if chart, err = l.svcCtx.ChartRepository.Delete(l.ctx, conn, chart); err != nil {
return nil, xerr.NewErrMsgErr("删除失败", err)
return xerr.NewErrMsgErr("删除失败", err)
}
//删除数据源
chartSetting, err := l.svcCtx.ChartSettingRepository.FindOne(l.ctx, conn, chart.Id)
if err == nil && len(chartSetting.DataSourceIds) > 0 {
for _, sourceId := range chartSetting.DataSourceIds {
//删除数据源
err = DeleteObjectTable(l.ctx, l.svcCtx, conn, int(sourceId))
if err != nil {
return xerr.NewErrMsg("删除失败")
}
//删除分组
err = l.svcCtx.ObjectTableRepository.DeleteGroup(ctx, conn, tenantId, int(sourceId))
if err != nil {
return xerr.NewErrMsg("删除失败")
}
}
}
return nil
}, true)
resp = &types.ChartDeleteResponse{}
return
... ...
... ... @@ -2,6 +2,7 @@ package chart
import (
"context"
"encoding/json"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/contextdata"
... ... @@ -89,6 +90,16 @@ func (l *SaveChartLogic) SaveChart(req *types.ChartSaveRequest) (resp *types.Cha
}, true); err != nil {
return nil, xerr.NewErrMsgErr("创建失败", err)
}
if len(chartSetting.DataSourceIds) > 0 {
for _, sourceId := range chartSetting.DataSourceIds {
pusher := &types.SyncTableDataPusher{
CompanyId: tenantId,
ObjectId: int(sourceId),
}
mBytes, _ := json.Marshal(pusher)
_, _ = l.svcCtx.Redis.Lpush(l.svcCtx.Config.Name+":table_data", string(mBytes))
}
}
resp = &types.ChartSaveResponse{
Chart: types.NewChartItemWithSetting(chart, chartSetting),
}
... ...
... ... @@ -2,6 +2,8 @@ package chart
import (
"context"
"encoding/json"
"github.com/samber/lo"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/contextdata"
... ... @@ -41,6 +43,7 @@ func (l *UpdateChartLogic) UpdateChart(req *types.ChartUpdateRequest) (resp *typ
if chartSetting, err = l.svcCtx.ChartSettingRepository.FindOne(l.ctx, conn, req.Id); err != nil {
return nil, xerr.NewErrMsgErr("图表配置不存在", err)
}
oldDataSource := chartSetting.DataSourceIds
if err = transaction.UseTrans(l.ctx, l.svcCtx.DB, func(ctx context.Context, conn transaction.Conn) error {
if len(req.Cover) > 0 && chart.Cover != req.Cover {
... ... @@ -54,12 +57,81 @@ func (l *UpdateChartLogic) UpdateChart(req *types.ChartUpdateRequest) (resp *typ
chartSetting.TableAbility = chartProperty.TableAbility
chartSetting.Series = chartProperty.Series
chartSetting.Other = chartProperty.Other
chartSetting.DataSourceIds = chartProperty.GetAllDataSourceId()
if chartSetting, err = l.svcCtx.ChartSettingRepository.UpdateWithVersion(l.ctx, conn, chartSetting); err != nil {
return err
}
return nil
err = l.SyncTableData(tenantId, conn, chartSetting.DataSourceIds, oldDataSource)
return err
}, true); err != nil {
return nil, xerr.NewErrMsgErr("创建失败", err)
}
return
}
func (l *UpdateChartLogic) SyncTableData(tenantId int64, conn transaction.Conn, newDataSourceIds, oldDataSourceIds []int64) error {
if len(newDataSourceIds) > 0 {
for _, sourceId := range newDataSourceIds {
pusher := &types.SyncTableDataPusher{
CompanyId: tenantId,
ObjectId: int(sourceId),
}
mBytes, _ := json.Marshal(pusher)
_, _ = l.svcCtx.Redis.Lpush(l.svcCtx.Config.Name+":table_data", string(mBytes))
}
}
//对比更新前后数据源
left, right := lo.Difference(newDataSourceIds, oldDataSourceIds)
//同步
if len(left) > 0 {
for _, sourceId := range left {
pusher := &types.SyncTableDataPusher{
CompanyId: tenantId,
ObjectId: int(sourceId),
}
mBytes, _ := json.Marshal(pusher)
_, _ = l.svcCtx.Redis.Lpush(l.svcCtx.Config.Name+":table_data", string(mBytes))
}
}
//删除
if len(right) > 0 {
for _, sourceId := range right {
err := DeleteObjectTable(l.ctx, l.svcCtx, conn, int(sourceId))
if err != nil {
return err
}
}
}
return nil
}
func DeleteObjectTable(ctx context.Context, svcCtx *svc.ServiceContext, conn transaction.Conn, sourceId int) error {
//验证其他图表是否使用
used, err := svcCtx.ChartSettingRepository.CheckUseDataSource(ctx, conn, sourceId)
if err == nil && !used { //未使用,删除
err = svcCtx.ObjectTableDataRepository.DropTable(ctx, conn, sourceId)
if err != nil {
return err
}
//是否远程已删除
objectTable, err := svcCtx.ObjectTableRepository.FindOneByTableId(ctx, conn, sourceId)
if err == nil && objectTable.Id > 0 && objectTable.RemoteDeleted == 1 {
//删除表
_, err = svcCtx.ObjectTableRepository.Delete(ctx, conn, &domain.ObjectTable{Id: objectTable.Id, TableType: objectTable.TableType})
if err != nil {
return err
}
//删除字段
_, err = svcCtx.ObjectFieldRepository.Delete(ctx, conn, &domain.ObjectField{Id: int64(sourceId)})
if err != nil {
return err
}
//删除分组
err = svcCtx.ObjectTableRepository.DeleteGroup(ctx, conn, objectTable.CompanyId, objectTable.ParentId)
if err != nil {
return err
}
}
}
return nil
}
... ...
package consumer
import (
"context"
"encoding/json"
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/types"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
)
type ByteNoticeLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
conn transaction.Conn
}
func NewByteNoticeLogic(svcCtx *svc.ServiceContext) *ByteNoticeLogic {
return &ByteNoticeLogic{
ctx: context.Background(),
svcCtx: svcCtx,
conn: svcCtx.DefaultDBConn(),
}
}
func (logic *ByteNoticeLogic) Consume(key, value string) error {
fmt.Println(key, value)
notice := &domain.ObjectNotice{}
err := json.Unmarshal([]byte(value), notice)
if err != nil {
return err
}
//保存推送消息
_, err = logic.svcCtx.ObjectNoticeRepository.Insert(logic.ctx, logic.conn, notice)
if err != nil {
return err
}
//处理消息
err = transaction.UseTrans(logic.ctx, logic.conn.DB(), func(ctx context.Context, conn transaction.Conn) error {
return logic.handleNotice(conn, notice)
}, true)
//更新处理结果
if err != nil {
notice.Status = domain.ObjectNoticeStatusError
notice.Message = err.Error()
} else {
notice.Status = domain.ObjectNoticeStatusDone
notice.Message = "OK"
}
_, _ = logic.svcCtx.ObjectNoticeRepository.Update(logic.ctx, logic.conn, notice)
return err
}
// handleNotice 处理消息
func (logic *ByteNoticeLogic) handleNotice(conn transaction.Conn, notice *domain.ObjectNotice) error {
//是否删除消息
if notice.IsDeletedEvent() {
return logic.handleDelete(conn, notice)
}
accessToken, _ := types.TableAccessToken{CompanyId: notice.CompanyId}.GenerateToken()
//结构变更
if notice.StructChanged {
request := bytelib.ObjectTableSearchRequest{
Token: accessToken,
Module: bytelib.ModuleChartTemplate,
}
if notice.ObjectType == "导入模块" {
request.TableTypes = []string{bytelib.MainTable, bytelib.SubTable, bytelib.SideTable}
}
if notice.ObjectType == "拆解模块" {
request.TableTypes = []string{bytelib.SchemaTable}
request.ReturnGroupItem = true
}
if notice.ObjectType == "计算模块" {
request.TableTypes = []string{bytelib.CalculateItem, bytelib.CalculateSet}
request.ReturnGroupItem = true
request.ExcludeTables = []int{0}
}
list, err := logic.svcCtx.ByteMetadataService.ObjectTableSearch(logic.ctx, request)
if err != nil {
return err
}
tablePreview, err := logic.svcCtx.ByteMetadataService.TableDataPreview(logic.ctx, &bytelib.TableDataPreviewRequest{
Token: accessToken,
ObjectId: int64(notice.TableId),
ObjectType: bytelib.ObjectMetaTable,
Where: &bytelib.TableQueryWhere{
PageNumber: 1,
PageSize: 1,
},
UseCache: false,
HiddenData: false,
})
if err != nil || tablePreview.ObjectId <= 0 {
return nil
}
if len(list.List) > 0 {
objectTables := make([]*domain.ObjectTable, 0)
for _, item := range list.List {
if item.TableId == notice.TableId {
objectTables = append(objectTables, &domain.ObjectTable{
Id: item.Id,
TableId: item.TableId,
Name: item.Name,
TableType: item.TableType,
CompanyId: notice.CompanyId,
ParentId: item.ParentId,
Flag: item.Flag,
})
//父级节点
objectTables = append(objectTables, logic.getParents(notice.CompanyId, item.ParentId, list.List)...)
}
}
err = logic.saveTables(conn, objectTables)
if err != nil {
return err
}
}
//保存字段
_, err = logic.saveFields(conn, &domain.ObjectField{
Id: tablePreview.ObjectId,
Name: tablePreview.Name,
Fields: tablePreview.Fields,
})
if err != nil {
return err
}
}
//数据变更
if notice.DataChanged {
data := &types.SyncTableDataPusher{
CompanyId: notice.CompanyId,
ObjectId: notice.TableId,
}
mBytes, _ := json.Marshal(data)
_, err := logic.svcCtx.Redis.LpushCtx(logic.ctx, logic.svcCtx.Config.Name+":table_data", string(mBytes))
return err
}
return nil
}
func (logic *ByteNoticeLogic) getParents(companyId int64, parentId int, list []*bytelib.Table) []*domain.ObjectTable {
result := make([]*domain.ObjectTable, 0)
for _, item := range list {
if item.Id == parentId {
result = append(result, &domain.ObjectTable{
Id: item.Id,
TableId: item.TableId,
Name: item.Name,
TableType: item.TableType,
CompanyId: companyId,
ParentId: item.ParentId,
Flag: item.Flag,
})
if item.ParentId > 0 {
result = append(result, logic.getParents(companyId, item.ParentId, list)...)
}
}
}
return result
}
// handleDelete 删除
func (logic *ByteNoticeLogic) handleDelete(conn transaction.Conn, notice *domain.ObjectNotice) error {
objectTable, err := logic.svcCtx.ObjectTableRepository.FindOneByTableId(logic.ctx, conn, notice.TableId)
if err == nil && objectTable.Id > 0 {
objectTable.RemoteDeleted = 1
_, err := logic.svcCtx.ObjectTableRepository.Update(logic.ctx, conn, objectTable)
if err != nil {
return err
}
//是否有使用数据源
used, err := logic.svcCtx.ChartSettingRepository.CheckUseDataSource(logic.ctx, conn, notice.TableId)
if err == nil && !used {
err = logic.svcCtx.ObjectTableDataRepository.DropTable(logic.ctx, conn, notice.TableId)
if err != nil {
return err
}
//删除表
_, err = logic.svcCtx.ObjectTableRepository.Delete(logic.ctx, conn, objectTable)
if err != nil {
return err
}
//删除字段
_, err = logic.svcCtx.ObjectFieldRepository.Delete(logic.ctx, conn, &domain.ObjectField{Id: int64(objectTable.Id)})
if err != nil {
return err
}
//删除分组
err = logic.svcCtx.ObjectTableRepository.DeleteGroup(logic.ctx, conn, objectTable.CompanyId, objectTable.ParentId)
if err != nil {
return err
}
}
}
return nil
}
// saveTables 保存表结构
func (logic *ByteNoticeLogic) saveTables(conn transaction.Conn, tables []*domain.ObjectTable) error {
if len(tables) > 0 {
for _, item := range tables {
objectTable, err := logic.svcCtx.ObjectTableRepository.FindOne(logic.ctx, conn, item.Id, item.TableType)
if err == nil && objectTable.Id > 0 {
item.Id = objectTable.Id
item.Version = objectTable.Version + 1
_, err := logic.svcCtx.ObjectTableRepository.Update(logic.ctx, conn, item)
if err != nil {
return err
}
} else {
_, err := logic.svcCtx.ObjectTableRepository.Insert(logic.ctx, conn, item)
if err != nil {
return err
}
}
}
}
return nil
}
// saveFields 保存表字段
func (logic *ByteNoticeLogic) saveFields(conn transaction.Conn, objectField *domain.ObjectField) (*domain.ObjectField, error) {
mField, err := logic.svcCtx.ObjectFieldRepository.FindOne(logic.ctx, conn, objectField.Id)
if err == nil && mField.Id > 0 { //已存在 - 更新
objectField.Version = mField.Version + 1
return logic.svcCtx.ObjectFieldRepository.Update(logic.ctx, conn, objectField)
} else {
return logic.svcCtx.ObjectFieldRepository.Insert(logic.ctx, conn, objectField)
}
}
... ...
package consumer
import (
"context"
"encoding/json"
"github.com/pkg/errors"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/types"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
)
type ByteTableDataLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewByteTableDataLogic(svcCtx *svc.ServiceContext) *ByteTableDataLogic {
return &ByteTableDataLogic{
svcCtx: svcCtx,
ctx: context.Background(),
}
}
func (logic *ByteTableDataLogic) Sync(pusherStr string) error {
pusher := &types.SyncTableDataPusher{}
err := json.Unmarshal([]byte(pusherStr), pusher)
if err != nil {
return err
}
conn := logic.svcCtx.DefaultDBConn()
//验证是否有使用数据源
used, err := logic.svcCtx.ChartSettingRepository.CheckUseDataSource(logic.ctx, conn, pusher.ObjectId)
if err != nil || !used {
return err
}
accessToken, _ := types.TableAccessToken{CompanyId: pusher.CompanyId}.GenerateToken()
tableDataPreview, err := logic.svcCtx.ByteMetadataService.TableDataPreview(logic.ctx, &bytelib.TableDataPreviewRequest{
Token: accessToken,
ObjectId: int64(pusher.ObjectId),
ObjectType: bytelib.ObjectMetaTable,
Where: &bytelib.TableQueryWhere{
PageNumber: 1,
PageSize: bytelib.MaxPageSize,
},
UseCache: true,
HiddenData: false,
})
if err != nil {
return err
}
err = transaction.UseTrans(logic.ctx, conn.DB(), func(ctx context.Context, conn transaction.Conn) error {
err = logic.svcCtx.ObjectTableDataRepository.InsertWithTableData(logic.ctx, conn, bytelib.TableData(tableDataPreview))
if err != nil {
return err
}
//更新标记本地存储
err = logic.updateTableWithLocal(conn, int(tableDataPreview.ObjectId))
if err != nil {
return err
}
return nil
}, true)
return err
}
// updateTableWithLocal 更新表标记本地存储
func (logic *ByteTableDataLogic) updateTableWithLocal(conn transaction.Conn, tableId int) error {
objectTable, err := logic.svcCtx.ObjectTableRepository.FindOneByTableId(logic.ctx, conn, tableId)
if err == nil && objectTable.Id > 0 {
objectTable.IsLocal = true
_, err = logic.svcCtx.ObjectTableRepository.Update(logic.ctx, conn, objectTable)
return err
}
return errors.New("表不存在")
}
... ...
... ... @@ -26,6 +26,11 @@ func NewGetTableDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Ge
}
func (l *GetTableDetailLogic) GetTableDetail(req *types.GetTableDetailRequest) (resp interface{}, err error) {
//获取本地数据
local, err := l.GetLocal(req.TableId)
if err == nil {
return local, nil
}
response, err := l.svcCtx.ByteMetadataService.TableInfo(l.ctx, &bytelib.TableInfoRequest{TableId: req.TableId, Token: req.Token})
if err != nil {
logx.Error(err)
... ... @@ -35,3 +40,25 @@ func (l *GetTableDetailLogic) GetTableDetail(req *types.GetTableDetailRequest) (
resp = response
return
}
func (l *GetTableDetailLogic) GetLocal(tableId int) (interface{}, error) {
conn := l.svcCtx.DefaultDBConn()
//查询表数据
objectTable, err := l.svcCtx.ObjectTableRepository.FindOneByTableId(l.ctx, conn, tableId)
if err != nil || objectTable.Id <= 0 {
return nil, xerr.NewErrMsg("表不存在")
}
//查询表字段
objectField, err := l.svcCtx.ObjectFieldRepository.FindOne(l.ctx, conn, int64(tableId))
if err != nil || objectField.Id <= 0 {
return nil, xerr.NewErrMsg("表字段不存在")
}
resp := bytelib.TableInfoResponse{
TableId: objectTable.TableId,
TableType: objectTable.TableType,
Name: objectTable.Name,
ParentId: objectTable.ParentId,
Fields: removeIdField(objectField.Fields),
}
return resp, nil
}
... ...
... ... @@ -8,6 +8,7 @@ import (
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/types"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/contextdata"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/xerr"
)
... ... @@ -29,38 +30,86 @@ func (l *SearchTableByModuleLogic) SearchTableByModule(req *types.SearchTableByM
var result = make(map[string]interface{})
var batchError errorx.BatchError
fx.Parallel(func() {
list, err := l.svcCtx.ByteMetadataService.ObjectTableSearch(l.ctx, bytelib.ObjectTableSearchRequest{
Token: req.Token,
TableTypes: []string{bytelib.MainTable, bytelib.SubTable, bytelib.SideTable},
Module: bytelib.ModuleDigitalCenter,
})
mResp, err := l.getTableByLocal([]string{bytelib.MainTable, bytelib.SubTable, bytelib.SideTable})
if err != nil {
batchError.Add(err)
}
result["导入模块"] = newList(list)
result["导入模块"] = mResp
//if err == nil {
// result["导入模块"] = mResp
//} else {
// list, err := l.svcCtx.ByteMetadataService.ObjectTableSearch(l.ctx, bytelib.ObjectTableSearchRequest{
// Token: req.Token,
// TableTypes: []string{bytelib.MainTable, bytelib.SubTable, bytelib.SideTable},
// Module: bytelib.ModuleChartTemplate, // TODO:字库更新完改为只查 bytelib.ModuleChartTemplate
// })
// if err != nil {
// batchError.Add(err)
// }
// result["导入模块"] = newList(list)
//}
}, func() {
list, err := l.svcCtx.ByteMetadataService.ObjectTableSearch(l.ctx, bytelib.ObjectTableSearchRequest{
Token: req.Token,
TableTypes: []string{bytelib.SchemaTable},
Module: bytelib.ModuleQuerySetCenter,
ReturnGroupItem: true,
})
mResp, err := l.getTableByLocal([]string{bytelib.SchemaTable})
if err != nil {
batchError.Add(err)
}
result["拆解模块"] = newList(list)
result["拆解模块"] = mResp
//if err == nil {
// result["拆解模块"] = mResp
//} else {
// list, err := l.svcCtx.ByteMetadataService.ObjectTableSearch(l.ctx, bytelib.ObjectTableSearchRequest{
// Token: req.Token,
// TableTypes: []string{bytelib.SchemaTable},
// Module: bytelib.ModuleQuerySetCenter,
// ReturnGroupItem: true,
// })
// if err != nil {
// batchError.Add(err)
// }
// result["拆解模块"] = newList(list)
//}
}, func() {
list, err := l.svcCtx.ByteMetadataService.ObjectTableSearch(l.ctx, bytelib.ObjectTableSearchRequest{
Token: req.Token,
TableTypes: []string{bytelib.CalculateItem, bytelib.CalculateSet},
Module: bytelib.ModuleCalculateCenter,
ReturnGroupItem: true,
ExcludeTables: []int{0},
})
mResp, err := l.getTableByLocal([]string{bytelib.CalculateItem})
if err != nil {
batchError.Add(err)
}
result["计算项"] = mResp
//if err == nil {
// result["计算项"] = mResp
//} else {
// list, err := l.svcCtx.ByteMetadataService.ObjectTableSearch(l.ctx, bytelib.ObjectTableSearchRequest{
// Token: req.Token,
// TableTypes: []string{bytelib.CalculateItem},
// Module: bytelib.ModuleCalculateCenter,
// ReturnGroupItem: true,
// ExcludeTables: []int{0},
// })
// if err != nil {
// batchError.Add(err)
// }
// result["计算项"] = newList(list)
//}
}, func() {
mResp, err := l.getTableByLocal([]string{bytelib.CalculateSet})
if err != nil {
batchError.Add(err)
}
result["计算模块"] = newList(list)
result["计算集"] = mResp
//if err == nil {
// result["计算集"] = mResp
//} else {
// list, err := l.svcCtx.ByteMetadataService.ObjectTableSearch(l.ctx, bytelib.ObjectTableSearchRequest{
// Token: req.Token,
// TableTypes: []string{bytelib.CalculateSet},
// Module: bytelib.ModuleCalculateCenter,
// ReturnGroupItem: true,
// ExcludeTables: []int{0},
// })
// if err != nil {
// batchError.Add(err)
// }
// result["计算集"] = newList(list)
//}
})
if err = batchError.Err(); err != nil {
logx.Error(err)
... ... @@ -76,3 +125,31 @@ func newList(r bytelib.ObjectTableSearchResponse) interface{} {
"list": r.List,
}
}
func (l *SearchTableByModuleLogic) getTableByLocal(modules []string) (types.SearchTableByModuleResponse, error) {
tenantId := contextdata.GetTenantFromCtx(l.ctx)
response := types.SearchTableByModuleResponse{
Count: 0,
List: make([]types.SearchTableByModuleItem, 0),
}
total, list, err := l.svcCtx.ObjectTableRepository.Find(l.ctx, l.svcCtx.DefaultDBConn(), map[string]interface{}{
"companyId": tenantId,
"tableTypeIn": modules,
})
if err != nil {
return response, err
}
response.Count = int(total)
for _, item := range list {
response.List = append(response.List, types.SearchTableByModuleItem{
Id: item.Id,
TableId: item.TableId,
TableType: item.TableType,
Name: item.Name,
ParentId: item.ParentId,
Flag: item.Flag,
IsLocal: item.IsLocal,
})
}
return response, nil
}
... ...
... ... @@ -2,13 +2,16 @@ package table
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/xerr"
"github.com/jinzhu/copier"
"github.com/zeromicro/go-zero/core/logx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/xerr"
"sort"
"strconv"
"strings"
)
type SearchTableDataLogic struct {
... ... @@ -32,9 +35,68 @@ func (l *SearchTableDataLogic) SearchTableData(req *types.SearchTableDataRequest
"fields": nil,
"total": 0,
"data": make([]string, 0),
"local": false,
}
return
}
resp, err = l.getLocal(req)
if err == nil {
return resp, nil
}
return l.getRemote(req)
}
// getLocal 获取本地数据
func (l *SearchTableDataLogic) getLocal(req *types.SearchTableDataRequest) (interface{}, error) {
conn := l.svcCtx.DefaultDBConn()
conditions := make([]*domain.TableDataCondition, 0)
_ = copier.Copy(&conditions, req.Condition)
//查询表数据
objectTable, err := l.svcCtx.ObjectTableRepository.FindOneByTableId(l.ctx, conn, req.ObjectId)
if err != nil || objectTable.Id <= 0 {
return nil, xerr.NewErrMsg("表不存在")
}
if !objectTable.IsLocal {
return nil, xerr.NewErrMsg("未保存到本地存储")
}
//查询表字段
objectField, err := l.svcCtx.ObjectFieldRepository.FindOne(l.ctx, conn, int64(req.ObjectId))
if err != nil || objectField.Id <= 0 {
return nil, xerr.NewErrMsg("表字段不存在")
}
//替换中文字段
for _, item := range conditions {
replace := false
for _, field := range objectField.Fields {
if field.Name == item.FieldName {
item.FieldName = field.SQLName
replace = true
}
}
if !replace {
return nil, xerr.NewErrMsg("字段" + item.FieldName + "不存在")
}
}
//表数据
total, list, err := l.svcCtx.ObjectTableDataRepository.Find(l.ctx, conn, req.ObjectId, &domain.ObjectTableDataQuery{
Page: req.PageNumber,
Size: req.PageSize,
Conditions: conditions,
})
if err != nil {
return nil, xerr.NewErrMsg("查询表数据失败")
}
return map[string]interface{}{
"objectId": req.ObjectId,
"fields": removeIdField(objectField.Fields),
"total": total,
"data": list,
"local": true,
}, nil
}
// getRemote 获取远程字库数据
func (l *SearchTableDataLogic) getRemote(req *types.SearchTableDataRequest) (resp interface{}, err error) {
tableDataPreviewRequest := &bytelib.TableDataPreviewRequest{
Token: req.Token,
ObjectType: bytelib.ObjectMetaTable,
... ... @@ -48,11 +110,53 @@ func (l *SearchTableDataLogic) SearchTableData(req *types.SearchTableDataRequest
if err != nil {
return resp, xerr.NewErr(err)
}
//排序
orderField := ""
orderBy := ""
fieldType := "string"
for _, item := range req.Condition {
if item.Order != "" {
orderField = item.FieldName
orderBy = item.Order
break
}
}
for _, item := range response.Fields {
if orderField == item.SQLName {
fieldType = item.SQLType
}
}
fieldType = strings.ToLower(fieldType)
if orderField != "" && orderBy != "" {
sort.Slice(response.Grid.List, func(i, j int) bool {
if _, ok := response.Grid.List[i][orderField]; ok {
if _, ok := response.Grid.List[j][orderField]; ok {
if fieldType == "bigint" || fieldType == "int" || fieldType == "float" {
idata, _ := strconv.ParseFloat(response.Grid.List[i][orderField], 64)
jdata, _ := strconv.ParseFloat(response.Grid.List[j][orderField], 64)
if strings.ToLower(orderBy) == "asc" {
return idata < jdata
} else {
return idata > jdata
}
} else {
if strings.ToLower(orderBy) == "asc" {
return response.Grid.List[i][orderField] < response.Grid.List[j][orderField]
} else {
return response.Grid.List[i][orderField] > response.Grid.List[j][orderField]
}
}
}
}
return true
})
}
resp = map[string]interface{}{
"objectId": response.ObjectId,
"fields": removeIdField(response.Fields),
"total": response.Grid.Total,
"data": response.Grid.List,
"local": false,
}
return
}
... ...
... ... @@ -2,13 +2,15 @@ package table
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/xerr"
"fmt"
"github.com/jinzhu/copier"
"github.com/samber/lo"
"github.com/zeromicro/go-zero/core/logx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/xerr"
)
type SearchTableFieldOptionalValuesLogic struct {
... ... @@ -26,6 +28,12 @@ func NewSearchTableFieldOptionalValuesLogic(ctx context.Context, svcCtx *svc.Ser
}
func (l *SearchTableFieldOptionalValuesLogic) SearchTableFieldOptionalValues(req *types.SearchTableFieldOptionalValuesRequest) (resp *types.SearchTableFieldOptionalValuesResponse, err error) {
//取本地数据
resp, err = l.getLocal(req)
if err == nil {
return resp, err
}
//获取远程数据
fieldOptionalValuesRequest := &bytelib.TableFieldOptionalValuesRequest{
Token: req.Token,
ObjectType: bytelib.ObjectMetaTable,
... ... @@ -58,6 +66,7 @@ func newWhere(conditions []*types.Condition) *bytelib.TableQueryWhere {
//if order == "" {
// order = "ASC"
//}
if c.Like != "" || len(c.In) > 0 {
where.Conditions = append(where.Conditions, &bytelib.TableQueryCondition{
Field: &bytelib.Field{
Name: c.FieldName,
... ... @@ -67,5 +76,67 @@ func newWhere(conditions []*types.Condition) *bytelib.TableQueryWhere {
//Order: order,
})
}
}
return where
}
func (l *SearchTableFieldOptionalValuesLogic) getLocal(req *types.SearchTableFieldOptionalValuesRequest) (resp *types.SearchTableFieldOptionalValuesResponse, err error) {
conn := l.svcCtx.DefaultDBConn()
//查询表数据
objectTable, err := l.svcCtx.ObjectTableRepository.FindOneByTableId(l.ctx, conn, req.ObjectId)
if err != nil || objectTable.Id <= 0 {
return nil, xerr.NewErrMsg("表不存在")
}
if !objectTable.IsLocal {
return nil, xerr.NewErrMsg("未保存到本地存储")
}
//查询表字段
objectField, err := l.svcCtx.ObjectFieldRepository.FindOne(l.ctx, conn, int64(req.ObjectId))
if err != nil || objectField.Id <= 0 {
return nil, xerr.NewErrMsg("表字段不存在")
}
conditions := make([]*domain.TableDataCondition, 0)
_ = copier.Copy(&conditions, req.Condition)
//替换中文字段
for _, item := range conditions {
replace := false
for _, field := range objectField.Fields {
if field.Name == item.FieldName {
item.FieldName = field.SQLName
replace = true
}
}
if !replace {
return nil, xerr.NewErrMsg("字段" + item.FieldName + "不存在")
}
}
field := req.Field
for _, item := range objectField.Fields {
if req.Field == item.Name {
field = item.SQLName
}
}
//表数据
_, list, err := l.svcCtx.ObjectTableDataRepository.Find(l.ctx, conn, req.ObjectId, &domain.ObjectTableDataQuery{
Conditions: conditions,
Group: field,
Select: field,
})
if err != nil {
return nil, xerr.NewErrMsg("查询表数据失败")
}
resp = &types.SearchTableFieldOptionalValuesResponse{
Values: make([]string, 0),
Total: 0,
}
if len(list) > 0 {
lo.ForEach(list, func(item map[string]interface{}, index int) {
if _, ok := item[field]; ok {
resp.Values = append(resp.Values, fmt.Sprintf("%v", item[field]))
}
})
resp.Values = lo.Uniq(resp.Values)
resp.Total = int64(len(resp.Values))
}
return resp, nil
}
... ...
package table
import (
"context"
"encoding/json"
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/types"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/xerr"
"github.com/zeromicro/go-zero/core/logx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/svc"
)
type SyncTableLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
conn transaction.Conn
}
func NewSyncTableLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SyncTableLogic {
return &SyncTableLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
conn: svcCtx.DefaultDBConn(),
}
}
func (l *SyncTableLogic) SyncTable() (resp interface{}, err error) {
companyIds, err := l.svcCtx.ChartRepository.FindCompanyIds(l.ctx, l.conn)
if err != nil {
return nil, xerr.NewErrMsg("查询公司ID失败:" + err.Error())
}
tables := make([]*domain.ObjectTable, 0)
for _, companyId := range companyIds {
accessToken, _ := types.TableAccessToken{CompanyId: companyId}.GenerateToken()
//获取导入模块
response, err := l.svcCtx.ByteMetadataService.ObjectTableSearch(l.ctx, bytelib.ObjectTableSearchRequest{
Token: accessToken,
TableTypes: []string{bytelib.MainTable, bytelib.SubTable, bytelib.SideTable},
Module: bytelib.ModuleChartTemplate,
})
if err == nil {
tables = append(tables, l.getTables(companyId, response)...)
}
//拆解模块
response, err = l.svcCtx.ByteMetadataService.ObjectTableSearch(l.ctx, bytelib.ObjectTableSearchRequest{
Token: accessToken,
TableTypes: []string{bytelib.SchemaTable},
Module: bytelib.ModuleQuerySetCenter,
ReturnGroupItem: true,
})
if err == nil {
tables = append(tables, l.getTables(companyId, response)...)
}
//计算项 计算集
response, err = l.svcCtx.ByteMetadataService.ObjectTableSearch(l.ctx, bytelib.ObjectTableSearchRequest{
Token: accessToken,
TableTypes: []string{bytelib.CalculateItem, bytelib.CalculateSet},
Module: bytelib.ModuleCalculateCenter,
ReturnGroupItem: true,
ExcludeTables: []int{0},
})
if err == nil {
tables = append(tables, l.getTables(companyId, response)...)
}
}
//获取字段信息
fields := l.getFields(tables)
//保存数据
err = transaction.UseTrans(l.ctx, l.conn.DB(), func(ctx context.Context, conn transaction.Conn) error {
err = l.SaveTables(conn, tables)
if err != nil {
return err
}
err = l.SaveFields(conn, fields)
if err != nil {
return err
}
return nil
}, true)
if err != nil {
return nil, xerr.NewErrMsg("保存表失败:" + err.Error())
}
//同步表数据
for _, item := range tables {
if item.TableId <= 0 {
continue
}
used, err := l.svcCtx.ChartSettingRepository.CheckUseDataSource(l.ctx, l.conn, item.TableId)
if err == nil && used {
pusher := &types.SyncTableDataPusher{
CompanyId: item.CompanyId,
ObjectId: int(item.TableId),
}
mBytes, _ := json.Marshal(pusher)
_, _ = l.svcCtx.Redis.Lpush(l.svcCtx.Config.Name+":table_data", string(mBytes))
fmt.Println(" ===========================> 加入数据下载队列 " + string(mBytes))
}
}
fmt.Println("========>数据同步完成")
return companyIds, err
}
func (l *SyncTableLogic) getTables(companyId int64, response bytelib.ObjectTableSearchResponse) []*domain.ObjectTable {
tables := make([]*domain.ObjectTable, 0)
if len(response.List) > 0 {
for _, item := range response.List {
tables = append(tables, &domain.ObjectTable{
Id: item.Id,
TableId: item.TableId,
Name: item.Name,
TableType: item.TableType,
CompanyId: companyId,
ParentId: item.ParentId,
Flag: item.Flag,
Version: 1,
IsLocal: false,
RemoteDeleted: 0,
})
}
}
return tables
}
func (l *SyncTableLogic) getFields(list []*domain.ObjectTable) []*domain.ObjectField {
fields := make([]*domain.ObjectField, 0)
for _, item := range list {
accessToken, _ := types.TableAccessToken{CompanyId: item.CompanyId}.GenerateToken()
if item.TableId > 0 {
//response, err := l.svcCtx.ByteMetadataService.TableInfo(l.ctx, &bytelib.TableInfoRequest{
// Token: accessToken,
// TableId: item.TableId,
//})
response, err := l.svcCtx.ByteMetadataService.TableDataPreview(l.ctx, &bytelib.TableDataPreviewRequest{
Token: accessToken,
ObjectId: int64(item.TableId),
ObjectType: bytelib.ObjectMetaTable,
Where: &bytelib.TableQueryWhere{
PageNumber: 1,
PageSize: 1,
},
UseCache: false,
HiddenData: false,
})
if err == nil {
fields = append(fields, &domain.ObjectField{
Id: int64(item.TableId),
Name: response.Name,
Fields: response.Fields,
Version: 1,
})
}
}
}
return fields
}
// SaveTables 保存数据
func (l *SyncTableLogic) SaveTables(conn transaction.Conn, list []*domain.ObjectTable) error {
for _, item := range list {
objectTable, err := l.svcCtx.ObjectTableRepository.FindOne(l.ctx, conn, item.Id, item.TableType)
if err == nil && objectTable.Id > 0 {
item.IsLocal = objectTable.IsLocal
item.Version = objectTable.Version + 1
}
_, err = l.svcCtx.ObjectTableRepository.Insert(l.ctx, conn, item)
if err != nil {
return err
}
}
return nil
}
func (l *SyncTableLogic) SaveFields(conn transaction.Conn, list []*domain.ObjectField) error {
for _, item := range list {
objectTable, err := l.svcCtx.ObjectFieldRepository.FindOne(l.ctx, conn, item.Id)
if err == nil && objectTable.Id > 0 {
item.Version = objectTable.Version + 1
}
_, err = l.svcCtx.ObjectFieldRepository.Insert(l.ctx, conn, item)
if err != nil {
return err
}
}
return nil
}
... ...
package middleware
import (
"github.com/zeromicro/go-zero/rest/httpx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/authlib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/result"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/xerr"
"net/http"
)
type LoginStatusCheckMiddleware struct {
apiAuth authlib.ApiAuthService
}
func NewLoginStatusCheckMiddleware(apiAuth authlib.ApiAuthService) *LoginStatusCheckMiddleware {
return &LoginStatusCheckMiddleware{
apiAuth: apiAuth,
}
}
func (m *LoginStatusCheckMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("x-mmm-accesstoken")
if len(token) > 0 {
_, err := m.apiAuth.LoginCheck(r.Context(), authlib.RequestLoginCheck{
Token: token,
})
if err != nil {
gatewayError, ok := err.(gateway.HttpError)
if ok {
unAuthResponse(w, gatewayError.Base.Code, gatewayError.Base.Msg)
return
}
result.HttpResult(r, w, struct{}{}, xerr.NewErr(err))
return
}
}
next(w, r)
}
}
func unAuthResponse(w http.ResponseWriter, code int, msg string) {
data := map[string]interface{}{
"msg": msg,
"code": code,
"data": struct{}{},
}
httpx.WriteJson(w, http.StatusUnauthorized, data)
}
... ...
package middleware
import (
"github.com/zeromicro/go-zero/rest/handler"
"net/http"
)
type LogRequestMiddleware struct {
logRequest bool
}
// NewLogRequestMiddleware 记录请求
// logRequest true开启记录,false关闭记录
func NewLogRequestMiddleware(logRequest bool) *LogRequestMiddleware {
return &LogRequestMiddleware{
logRequest: logRequest,
}
}
func (m *LogRequestMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
if !m.logRequest {
return func(writer http.ResponseWriter, request *http.Request) {
next(writer, request)
}
}
return handler.DetailedLogHandler(next).(http.HandlerFunc)
}
... ...
... ... @@ -3,11 +3,14 @@ package svc
import (
"github.com/tiptok/gocomm/pkg/cache/gzcache"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/rest"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/config"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/api/internal/middleware"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/repository"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/authlib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/cache"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/pkg/database"
... ... @@ -22,6 +25,14 @@ type ServiceContext struct {
ChartRepository domain.ChartRepository
ChartSettingRepository domain.ChartSettingRepository
AppPageRepository domain.AppPageRepository
ObjectNoticeRepository domain.ObjectNoticeRepository
ObjectTableRepository domain.ObjectTableRepository
ObjectFieldRepository domain.ObjectFieldRepository
ObjectTableDataRepository domain.ObjectTableDataRepository
ApiAuthService authlib.ApiAuthService
LoginStatusCheck rest.Middleware
LogRequest rest.Middleware
ByteMetadataService bytelib.ByteMetadataService
}
... ... @@ -31,15 +42,24 @@ func NewServiceContext(c config.Config) *ServiceContext {
mlCache := cache.NewMultiLevelCache([]string{c.Redis.Host}, c.Redis.Pass)
redisCache := gzcache.NewClusterCache([]string{c.Redis.Host}, c.Redis.Pass)
redis, _ := redis.NewRedis(redis.RedisConf{Host: c.Redis.Host, Pass: c.Redis.Pass, Type: "node"})
apiAuth := authlib.ApiAuthService{
Service: gateway.NewService(c.ApiAuth.Name, c.ApiAuth.Host, c.ApiAuth.Timeout),
}
return &ServiceContext{
Config: c,
DB: db,
RedisCache: redisCache,
Redis: redis,
ApiAuthService: apiAuth,
LoginStatusCheck: middleware.NewLoginStatusCheckMiddleware(apiAuth).Handle,
LogRequest: middleware.NewLogRequestMiddleware(c.LogRequest).Handle,
ChartRepository: repository.NewChartRepository(cache.NewCachedRepository(mlCache)),
ChartSettingRepository: repository.NewChartSettingRepository(cache.NewCachedRepository(mlCache)),
AppPageRepository: repository.NewAppPageRepository(cache.NewCachedRepository(mlCache)),
ObjectNoticeRepository: repository.NewObjectNoticeRepository(cache.NewCachedRepository(mlCache)),
ObjectTableRepository: repository.NewObjectTableRepository(cache.NewCachedRepository(mlCache)),
ObjectFieldRepository: repository.NewObjectFieldRepository(cache.NewCachedRepository(mlCache)),
ObjectTableDataRepository: repository.NewObjectTableDataRepository(),
ByteMetadataService: bytelib.ByteMetadataService{
Service: gateway.NewService(c.ByteMetadata.Name, c.ByteMetadata.Host, c.ByteMetadata.Timeout),
... ...
... ... @@ -42,6 +42,7 @@ func NewAppPageItem(appPage *domain.AppPage, charts []*domain.Chart) AppPageItem
Id: appPage.Id,
Name: appPage.Name,
Cover: appPage.Cover,
UpdatedAt: appPage.UpdatedAt,
}
for _, id := range appPage.Charts {
if v, ok := chartsMap[id]; ok {
... ...
package types
import (
"github.com/golang-jwt/jwt/v4"
"time"
)
type TableAccessToken struct {
UserId int64 `json:"userId"`
CompanyId int64 `json:"companyId"`
UserName string `json:"userName"`
Phone string `json:"phone"`
}
func (tk TableAccessToken) GenerateToken() (string, error) {
claims := make(jwt.MapClaims)
claims["exp"] = time.Now().Unix() + 3600
claims["iat"] = time.Now().Unix()
claims["UserId"] = tk.UserId
claims["CompanyId"] = tk.CompanyId
claims["UserName"] = tk.UserName
claims["Phone"] = tk.Phone
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = claims
return token.SignedString([]byte("digital-platform"))
}
... ...
... ... @@ -82,6 +82,7 @@ type ChartItem struct {
Name string `json:"name,optional"` // 名称
Cover string `json:"cover,optional"` // 封面
ChartType string `json:"chartType,optional"` // 图表类型
UpdatedAt int `json:"updatedAt,optional"` // 更新时间
ChartProperty *ChartProperty `json:"property,optional,omitempty"` //属性
}
... ... @@ -117,24 +118,55 @@ type ChartProperty struct {
type Other struct {
Quarter *Quarter `json:"quarter,optional,omitempty"` // 四分图
Divider *Divider `json:"divider,optional,omitempty"` // 分割线
Rank *Rank `json:"rank,optional,omitempty"` // 排名图
Deviation *Deviation `json:"deviation,optional,omitempty"` // 偏差图
Notepaper *Notepaper `json:"notepaper,optional,omitempty"` // 便签(富文本)
}
type Quarter struct {
XAxisLabel string `json:"xAxisLabel"` // x轴标签名
XAxisFirstLabel string `json:"xAxisFirstLabel"` // 签名1
XAxisSecondLabel string `json:"xAxisSecondLabel"` // 签名2
XAxisFirstColor string `json:"xAxisFirstColor,optional,omitempty"` // x轴标签1默认颜色
XAxisSecondColor string `json:"xAxisSecondColor,optional,omitempty"` // x轴标签2默认颜色
YAxisLabel string `json:"yAxisLabel"` // y轴标签名
YAxisFirstLabel string `json:"yAxisFirstLabel"` // y标签1
YAxisSecondLabel string `json:"yAxisSecondLabel"` // y标签2
YAxisFirstColor string `json:"yAxisFirstColor,optional,omitempty"` // y轴标签1默认颜色
YAxisSecondColor string `json:"yAxisSecondColor,optional,omitempty"` // y轴标签2默认颜色
Area string `json:"area"` // 图形面积
AreaColor bool `json:"areaColor"` // 颜色
SeriesList []QuarterSeries `json:"seriesList"` // 图形系列
TableSwitch bool `json:"tableSwitch"` // 是否展示记录型表格
}
type QuarterSeries struct {
SeriesValue string `json:"seriesValue"`
}
type Divider struct {
SelectedIdx string `json:"selectedIdx,optional,omitempty"` // 选择的分割线样式
TextSwitch bool `json:"textSwitch,optional,omitempty"` // 是否展示组件文本
Text string `json:"text"` // 组件文本内容
}
type Rank struct {
FirstLine []RankLine `json:"firstLine,optional,omitempty"` // 第一名设置
SecondLine []RankLine `json:"secondLine,optional,omitempty"` // 第二名设置
SortBySwitch bool `json:"sortBySwitch,optional,omitempty"` // 排序开关
SortBySeries string `json:"sortBySeries,optional,omitempty"` // 排序依据
SortByArrow string `json:"sortByArrow,optional,omitempty"` // 排序方向 1-降序 2-升序
}
type RankLine struct {
SeriesValue string `json:"seriesValue"` // 排名图序列值
LabelSwitch bool `json:"labelSwitch"` // 标签开关
Label string `json:"label"` // 标签
ArrowSwitch bool `json:"arrowSwitch"` // 箭头开关
Unit string `json:"unit"` // 单位
}
type Title struct {
TitleSwitch bool `json:"titleSwitch,optional"` // 组件标题开关
IntroduceSwitch bool `json:"introduceSwitch,optional"` // 组件说明开关
... ... @@ -153,6 +185,13 @@ type Title struct {
type TableAbility struct {
FilterSwitch bool `json:"filterSwitch,optional"` // 表筛选功能开关
DimensionList []Dimension `json:"dimensionList,optional"` // 维度列表
CardSwitch bool `json:"cardSwitch,optional"` // 顺序标识开关
CardIdent string `json:"cardIdent,optional"` // 顺序标识
CardOrderList []CardOrderItem `json:"cardOrderList,optional"` // 卡片列表顺序
}
type CardOrderItem struct {
CardId string `json:"cardId,optional"`
}
type Series struct {
... ... @@ -177,11 +216,58 @@ type Dimension struct {
Value string `json:"dimensionVal,optional"`
}
type Deviation struct {
XAxisLabel string `json:"xAxisLabel,optional,omitempty"` // 分类标签
TopChart TopChart `json:"topChart,optional,omitempty"`
MidChart MidChart `json:"midChart,optional,omitempty"`
BotChart []BotChart `json:"botChart,optional,omitempty"`
}
type Notepaper struct {
Text string `json:"text,optional,omitempty"` // 富文本内容
Theme string `json:"theme,optional,omitempty"` // 主题风格
}
type TopChart struct {
SeriesValue string `json:"seriesValue,optional,omitempty"` // 系列
Legend string `json:"legend,optional,omitempty"` // 图例
FormatType string `json:"formatType,optional,omitempty"` //
FormatPoint string `json:"formatPoint,optional,omitempty"` //
}
type MidChart struct {
SeriesValue string `json:"seriesValue,optional,omitempty"` // 系列
Legend string `json:"legend,optional,omitempty"` // 图例
FormatType string `json:"formatType,optional,omitempty"` //
FormatPoint string `json:"formatPoint,optional,omitempty"` //
}
type BotChart struct {
SeriesSwitch bool `json:"seriesSwitch,optional,omitempty"` // 是否显示
Type string `json:"type,optional,omitempty"` // 图表类型
SeriesValue string `json:"seriesValue,optional,omitempty"` // 系列
Legend string `json:"legend,optional,omitempty"` // 图例
FormatType string `json:"formatType,optional,omitempty"` //
FormatPoint string `json:"formatPoint,optional,omitempty"` //
}
type SearchTableByModuleRequest struct {
Token string `header:"x-mmm-accesstoken,optional"`
}
type SearchTableByModuleResponse struct {
Count int `json:"count"`
List []SearchTableByModuleItem `json:"list"`
}
type SearchTableByModuleItem struct {
Id int `json:"id"` //ID
TableId int `json:"tableId"` //表ID
Name string `json:"name"` //表名
TableType string `json:"tableType"` //表类型
ParentId int `json:"parentId"` //父级ID
Flag string `json:"flag"` //分组:Group 集合:Set
IsLocal bool `json:"isLocal"` //是否本地存储
}
type SearchTableFieldOptionalValuesRequest struct {
... ... @@ -222,6 +308,14 @@ type SearchTableDataRequest struct {
type SearchTableDataResponse struct {
}
type SyncTableDataPusher struct {
CompanyId int64 `json:"companyId,string"` //公司ID
ObjectId int `json:"objectId"`
}
type SyncTableResponse struct {
}
type AppPageGetRequest struct {
Id int64 `path:"id"`
}
... ... @@ -291,6 +385,7 @@ type AppPageItem struct {
Name string `json:"name,optional"` // 名称
Cover string `json:"cover,optional"` // 封面
Charts []AppPageChartItem `json:"charts,optional"` // 图表
UpdatedAt int64 `json:"updatedAt,optional"` //更新时间
}
type AppPageChartItem struct {
... ...
syntax = "v1"
info(
title: "xx实例"
desc: "xx实例"
author: "author"
email: "email"
version: "v1"
)
@server(
prefix: object_field/v1
group: object_field
jwt: JwtAuth
)
service Core {
@handler getObjectField
post /object_field/:id (ObjectFieldGetRequest) returns (ObjectFieldGetResponse)
@handler saveObjectField
post /object_field (ObjectFieldSaveRequest) returns (ObjectFieldSaveResponse)
@handler deleteObjectField
delete /object_field/:id (ObjectFieldDeleteRequest) returns (ObjectFieldDeleteResponse)
@handler updateObjectField
put /object_field/:id (ObjectFieldUpdateRequest) returns (ObjectFieldUpdateResponse)
@handler searchObjectField
post /object_field/search (ObjectFieldSearchRequest) returns (ObjectFieldSearchResponse)
}
type (
ObjectFieldGetRequest {
Id int64 `path:"id"`
}
ObjectFieldGetResponse struct{
ObjectField ObjectFieldItem `json:"object_field"`
}
ObjectFieldSaveRequest struct{
ObjectField ObjectFieldItem `json:"object_field"`
}
ObjectFieldSaveResponse struct{}
ObjectFieldDeleteRequest struct{
Id int64 `path:"id"`
}
ObjectFieldDeleteResponse struct{}
ObjectFieldUpdateRequest struct{
Id int64 `path:"id"`
ObjectField ObjectFieldItem `json:"object_field"`
}
ObjectFieldUpdateResponse struct{}
ObjectFieldSearchRequest struct{
Page int `json:"page"`
Size int `json:"size"`
}
ObjectFieldSearchResponse{
List []ObjectFieldItem `json:"list"`
Total int64 `json:"total"`
}
ObjectFieldItem struct{
}
)
... ...
syntax = "v1"
info(
title: "xx实例"
desc: "xx实例"
author: "author"
email: "email"
version: "v1"
)
@server(
prefix: object_notice/v1
group: object_notice
jwt: JwtAuth
)
service Core {
@handler getObjectNotice
post /object_notice/:id (ObjectNoticeGetRequest) returns (ObjectNoticeGetResponse)
@handler saveObjectNotice
post /object_notice (ObjectNoticeSaveRequest) returns (ObjectNoticeSaveResponse)
@handler deleteObjectNotice
delete /object_notice/:id (ObjectNoticeDeleteRequest) returns (ObjectNoticeDeleteResponse)
@handler updateObjectNotice
put /object_notice/:id (ObjectNoticeUpdateRequest) returns (ObjectNoticeUpdateResponse)
@handler searchObjectNotice
post /object_notice/search (ObjectNoticeSearchRequest) returns (ObjectNoticeSearchResponse)
}
type (
ObjectNoticeGetRequest {
Id int64 `path:"id"`
}
ObjectNoticeGetResponse struct{
ObjectNotice ObjectNoticeItem `json:"object_notice"`
}
ObjectNoticeSaveRequest struct{
ObjectNotice ObjectNoticeItem `json:"object_notice"`
}
ObjectNoticeSaveResponse struct{}
ObjectNoticeDeleteRequest struct{
Id int64 `path:"id"`
}
ObjectNoticeDeleteResponse struct{}
ObjectNoticeUpdateRequest struct{
Id int64 `path:"id"`
ObjectNotice ObjectNoticeItem `json:"object_notice"`
}
ObjectNoticeUpdateResponse struct{}
ObjectNoticeSearchRequest struct{
Page int `json:"page"`
Size int `json:"size"`
}
ObjectNoticeSearchResponse{
List []ObjectNoticeItem `json:"list"`
Total int64 `json:"total"`
}
ObjectNoticeItem struct{
}
)
... ...
syntax = "v1"
info(
title: "xx实例"
desc: "xx实例"
author: "author"
email: "email"
version: "v1"
)
@server(
prefix: object_table/v1
group: object_table
jwt: JwtAuth
)
service Core {
@handler getObjectTable
post /object_table/:id (ObjectTableGetRequest) returns (ObjectTableGetResponse)
@handler saveObjectTable
post /object_table (ObjectTableSaveRequest) returns (ObjectTableSaveResponse)
@handler deleteObjectTable
delete /object_table/:id (ObjectTableDeleteRequest) returns (ObjectTableDeleteResponse)
@handler updateObjectTable
put /object_table/:id (ObjectTableUpdateRequest) returns (ObjectTableUpdateResponse)
@handler searchObjectTable
post /object_table/search (ObjectTableSearchRequest) returns (ObjectTableSearchResponse)
}
type (
ObjectTableGetRequest {
Id int64 `path:"id"`
}
ObjectTableGetResponse struct{
ObjectTable ObjectTableItem `json:"object_table"`
}
ObjectTableSaveRequest struct{
ObjectTable ObjectTableItem `json:"object_table"`
}
ObjectTableSaveResponse struct{}
ObjectTableDeleteRequest struct{
Id int64 `path:"id"`
}
ObjectTableDeleteResponse struct{}
ObjectTableUpdateRequest struct{
Id int64 `path:"id"`
ObjectTable ObjectTableItem `json:"object_table"`
}
ObjectTableUpdateResponse struct{}
ObjectTableSearchRequest struct{
Page int `json:"page"`
Size int `json:"size"`
}
ObjectTableSearchResponse{
List []ObjectTableItem `json:"list"`
Total int64 `json:"total"`
}
ObjectTableItem struct{
}
)
... ...
syntax = "proto3";
option go_package ="./pb";
package pb;
message ObjectFieldGetReq {
int64 Id = 1;
}
message ObjectFieldGetResp{
ObjectFieldItem User = 1;
}
message ObjectFieldSaveReq {
}
message ObjectFieldSaveResp{
}
message ObjectFieldDeleteReq {
int64 Id = 1;
}
message ObjectFieldDeleteResp{
}
message ObjectFieldUpdateReq {
int64 Id = 1;
}
message ObjectFieldUpdateResp{
}
message ObjectFieldSearchReq {
int64 PageNumber = 1;
int64 PageSize = 2;
}
message ObjectFieldSearchResp{
repeated ObjectFieldItem List =1;
int64 Total =2;
}
message ObjectFieldItem {
}
service ObjectFieldService {
rpc ObjectFieldGet(ObjectFieldGetReq) returns(ObjectFieldGetResp);
rpc ObjectFieldSave(ObjectFieldSaveReq) returns(ObjectFieldSaveResp);
rpc ObjectFieldDelete(ObjectFieldDeleteReq) returns(ObjectFieldDeleteResp);
rpc ObjectFieldUpdate(ObjectFieldUpdateReq) returns(ObjectFieldUpdateResp);
rpc ObjectFieldSearch(ObjectFieldSearchReq) returns(ObjectFieldSearchResp);
}
... ...
syntax = "proto3";
option go_package ="./pb";
package pb;
message ObjectNoticeGetReq {
int64 Id = 1;
}
message ObjectNoticeGetResp{
ObjectNoticeItem User = 1;
}
message ObjectNoticeSaveReq {
}
message ObjectNoticeSaveResp{
}
message ObjectNoticeDeleteReq {
int64 Id = 1;
}
message ObjectNoticeDeleteResp{
}
message ObjectNoticeUpdateReq {
int64 Id = 1;
}
message ObjectNoticeUpdateResp{
}
message ObjectNoticeSearchReq {
int64 PageNumber = 1;
int64 PageSize = 2;
}
message ObjectNoticeSearchResp{
repeated ObjectNoticeItem List =1;
int64 Total =2;
}
message ObjectNoticeItem {
}
service ObjectNoticeService {
rpc ObjectNoticeGet(ObjectNoticeGetReq) returns(ObjectNoticeGetResp);
rpc ObjectNoticeSave(ObjectNoticeSaveReq) returns(ObjectNoticeSaveResp);
rpc ObjectNoticeDelete(ObjectNoticeDeleteReq) returns(ObjectNoticeDeleteResp);
rpc ObjectNoticeUpdate(ObjectNoticeUpdateReq) returns(ObjectNoticeUpdateResp);
rpc ObjectNoticeSearch(ObjectNoticeSearchReq) returns(ObjectNoticeSearchResp);
}
... ...
syntax = "proto3";
option go_package ="./pb";
package pb;
message ObjectTableGetReq {
int64 Id = 1;
}
message ObjectTableGetResp{
ObjectTableItem User = 1;
}
message ObjectTableSaveReq {
}
message ObjectTableSaveResp{
}
message ObjectTableDeleteReq {
int64 Id = 1;
}
message ObjectTableDeleteResp{
}
message ObjectTableUpdateReq {
int64 Id = 1;
}
message ObjectTableUpdateResp{
}
message ObjectTableSearchReq {
int64 PageNumber = 1;
int64 PageSize = 2;
}
message ObjectTableSearchResp{
repeated ObjectTableItem List =1;
int64 Total =2;
}
message ObjectTableItem {
}
service ObjectTableService {
rpc ObjectTableGet(ObjectTableGetReq) returns(ObjectTableGetResp);
rpc ObjectTableSave(ObjectTableSaveReq) returns(ObjectTableSaveResp);
rpc ObjectTableDelete(ObjectTableDeleteReq) returns(ObjectTableDeleteResp);
rpc ObjectTableUpdate(ObjectTableUpdateReq) returns(ObjectTableUpdateResp);
rpc ObjectTableSearch(ObjectTableSearchReq) returns(ObjectTableSearchResp);
}
... ...
... ... @@ -10,5 +10,8 @@ func Migrate(db *gorm.DB) {
&models.Chart{},
&models.ChartSetting{},
&models.AppPage{},
&models.ObjectNotice{},
&models.ObjectTable{},
&models.ObjectField{},
)
}
... ...
package models
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gorm.io/gorm"
"gorm.io/plugin/soft_delete"
"time"
)
type ObjectField struct {
Id int64 `json:"id" gorm:"primaryKey"` // ID
Name string `json:"name"` //表名
Fields []*bytelib.Field `json:"fields" gorm:"serializer:json"` //表字段
Version int `json:",omitempty"` //版本
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` //删除标记
CreatedAt int64 `json:",omitempty"` //创建时间
UpdatedAt int64 `json:",omitempty"` //更新时间
DeletedAt int64 `json:",omitempty"` //删除时间
}
func (m *ObjectField) TableName() string {
return "object_field"
}
func (m *ObjectField) BeforeCreate(tx *gorm.DB) (err error) {
m.CreatedAt = time.Now().Unix()
m.UpdatedAt = time.Now().Unix()
return
}
func (m *ObjectField) BeforeUpdate(tx *gorm.DB) (err error) {
m.UpdatedAt = time.Now().Unix()
return
}
func (m *ObjectField) CacheKeyFunc() string {
if m.Id == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:id:%v", domain.ProjectName, m.TableName(), m.Id)
}
func (m *ObjectField) CacheKeyFuncByObject(obj interface{}) string {
if v, ok := obj.(*ObjectField); ok {
return v.CacheKeyFunc()
}
return ""
}
func (m *ObjectField) CachePrimaryKeyFunc() string {
if len("") == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:primarykey:%v", domain.ProjectName, m.TableName(), "key")
}
... ...
package models
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gorm.io/gorm"
"gorm.io/plugin/soft_delete"
"time"
)
type ObjectNotice struct {
Id int64 `json:"id" gorm:"primaryKey"` // ID
CompanyId int64 `json:"companyId"` //公司ID
TableId int64 `json:"tableId"` //表ID
TableType string `json:"tableType"` //表类型 导入模块(主表、附表、分表) 拆解(方案、子过程、计算表) 计算(计算项、计算集)
ObjectType string `json:"objectType"` //模块 导入模块、拆解模块、计算模块
Event string `json:"event"` //事件
TableAffectedList []int `json:"TableAffectedList" gorm:"serializer:json"` //级联影响到的表
DataChanged bool `json:"dataChanged"` //数据有更新
StructChanged bool `json:"structChanged"` //结构有更新
Status int `json:"status" gorm:"index:idx_object_notice_status"` //状态 1-等待处理 2-处理完成 3-处理失败
Message string `json:"message"` //错误信息
Retry int `json:"retry" gorm:"default:0"` //重试次数
MetaData domain.ObjectNoticeMetaData `json:"metaData" gorm:"serializer:json"` //模块信息
Version int `json:",omitempty"` //版本
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` //删除标记
CreatedAt int64 `json:",omitempty"` //创建时间
UpdatedAt int64 `json:",omitempty"` //更新时间
DeletedAt int64 `json:",omitempty"` //删除时间
}
func (m *ObjectNotice) TableName() string {
return "object_notice"
}
func (m *ObjectNotice) BeforeCreate(tx *gorm.DB) (err error) {
m.CreatedAt = time.Now().Unix()
m.UpdatedAt = time.Now().Unix()
return
}
func (m *ObjectNotice) BeforeUpdate(tx *gorm.DB) (err error) {
m.UpdatedAt = time.Now().Unix()
return
}
func (m *ObjectNotice) CacheKeyFunc() string {
if m.Id == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:id:%v", domain.ProjectName, m.TableName(), m.Id)
}
func (m *ObjectNotice) CacheKeyFuncByObject(obj interface{}) string {
if v, ok := obj.(*ObjectNotice); ok {
return v.CacheKeyFunc()
}
return ""
}
func (m *ObjectNotice) CachePrimaryKeyFunc() string {
if len("") == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:primarykey:%v", domain.ProjectName, m.TableName(), "key")
}
... ...
package models
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gorm.io/gorm"
"gorm.io/plugin/soft_delete"
"time"
)
type ObjectTable struct {
Id int `json:"id" gorm:"primaryKey;autoIncrement:false"` // ID
TableId int `json:"tableId" gorm:"index:idx_object_table_id"` //表ID
Name string `json:"name"` //表名
TableType string `json:"tableType" gorm:"primaryKey;autoIncrement:false;index:idx_object_table_type"` //模块
CompanyId int64 `json:"companyId" gorm:"index:idx_object_table_company"` //公司id
ParentId int `json:"parentId" gorm:"default:0"` //父id
Flag string `json:"flag"` //分组:Group 集合:Set
Version int `json:",omitempty"` //版本
IsLocal bool `json:"isLocal" gorm:"default:false"` //是否有本地存储
RemoteDeleted int `json:"remoteDeleted"` //远端删除
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` //删除标记
CreatedAt int64 `json:",omitempty"` //创建时间
UpdatedAt int64 `json:",omitempty"` //更新时间
DeletedAt int64 `json:",omitempty"` //删除时间
}
func (m *ObjectTable) TableName() string {
return "object_table"
}
func (m *ObjectTable) BeforeCreate(tx *gorm.DB) (err error) {
m.CreatedAt = time.Now().Unix()
m.UpdatedAt = time.Now().Unix()
return
}
func (m *ObjectTable) BeforeUpdate(tx *gorm.DB) (err error) {
m.UpdatedAt = time.Now().Unix()
return
}
func (m *ObjectTable) CacheKeyFunc() string {
if m.Id == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:id:%v", domain.ProjectName, m.TableName(), m.Id)
}
func (m *ObjectTable) CacheKeyFuncByObject(obj interface{}) string {
if v, ok := obj.(*ObjectTable); ok {
return v.CacheKeyFunc()
}
return ""
}
func (m *ObjectTable) CachePrimaryKeyFunc() string {
if len("") == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:primarykey:%v", domain.ProjectName, m.TableName(), "key")
}
... ...
... ... @@ -162,7 +162,7 @@ func (repository *AppPageRepository) Find(ctx context.Context, conn transaction.
total int64
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(&ms).Order("id desc")
tx = tx.Model(&ms).Order("updated_at desc")
if v, ok := queryOptions["tenantId"]; ok {
tx.Where("tenant_id = ?", v)
}
... ...
... ... @@ -119,7 +119,7 @@ func (repository *ChartRepository) Find(ctx context.Context, conn transaction.Co
total int64
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(&ms).Order("id desc") //.Order("pid asc").Order("sort asc")
tx = tx.Model(&ms).Order("updated_at desc") //.Order("pid asc").Order("sort asc")
if v, ok := queryOptions["ids"]; ok {
tx.Where("id in (?)", v)
}
... ... @@ -201,6 +201,18 @@ func (repository *ChartRepository) FindOneByGroup(ctx context.Context, conn tran
return repository.ModelToDomainModel(m)
}
// FindCompanyIds 获取所有的公司ID
func (repository *ChartRepository) FindCompanyIds(ctx context.Context, conn transaction.Conn) ([]int64, error) {
var (
err error
tx = conn.DB()
m = new(models.Chart)
)
list := make([]int64, 0)
err = tx.Model(&m).Group("tenant_id").Pluck("tenant_id", &list).Error
return list, err
}
func (repository *ChartRepository) ModelToDomainModel(from *models.Chart) (*domain.Chart, error) {
to := &domain.Chart{}
err := copier.Copy(to, from)
... ...
... ... @@ -2,6 +2,7 @@ package repository
import (
"context"
"fmt"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"github.com/tiptok/gocomm/pkg/cache"
... ... @@ -140,6 +141,19 @@ func (repository *ChartSettingRepository) Find(ctx context.Context, conn transac
return total, dms, nil
}
// CheckUseDataSource 检验是否使用数据源
func (repository *ChartSettingRepository) CheckUseDataSource(ctx context.Context, conn transaction.Conn, objectId int) (bool, error) {
var count int64
err := conn.DB().Model(&models.ChartSetting{}).
Joins("left join chart on chart.id=chart_setting.chart_id").
Where("chart.is_del = 0").
Where(fmt.Sprintf("data_source_ids::jsonb @>'[%v]'", objectId)).Count(&count).Error
if err != nil {
return false, err
}
return count > 0, nil
}
func (repository *ChartSettingRepository) ModelToDomainModel(from *models.ChartSetting) (*domain.ChartSetting, error) {
to := &domain.ChartSetting{}
err := copier.Copy(to, from)
... ...
package repository
import (
"context"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"github.com/tiptok/gocomm/pkg/cache"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/models"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gorm.io/gorm"
)
type ObjectFieldRepository struct {
*cache.CachedRepository
}
func (repository *ObjectFieldRepository) Insert(ctx context.Context, conn transaction.Conn, dm *domain.ObjectField) (*domain.ObjectField, error) {
var (
err error
m = &models.ObjectField{}
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
if tx = tx.Model(m).Save(m); tx.Error != nil {
return nil, tx.Error
}
dm.Id = m.Id
return repository.ModelToDomainModel(m)
}
func (repository *ObjectFieldRepository) Update(ctx context.Context, conn transaction.Conn, dm *domain.ObjectField) (*domain.ObjectField, error) {
var (
err error
m *models.ObjectField
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Updates(m)
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectFieldRepository) UpdateWithVersion(ctx context.Context, transaction transaction.Conn, dm *domain.ObjectField) (*domain.ObjectField, error) {
var (
err error
m *models.ObjectField
tx = transaction.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
oldVersion := dm.Version
m.Version += 1
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Select("*").Where("id = ?", m.Id).Where("version = ?", oldVersion).Updates(m)
if tx.RowsAffected == 0 {
return nil, domain.ErrUpdateFail
}
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectFieldRepository) Delete(ctx context.Context, conn transaction.Conn, dm *domain.ObjectField) (*domain.ObjectField, error) {
var (
tx = conn.DB()
m = &models.ObjectField{Id: dm.Identify().(int64)}
)
queryFunc := func() (interface{}, error) {
tx = tx.Where("id = ?", m.Id).Unscoped().Delete(m)
return m, tx.Error
}
if _, err := repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return dm, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectFieldRepository) FindOne(ctx context.Context, conn transaction.Conn, id int64) (*domain.ObjectField, error) {
var (
err error
tx = conn.DB()
m = new(models.ObjectField)
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Where("id = ?", id).First(m)
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrNotFound
}
return m, tx.Error
}
cacheModel := new(models.ObjectField)
cacheModel.Id = id
if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectFieldRepository) Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*domain.ObjectField, error) {
var (
tx = conn.DB()
ms []*models.ObjectField
dms = make([]*domain.ObjectField, 0)
total int64
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(&ms).Order("id desc")
if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
return dms, tx.Error
}
return dms, nil
}
if _, err := repository.Query(queryFunc); err != nil {
return 0, nil, err
}
for _, item := range ms {
if dm, err := repository.ModelToDomainModel(item); err != nil {
return 0, dms, err
} else {
dms = append(dms, dm)
}
}
return total, dms, nil
}
func (repository *ObjectFieldRepository) ModelToDomainModel(from *models.ObjectField) (*domain.ObjectField, error) {
to := &domain.ObjectField{}
err := copier.Copy(to, from)
return to, err
}
func (repository *ObjectFieldRepository) DomainModelToModel(from *domain.ObjectField) (*models.ObjectField, error) {
to := &models.ObjectField{}
err := copier.Copy(to, from)
return to, err
}
func NewObjectFieldRepository(cache *cache.CachedRepository) domain.ObjectFieldRepository {
return &ObjectFieldRepository{CachedRepository: cache}
}
... ...
package repository
import (
"context"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"github.com/tiptok/gocomm/pkg/cache"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/models"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gorm.io/gorm"
)
type ObjectNoticeRepository struct {
*cache.CachedRepository
}
func (repository *ObjectNoticeRepository) Insert(ctx context.Context, conn transaction.Conn, dm *domain.ObjectNotice) (*domain.ObjectNotice, error) {
var (
err error
m = &models.ObjectNotice{}
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
if tx = tx.Model(m).Save(m); tx.Error != nil {
return nil, tx.Error
}
dm.Id = m.Id
return repository.ModelToDomainModel(m)
}
func (repository *ObjectNoticeRepository) Update(ctx context.Context, conn transaction.Conn, dm *domain.ObjectNotice) (*domain.ObjectNotice, error) {
var (
err error
m *models.ObjectNotice
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Updates(m)
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectNoticeRepository) UpdateWithVersion(ctx context.Context, transaction transaction.Conn, dm *domain.ObjectNotice) (*domain.ObjectNotice, error) {
var (
err error
m *models.ObjectNotice
tx = transaction.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
oldVersion := dm.Version
m.Version += 1
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Select("*").Where("id = ?", m.Id).Where("version = ?", oldVersion).Updates(m)
if tx.RowsAffected == 0 {
return nil, domain.ErrUpdateFail
}
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectNoticeRepository) Delete(ctx context.Context, conn transaction.Conn, dm *domain.ObjectNotice) (*domain.ObjectNotice, error) {
var (
tx = conn.DB()
m = &models.ObjectNotice{Id: dm.Identify().(int64)}
)
queryFunc := func() (interface{}, error) {
tx = tx.Where("id = ?", m.Id).Delete(m)
return m, tx.Error
}
if _, err := repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return dm, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectNoticeRepository) FindOne(ctx context.Context, conn transaction.Conn, id int64) (*domain.ObjectNotice, error) {
var (
err error
tx = conn.DB()
m = new(models.ObjectNotice)
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Where("id = ?", id).First(m)
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrNotFound
}
return m, tx.Error
}
cacheModel := new(models.ObjectNotice)
cacheModel.Id = id
if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectNoticeRepository) Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*domain.ObjectNotice, error) {
var (
tx = conn.DB()
ms []*models.ObjectNotice
dms = make([]*domain.ObjectNotice, 0)
total int64
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(&ms).Order("id desc")
if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
return dms, tx.Error
}
return dms, nil
}
if _, err := repository.Query(queryFunc); err != nil {
return 0, nil, err
}
for _, item := range ms {
if dm, err := repository.ModelToDomainModel(item); err != nil {
return 0, dms, err
} else {
dms = append(dms, dm)
}
}
return total, dms, nil
}
func (repository *ObjectNoticeRepository) ModelToDomainModel(from *models.ObjectNotice) (*domain.ObjectNotice, error) {
to := &domain.ObjectNotice{}
err := copier.Copy(to, from)
return to, err
}
func (repository *ObjectNoticeRepository) DomainModelToModel(from *domain.ObjectNotice) (*models.ObjectNotice, error) {
to := &models.ObjectNotice{}
err := copier.Copy(to, from)
return to, err
}
func NewObjectNoticeRepository(cache *cache.CachedRepository) domain.ObjectNoticeRepository {
return &ObjectNoticeRepository{CachedRepository: cache}
}
... ...
package repository
import (
"context"
"fmt"
"github.com/pkg/errors"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"strconv"
"strings"
)
type ObjectTableDataRepository struct{}
type TableColumnSQL struct {
Sql string `json:"sql"`
Column []string `json:"column"`
Data []map[string]string `json:"data"`
}
// makeDropTableSQL 创建删除表SQL
func (repository *ObjectTableDataRepository) makeDropTableSQL(tableId int) (string, error) {
return fmt.Sprintf(`drop table if exists data."%v"`, tableId), nil
}
// makeCreateTableSQL 创建表SQL
func (repository *ObjectTableDataRepository) makeCreateTableSQL(tableId int, tableData bytelib.TableData) (string, error) {
fields := tableData.Fields
list := tableData.Grid.List
if len(fields) <= 0 {
return "", errors.New("缺少字段信息")
}
columns := make([]string, 0)
for _, item := range fields {
fieldType := "text"
//判断字段是否为id,并且数据值能转为整型 设置字段类型 为 int8,否则为 text
if item.SQLName == "id" && len(list) > 0 {
listItem := list[0]
if idValue, ok := listItem["id"]; ok {
_, err := strconv.Atoi(idValue)
if err == nil {
fieldType = "int8"
}
}
}
columns = append(columns, item.SQLName+" "+fieldType+" ")
}
sql := `Create TABLE data."` + fmt.Sprintf("%v", tableId) + `" (` + strings.Join(columns, ",") + `);`
return sql, nil
}
// makeInsertTableSQL 创建表数据SQL
func (repository *ObjectTableDataRepository) makeInsertTableSQL(tableId int, fields []*bytelib.Field, list []map[string]string) (*TableColumnSQL, error) {
tableColumnSQL := &TableColumnSQL{
Column: make([]string, 0),
Data: make([]map[string]string, 0),
}
if len(list) > 0 && len(fields) > 0 {
for _, field := range fields {
tableColumnSQL.Column = append(tableColumnSQL.Column, field.SQLName)
}
for _, item := range list {
values := make(map[string]string)
for _, field := range tableColumnSQL.Column {
if _, ok := item[field]; ok {
values[field] = item[field]
} else {
return tableColumnSQL, errors.New("未获取到字段值")
}
}
tableColumnSQL.Data = append(tableColumnSQL.Data, values)
}
tableColumnSQL.Sql = fmt.Sprintf(`INSERT INTO data."%v" (%s) values (%s)`, tableId, strings.Join(tableColumnSQL.Column, ","), repository.sqlPlaceHoldersSnippet(tableColumnSQL.Column))
}
return tableColumnSQL, nil
}
func (repository *ObjectTableDataRepository) sqlPlaceHoldersSnippet(sqlBuildFields []string) string {
var placeHolder []string
for i := 0; i < len(sqlBuildFields); i++ {
placeHolder = append(placeHolder, "?")
}
return strings.Join(placeHolder, ",")
}
func (repository *ObjectTableDataRepository) DropTable(ctx context.Context, conn transaction.Conn, tableId int) error {
sql, err := repository.makeDropTableSQL(tableId)
if err != nil {
return err
}
err = conn.DB().Exec(sql).Error
if err != nil {
return err
}
//设置数据表本地存储为false
return conn.DB().Exec("update object_table set is_local=false where table_id = ? and is_del=0", tableId).Error
}
// InsertWithTableData 写入表数据
func (repository *ObjectTableDataRepository) InsertWithTableData(ctx context.Context, conn transaction.Conn, tableDataPreview bytelib.TableData) error {
//删除表
err := repository.DropTable(ctx, conn, int(tableDataPreview.ObjectId))
if err != nil {
return err
}
//创建表
createTableSql, err := repository.makeCreateTableSQL(int(tableDataPreview.ObjectId), tableDataPreview)
if err != nil {
return err
}
err = conn.DB().Exec(createTableSql).Error
if err != nil {
return err
}
tableColumnSQL, err := repository.makeInsertTableSQL(int(tableDataPreview.ObjectId), tableDataPreview.Fields, tableDataPreview.Grid.List)
if err != nil {
return err
}
if len(tableColumnSQL.Column) > 0 && len(tableColumnSQL.Data) > 0 {
for _, item := range tableColumnSQL.Data {
if len(item) > 0 {
params := make([]interface{}, 0)
for _, m := range tableColumnSQL.Column {
if _, ok := item[m]; ok {
params = append(params, item[m])
} else {
params = append(params, "")
}
}
err = conn.DB().Exec(tableColumnSQL.Sql, params...).Error
if err != nil {
return err
}
}
}
}
return nil
}
// Find 获取表内所有数据
func (repository *ObjectTableDataRepository) Find(ctx context.Context, conn transaction.Conn, tableId int, query *domain.ObjectTableDataQuery) (int64, []map[string]interface{}, error) {
tx := conn.DB().Table(fmt.Sprintf("data.%v", tableId))
if len(query.Conditions) > 0 {
for _, item := range query.Conditions {
if item.FieldName == "" {
continue
}
if item.Like != "" {
tx = tx.Where(item.FieldName+" like ?", item.Like)
}
if len(item.In) > 0 {
tx = tx.Where(item.FieldName+" in ?", item.In)
}
if item.Order != "" {
tx = tx.Order(item.FieldName + " " + item.Order)
}
}
}
if query.Group != "" {
tx = tx.Group(query.Group)
}
if query.Select != "" {
tx = tx.Select(query.Select)
}
list := make([]map[string]interface{}, 0)
options := domain.NewQueryOptions()
if query.Size > 0 {
options = options.WithOffsetLimit(query.Page, query.Size)
}
total, tx := transaction.PaginationAndCount(ctx, tx, options, &list)
return total, list, tx.Error
}
// SyncData 同步表数据
//func (repository *ObjectTableDataRepository) SyncData(ctx context.Context, conn transaction.Conn, companyId int64, tableId int) error {
//
//}
func NewObjectTableDataRepository() domain.ObjectTableDataRepository {
return &ObjectTableDataRepository{}
}
... ...
package repository
import (
"context"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"github.com/tiptok/gocomm/pkg/cache"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/models"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/domain"
"gorm.io/gorm"
)
type ObjectTableRepository struct {
*cache.CachedRepository
}
func (repository *ObjectTableRepository) Insert(ctx context.Context, conn transaction.Conn, dm *domain.ObjectTable) (*domain.ObjectTable, error) {
var (
err error
m = &models.ObjectTable{}
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
if tx = tx.Model(m).Save(m); tx.Error != nil {
return nil, tx.Error
}
dm.Id = m.Id
return repository.ModelToDomainModel(m)
}
func (repository *ObjectTableRepository) Update(ctx context.Context, conn transaction.Conn, dm *domain.ObjectTable) (*domain.ObjectTable, error) {
var (
err error
m *models.ObjectTable
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Updates(m)
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectTableRepository) UpdateWithVersion(ctx context.Context, transaction transaction.Conn, dm *domain.ObjectTable) (*domain.ObjectTable, error) {
var (
err error
m *models.ObjectTable
tx = transaction.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
oldVersion := dm.Version
m.Version += 1
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Select("*").Where("id = ?", m.Id).Where("version = ?", oldVersion).Updates(m)
if tx.RowsAffected == 0 {
return nil, domain.ErrUpdateFail
}
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectTableRepository) Delete(ctx context.Context, conn transaction.Conn, dm *domain.ObjectTable) (*domain.ObjectTable, error) {
var (
tx = conn.DB()
m = &models.ObjectTable{Id: dm.Identify().(int), TableType: dm.TableType}
)
queryFunc := func() (interface{}, error) {
tx = tx.Where("id = ? and table_type = ?", m.Id, dm.TableType).Unscoped().Delete(m)
return m, tx.Error
}
if _, err := repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return dm, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectTableRepository) FindOne(ctx context.Context, conn transaction.Conn, id int, tableType string) (*domain.ObjectTable, error) {
var (
err error
tx = conn.DB()
m = new(models.ObjectTable)
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Where("id = ?", id).First(m)
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrNotFound
}
return m, tx.Error
}
cacheModel := new(models.ObjectTable)
cacheModel.Id = id
if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectTableRepository) FindOneByTableId(ctx context.Context, conn transaction.Conn, tableId int) (*domain.ObjectTable, error) {
var (
tx = conn.DB()
m = new(models.ObjectTable)
)
tx = tx.Model(m).Where("table_id = ?", tableId).First(m)
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrNotFound
}
return repository.ModelToDomainModel(m)
}
func (repository *ObjectTableRepository) Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*domain.ObjectTable, error) {
var (
tx = conn.DB()
ms []*models.ObjectTable
dms = make([]*domain.ObjectTable, 0)
total int64
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(&ms).Order("id desc")
if v, ok := queryOptions["companyId"]; ok {
tx = tx.Where("company_id = ?", v)
}
if v, ok := queryOptions["id"]; ok {
tx = tx.Where("id = ?", v)
}
if v, ok := queryOptions["flag"]; ok {
tx = tx.Where("flag = ?", v)
}
if v, ok := queryOptions["parentId"]; ok {
tx = tx.Where("parent_id = ?", v)
}
if v, ok := queryOptions["tableTypeIn"]; ok {
tx = tx.Where("table_type in ?", v)
}
if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
return dms, tx.Error
}
return dms, nil
}
if _, err := repository.Query(queryFunc); err != nil {
return 0, nil, err
}
for _, item := range ms {
if dm, err := repository.ModelToDomainModel(item); err != nil {
return 0, dms, err
} else {
dms = append(dms, dm)
}
}
return total, dms, nil
}
// DeleteGroup 删除分组
func (repository *ObjectTableRepository) DeleteGroup(ctx context.Context, conn transaction.Conn, companyId int64, parentId int) error {
//分组下是否有数据
_, list, err := repository.Find(ctx, conn, domain.NewQueryOptions().WithKV("companyId", companyId).WithKV("parentId", parentId))
if err != nil {
return err
}
if len(list) > 0 {
return nil
}
_, items, err := repository.Find(
ctx, conn,
domain.NewQueryOptions().
WithKV("companyId", companyId).
WithKV("id", parentId).
WithKV("flag", "Group"),
)
if err != nil {
return err
}
if len(items) > 0 {
for _, item := range items {
//删除分组
_, err = repository.Delete(ctx, conn, item)
if err != nil {
return err
}
//递归删除上级分组
err = repository.DeleteGroup(ctx, conn, companyId, item.ParentId)
if err != nil {
return err
}
}
}
return nil
}
func (repository *ObjectTableRepository) ModelToDomainModel(from *models.ObjectTable) (*domain.ObjectTable, error) {
to := &domain.ObjectTable{}
err := copier.Copy(to, from)
return to, err
}
func (repository *ObjectTableRepository) DomainModelToModel(from *domain.ObjectTable) (*models.ObjectTable, error) {
to := &models.ObjectTable{}
err := copier.Copy(to, from)
return to, err
}
func NewObjectTableRepository(cache *cache.CachedRepository) domain.ObjectTableRepository {
return &ObjectTableRepository{CachedRepository: cache}
}
... ...
... ... @@ -35,6 +35,7 @@ type ChartRepository interface {
Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*Chart, error)
FindOneByGroup(ctx context.Context, conn transaction.Conn, tenantId, pid int64) (*Chart, error)
FindByTypeAndName(ctx context.Context, conn transaction.Conn, tenantId int64, t string, name string) (int64, []*Chart, error)
FindCompanyIds(ctx context.Context, conn transaction.Conn) ([]int64, error)
}
/*************** 索引函数 开始****************/
... ...
... ... @@ -28,23 +28,54 @@ type ChartProperty struct {
}
type Other struct {
Quarter *Quarter `json:"quarter,optional,omitempty"` // 四分图
Divider *Divider `json:"divider,optional,omitempty"` // 分割线
Rank *Rank `json:"rank,optional,omitempty"` // 排名图
Deviation *Deviation `json:"deviation,optional,omitempty"` // 偏差图
Notepaper *Notepaper `json:"notepaper,optional,omitempty"` // 便签(富文本)
}
type Quarter struct {
XAxisLabel string `json:"xAxisLabel"` // x轴标签名
XAxisFirstLabel string `json:"xAxisFirstLabel"` // 签名1
XAxisSecondLabel string `json:"xAxisSecondLabel"` // 签名2
XAxisFirstColor string `json:"xAxisFirstColor,optional,omitempty"` // x轴标签1默认颜色
XAxisSecondColor string `json:"xAxisSecondColor,optional,omitempty"` // x轴标签2默认颜色
YAxisLabel string `json:"yAxisLabel"` // y轴标签名
YAxisFirstLabel string `json:"yAxisFirstLabel"` // y标签1
YAxisSecondLabel string `json:"yAxisSecondLabel"` // y标签2
YAxisFirstColor string `json:"yAxisFirstColor,optional,omitempty"` // y轴标签1默认颜色
YAxisSecondColor string `json:"yAxisSecondColor,optional,omitempty"` // y轴标签2默认颜色
Area string `json:"area"` // 图形面积
AreaColor bool `json:"areaColor"` // 颜色
SeriesList []QuarterSeries `json:"seriesList"` // 图形系列
TableSwitch bool `json:"tableSwitch"` // 是否展示记录型表格
}
type QuarterSeries struct {
SeriesValue string `json:"seriesValue"`
}
type Divider struct {
SelectedIdx string `json:"selectedIdx,optional,omitempty"` // 选择的分割线样式
TextSwitch bool `json:"textSwitch,optional,omitempty"` // 是否展示组件文本
Text string `json:"text"` // 组件文本内容
}
type Rank struct {
FirstLine []RankLine `json:"firstLine,optional,omitempty"` // 第一名设置
SecondLine []RankLine `json:"secondLine,optional,omitempty"` // 第二名设置
SortBySwitch bool `json:"sortBySwitch,optional,omitempty"` // 排序开关
SortBySeries string `json:"sortBySeries,optional,omitempty"` // 排序依据
SortByArrow string `json:"sortByArrow,optional,omitempty"` // 排序方向 1-降序 2-升序
}
type RankLine struct {
SeriesValue string `json:"seriesValue"` // 排名图序列值
LabelSwitch bool `json:"labelSwitch"` // 标签开关
Label string `json:"label"` // 标签
ArrowSwitch bool `json:"arrowSwitch"` // 箭头开关
Unit string `json:"unit"` // 单位
}
type Title struct {
TitleSwitch bool `json:"titleSwitch,optional"` // 组件标题开关
IntroduceSwitch bool `json:"introduceSwitch,optional"` // 组件说明开关
... ... @@ -63,6 +94,13 @@ type Title struct {
type TableAbility struct {
FilterSwitch bool `json:"filterSwitch,optional"` // 表筛选功能开关
DimensionList []Dimension `json:"dimensionList,optional"` // 维度列表
CardSwitch bool `json:"cardSwitch,optional"` // 顺序标识开关
CardIdent string `json:"cardIdent,optional"` // 顺序标识
CardOrderList []CardOrderItem `json:"cardOrderList,optional"` // 卡片列表顺序
}
type CardOrderItem struct {
CardId string `json:"cardId,optional"`
}
type Series struct {
... ... @@ -83,6 +121,39 @@ type Expression struct {
ToValue string `json:"toValue"` // 显示值(转为)
}
type (
Deviation struct {
XAxisLabel string `json:"xAxisLabel,optional,omitempty"` // 分类标签
TopChart TopChart `json:"topChart,optional,omitempty"`
MidChart MidChart `json:"midChart,optional,omitempty"`
BotChart []BotChart `json:"botChart,optional,omitempty"`
}
Notepaper struct {
Text string `json:"text,optional,omitempty"` // 富文本内容
Theme string `json:"theme,optional,omitempty"` // 主题风格
}
TopChart struct {
SeriesValue string `json:"seriesValue,optional,omitempty"` // 系列
Legend string `json:"legend,optional,omitempty"` // 图例
FormatType string `json:"formatType,optional,omitempty"` //
FormatPoint string `json:"formatPoint,optional,omitempty"` //
}
MidChart struct {
SeriesValue string `json:"seriesValue,optional,omitempty"` // 系列
Legend string `json:"legend,optional,omitempty"` // 图例
FormatType string `json:"formatType,optional,omitempty"` //
FormatPoint string `json:"formatPoint,optional,omitempty"` //
}
BotChart struct {
SeriesSwitch bool `json:"seriesSwitch,optional,omitempty"` // 是否显示
Type string `json:"type,optional,omitempty"` // 图表类型
SeriesValue string `json:"seriesValue,optional,omitempty"` // 系列
Legend string `json:"legend,optional,omitempty"` // 图例
FormatType string `json:"formatType,optional,omitempty"` //
FormatPoint string `json:"formatPoint,optional,omitempty"` //
}
)
func (exp Expression) Match(value string) (result bool, toValue string) {
fValue, ferr := strconv.ParseFloat(value, 64)
cValue, cerr := strconv.ParseFloat(exp.CompareValue, 64)
... ...
... ... @@ -30,6 +30,7 @@ type ChartSettingRepository interface {
Delete(ctx context.Context, conn transaction.Conn, dm *ChartSetting) (*ChartSetting, error)
FindOne(ctx context.Context, conn transaction.Conn, id int64) (*ChartSetting, error)
Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ChartSetting, error)
CheckUseDataSource(ctx context.Context, conn transaction.Conn, objectId int) (bool, error)
}
func (m *ChartSetting) Identify() interface{} {
... ...
package domain
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gorm.io/plugin/soft_delete"
)
type ObjectField struct {
Id int64 `json:"id"` // ID
Name string `json:"name"` //表名
Fields []*bytelib.Field `json:"fields"` //表字段
Version int `json:"version,omitempty"` //版本
IsDel soft_delete.DeletedAt `json:"isDel"` //删除标记
CreatedAt int64 `json:"createdAt,omitempty"` //创建时间
UpdatedAt int64 `json:"updatedAt,omitempty"` //更新时间
DeletedAt int64 `json:"deletedAt,omitempty"` //删除时间
}
type ObjectFieldRepository interface {
Insert(ctx context.Context, conn transaction.Conn, dm *ObjectField) (*ObjectField, error)
Update(ctx context.Context, conn transaction.Conn, dm *ObjectField) (*ObjectField, error)
UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *ObjectField) (*ObjectField, error)
Delete(ctx context.Context, conn transaction.Conn, dm *ObjectField) (*ObjectField, error)
FindOne(ctx context.Context, conn transaction.Conn, id int64) (*ObjectField, error)
Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ObjectField, error)
}
func (m *ObjectField) Identify() interface{} {
if m.Id == 0 {
return nil
}
return m.Id
}
... ...
package domain
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gorm.io/plugin/soft_delete"
)
type ObjectNotice struct {
Id int64 `json:"id"` // ID
CompanyId int64 `json:"companyId"` //公司ID
TableId int `json:"tableId"` //表ID
TableType string `json:"tableType"` //表类型 导入模块(主表、附表、分表) 拆解(方案、子过程、计算表) 计算(计算项、计算集)
ObjectType string `json:"objectType"` //模块 导入模块、拆解模块、计算模块
Event string `json:"event"` //事件
TableAffectedList []int `json:"TableAffectedList"` //级联影响到的表
DataChanged bool `json:"dataChanged"` //数据有更新
StructChanged bool `json:"structChanged"` //结构有更新
Status int `json:"status"` //状态 1-等待处理 2-处理完成 3-处理失败
UpdateTable int `json:"updateTable"` //更新表结构
UpdateData int `json:"updateData"` //更新表数据
Message string `json:"message"` //错误信息
Retry int `json:"retry"` //重试次数
MetaData ObjectNoticeMetaData `json:"metaData"` //模块信息
Version int `json:",omitempty"` //版本
IsDel soft_delete.DeletedAt `json:"isDel"` //删除标记
CreatedAt int64 `json:"createdAt,omitempty"` //创建时间
UpdatedAt int64 `json:"updatedAt,omitempty"` //更新时间
DeletedAt int64 `json:"deletedAt,omitempty"` //删除时间
}
type ObjectNoticeMetaData struct {
Module int `json:"module"` // 导入模块判断是否 取消应用
Status int `json:"status"` // 拆解模块判断是否 取消
}
var (
ObjectNoticeStatusWait = 1 //等待处理
ObjectNoticeStatusDone = 2 //处理完成
ObjectNoticeStatusError = 3 //处理失败
)
type ObjectNoticeRepository interface {
Insert(ctx context.Context, conn transaction.Conn, dm *ObjectNotice) (*ObjectNotice, error)
Update(ctx context.Context, conn transaction.Conn, dm *ObjectNotice) (*ObjectNotice, error)
UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *ObjectNotice) (*ObjectNotice, error)
Delete(ctx context.Context, conn transaction.Conn, dm *ObjectNotice) (*ObjectNotice, error)
FindOne(ctx context.Context, conn transaction.Conn, id int64) (*ObjectNotice, error)
Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ObjectNotice, error)
}
func (m *ObjectNotice) Identify() interface{} {
if m.Id == 0 {
return nil
}
return m.Id
}
// IsDeletedEvent 是否删除事件
func (m *ObjectNotice) IsDeletedEvent() bool {
deletedEvents := []string{
"table.delete",
"table.query.set.delete",
}
for _, event := range deletedEvents {
if m.Event == event {
return true
}
}
//导入模块 取消应用和应用于
if m.Event == "table.apply-on" {
if m.MetaData.Module&bytelib.ModuleChartTemplate == 0 {
return true
}
}
//拆解模块 方案启用、禁用
//计算模块 计算项和计算集启用、禁用
if m.Event == "table.query.set.update.status" {
if m.MetaData.Status&bytelib.ModuleDigitalCenter == 0 {
return true
}
}
return false
}
... ...
package domain
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway/bytelib"
"gorm.io/plugin/soft_delete"
)
type ObjectTable struct {
Id int `json:"id"` // ID
TableId int `json:"tableId" ` //表ID
Name string `json:"name"` //表名
TableType string `json:"tableType" ` //模块
CompanyId int64 `json:"companyId"` //公司id
ParentId int `json:"parentId"` //父id
Flag string `json:"flag"` //分组:Group 集合:Set
Version int `json:"version,omitempty"` //版本
IsLocal bool `json:"isLocal"` //是否有本地存储
RemoteDeleted int `json:"remoteDeleted"` //远端删除
IsDel soft_delete.DeletedAt `json:"isDel,omitempty"` //删除标记
CreatedAt int64 `json:"createdAt,omitempty"` //创建时间
UpdatedAt int64 `json:"updatedAt,omitempty"` //更新时间
DeletedAt int64 `json:"deletedAt,omitempty"` //删除时间
}
type ObjectTableRepository interface {
Insert(ctx context.Context, conn transaction.Conn, dm *ObjectTable) (*ObjectTable, error)
Update(ctx context.Context, conn transaction.Conn, dm *ObjectTable) (*ObjectTable, error)
UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *ObjectTable) (*ObjectTable, error)
Delete(ctx context.Context, conn transaction.Conn, dm *ObjectTable) (*ObjectTable, error)
FindOne(ctx context.Context, conn transaction.Conn, id int, tableType string) (*ObjectTable, error)
FindOneByTableId(ctx context.Context, conn transaction.Conn, tableId int) (*ObjectTable, error)
Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ObjectTable, error)
DeleteGroup(ctx context.Context, conn transaction.Conn, companyId int64, parentId int) error
}
type ObjectTableDataQuery struct {
Page int
Size int
Conditions []*TableDataCondition
Group string
Select string
}
type TableDataCondition struct {
FieldName string `json:"field"` // 条件字段
Like string `json:"like"` // 模糊匹配
In []string `json:"in"` // 匹配多个值
Order string `json:"order"` // 排序 ASC DESC 默认ASC
}
type ObjectTableDataRepository interface {
InsertWithTableData(ctx context.Context, conn transaction.Conn, tableDataPreview bytelib.TableData) error
Find(ctx context.Context, conn transaction.Conn, tableId int, query *ObjectTableDataQuery) (int64, []map[string]interface{}, error)
DropTable(ctx context.Context, conn transaction.Conn, tableId int) error
}
func (m *ObjectTable) Identify() interface{} {
if m.Id == 0 {
return nil
}
return m.Id
}
... ...
package authlib
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-bchart/cmd/chart-server/interanl/pkg/gateway"
"net/http"
)
type ApiAuthService struct {
gateway.Service
}
func (svc *ApiAuthService) MeInfo(ctx context.Context, request RequestUserMeQuery) (*DataUserMe, error) {
var result DataUserMe
if err := svc.Do(ctx, "/v1/user/me", http.MethodGet, request, &result); err != nil {
return nil, err
}
return &result, nil
}
func (svc *ApiAuthService) MeAppInfo(ctx context.Context, request RequestUserMeQuery) (*DataUserAppInfo, error) {
var result DataUserAppInfo
if err := svc.Do(ctx, "/v1/user/me-app-info", http.MethodGet, request, &result); err != nil {
return nil, err
}
return &result, nil
}
func (svc *ApiAuthService) LoginCheck(ctx context.Context, request RequestLoginCheck) (*DataLoginCheck, error) {
var (
result DataLoginCheck
err error
)
if err = svc.Do(ctx, "/v1/login/check?token="+request.Token, http.MethodGet, request, &result); err != nil {
return nil, err
}
if errCodeMsg, ok := err.(gateway.HttpError); ok {
return &DataLoginCheck{
Code: errCodeMsg.Base.Code,
Msg: errCodeMsg.Base.Msg,
}, nil
}
return &result, nil
}
func (svc *ApiAuthService) AppLogin(ctx context.Context, request RequestAppLogin) (*DataAppLogin, error) {
var result DataAppLogin
if err := svc.Do(ctx, "/v1/login/check?token="+request.Token, http.MethodGet, request, &result); err != nil {
return nil, err
}
return &result, nil
}
... ...
package authlib
type RequestUserMeQuery struct {
Token string `header:"x-mmm-accesstoken"`
//UserId int
//CompanyId int
}
type DataUserMe struct {
User *struct {
ID string `json:"id"`
Phone string `json:"phone"`
NickName string `json:"nickName"`
Avatar string `json:"avatar"`
} `json:"user,optional"`
CompanyList []*struct {
ID string `json:"id"`
Name string `json:"name"`
Logo string `json:"logo"`
DefaultLogin int `json:"defaultLogin"`
Types int `json:"types"`
} `json:"companyList,optional"`
CurrentCompany *struct {
ID string `json:"id"`
Name string `json:"name"`
Logo string `json:"logo"`
DefaultLogin int `json:"defaultLogin"`
Types int `json:"types"`
} `json:"currentCompany,optional"`
Workbench []*struct {
ID int `json:"id"`
Name string `json:"name"`
Code string `json:"code"`
CoverImage string `json:"coverImage"`
URL string `json:"url"`
} `json:"workbench,optional"`
Menus []*struct {
MenuID int `json:"menuId"`
ParentID int `json:"parentId"`
MenuName string `json:"menuName"`
Code string `json:"code"`
Types string `json:"types"`
} `json:"menus,optional"`
}
type RequestLoginCheck struct {
Token string
}
type DataLoginCheck struct {
Code int `json:"code,optional"`
Msg string `json:"msg,optional"`
}
type (
RequestAppLogin struct {
AppKey string `json:"appKey" valid:"Required"` // 应用键值
Token string `json:"token" valid:"Required"` // 凭证
}
DataAppLogin struct {
AppEnabled bool `json:"appEnabled"`
}
)
type (
DataUserAppInfo struct {
Apps []AppItem `json:"apps"`
}
AppItem struct {
AppId int64
AppKey string
AppName string
}
)
... ...
... ... @@ -7,7 +7,7 @@ import (
func (gateway *ByteMetadataService) TableDataPreview(ctx context.Context, request *TableDataPreviewRequest) (TablePreviewResponse, error) {
var result TablePreviewResponse
if err := gateway.Do(ctx, "/data/table-preview", http.MethodPost, request, &result); err != nil {
if err := gateway.Do(ctx, "/api/tables/table-preview", http.MethodPost, request, &result); err != nil {
return result, err
}
return result, nil
... ... @@ -75,7 +75,7 @@ type TableData struct {
//数据
Grid *TableDataGrid `json:"grid,optional"`
//字段
Fields []*Field `json:"fields"`
Fields []*Field `json:"fields,optional"`
}
type TableDataGrid struct {
... ...
... ... @@ -7,7 +7,7 @@ import (
func (gateway *ByteMetadataService) TableFieldOptionalValues(ctx context.Context, request *TableFieldOptionalValuesRequest) (TableFieldOptionalValuesResponse, error) {
var result TableFieldOptionalValuesResponse
if err := gateway.Do(ctx, "/data/field-optional-values", http.MethodPost, request, &result); err != nil {
if err := gateway.Do(ctx, "/api/tables/field-optional-values", http.MethodPost, request, &result); err != nil {
return result, err
}
return result, nil
... ...
... ... @@ -7,7 +7,7 @@ import (
func (gateway *ByteMetadataService) TableInfo(ctx context.Context, request *TableInfoRequest) (TableInfoResponse, error) {
var result TableInfoResponse
if err := gateway.Do(ctx, "/data/tables/:tableId", http.MethodGet, request, &result); err != nil {
if err := gateway.Do(ctx, "/api/tables/tables/:tableId", http.MethodGet, request, &result); err != nil {
return result, err
}
return result, nil
... ...
... ... @@ -7,7 +7,7 @@ import (
func (gateway *ByteMetadataService) ObjectTableSearch(ctx context.Context, request ObjectTableSearchRequest) (ObjectTableSearchResponse, error) {
result := ObjectTableSearchResponse{}
if err := gateway.Do(ctx, "/data/table-object-search", http.MethodPost, request, &result); err != nil {
if err := gateway.Do(ctx, "/api/tables/table-object-search", http.MethodPost, request, &result); err != nil {
return result, err
}
return result, nil
... ...
... ... @@ -12,10 +12,11 @@ var (
)
const (
ModuleAll = ModuleDigitalCenter | ModuleQuerySetCenter | ModuleCalculateCenter
ModuleAll = ModuleDigitalCenter | ModuleQuerySetCenter | ModuleCalculateCenter | ModuleChartTemplate
ModuleDigitalCenter = 1
ModuleQuerySetCenter = 2
ModuleCalculateCenter = 4
ModuleChartTemplate = 8
)
const (
... ... @@ -23,3 +24,7 @@ const (
ObjectMetaTable = "MetaTable"
ObjectDBTable = "DBTable"
)
const (
MaxPageSize = 30000 //最大读取行数
)
... ...
... ... @@ -13,6 +13,7 @@ info(
prefix: v1
group: page
jwt: JwtAuth
middleware: LoginStatusCheck,LogRequest
)
service Core {
@doc "保存应用页"
... ... @@ -94,6 +95,7 @@ type (
Name string `json:"name,optional"` // 名称
Cover string `json:"cover,optional"` // 封面
Charts []AppPageChartItem `json:"charts,optional"`// 图表
UpdatedAt int64 `json:"updatedAt,optional"` //更新时间
}
AppPageChartItem struct{
ChartId int64 `json:"chartId"` // 图表ID
... ... @@ -107,6 +109,7 @@ type (
@server(
prefix: v1
group: page
middleware: LogRequest
)
service Core {
@doc "获取应用页详情"
... ...
syntax = "v1"
info(
... ... @@ -13,7 +12,7 @@ info(
prefix: v1
group: chart
jwt: JwtAuth
//middleware: Authority
middleware: LoginStatusCheck,LogRequest
)
service Core {
@doc "保存图表"
... ... @@ -46,6 +45,7 @@ service Core {
@server(
prefix: v1
group: chart
middleware: LogRequest
)
service Core {
@doc "加载图表数据"
... ... @@ -60,120 +60,148 @@ type (
ChartGetRequest {
Id int64 `path:"id"`
}
ChartGetResponse struct{
ChartGetResponse {
Chart ChartItem `json:"chart"`
}
ChartSaveRequest struct{
Pid int64 `json:"pid,optional"`// 父级ID
Type string `json:"type"`// 类型 report:报表 group:分组 chart:图表
Name string `json:"name,optional"`// 名称
ChartSaveRequest {
Pid int64 `json:"pid,optional"` // 父级ID
Type string `json:"type"` // 类型 report:报表 group:分组 chart:图表
Name string `json:"name,optional"` // 名称
ChartType string `json:"chartType"` // 图表类型
Cover string `json:"cover,optional"` // 封面
ChartProperty ChartProperty `json:"property"` // 图表属性
}
ChartSaveResponse struct{
ChartSaveResponse {
Chart ChartItem `json:"chart"`
}
ChartSaveAsRequest struct{
ChartSaveAsRequest {
ChartId int64 `json:"chartId"` // 图表Id
Name string `json:"name"`// 名称
Name string `json:"name"` // 名称
}
ChartSaveAsResponse struct{
ChartSaveAsResponse {
Chart ChartItem `json:"chart"`
}
ChartDeleteRequest struct{
ChartDeleteRequest {
Id int64 `path:"id"`
}
ChartDeleteResponse struct{}
ChartUpdateRequest struct{
ChartUpdateRequest {
Id int64 `path:"id"`
Cover string `json:"cover,optional"` // 封面
ChartProperty ChartProperty `json:"property"` // 图表属性
}
ChartUpdateResponse struct{}
ChartSearchRequest struct {
ChartSearchRequest {
IncludeTypes []string `json:"includeTypes,optional"` //包含的类型: 类型 report:报表 group:分组 chart:图表(未指定返回所有)
DataStyle string `json:"dataStyle,optional"` // 数据样式 tree:树形 flat:平铺
}
ChartSearchResponse{
ChartSearchResponse {
List []ChartItem `json:"list"`
Total int64 `json:"total"`
}
ChartUpdateSortRequest struct{
ChartUpdateSortRequest {
Id int64 `json:"id"`
Pid int64 `json:"pid"`
Index int `json:"index"` // 元素下标
}
ChartUpdateSortResponse struct{}
ChartRenameRequest struct{
ChartRenameRequest {
Id int64 `json:"id"`
Name string `json:"name"`// 名称
Name string `json:"name"` // 名称
}
ChartRenameResponse struct{}
ChartItem struct{
Id int64 `json:"id,optional"`// ID
Pid int64 `json:"pid,optional"`// 父级ID
Type string `json:"type,optional"`// 类型 report:报表 group:分组 chart:图表
Sort int64 `json:"sort,optional"`// 排序
Name string `json:"name,optional"`// 名称
ChartItem {
Id int64 `json:"id,optional"` // ID
Pid int64 `json:"pid,optional"` // 父级ID
Type string `json:"type,optional"` // 类型 report:报表 group:分组 chart:图表
Sort int64 `json:"sort,optional"` // 排序
Name string `json:"name,optional"` // 名称
Cover string `json:"cover,optional"` // 封面
ChartType string `json:"chartType,optional"` // 图表类型
UpdatedAt int `json:"updatedAt,optional"` // 更新时间
ChartProperty *ChartProperty `json:"property,optional,omitempty"` //属性
}
LoadChartDataRequest struct{
LoadChartDataRequest {
ChartId int64 `json:"chartId"`
}
LoadChartDataResponse struct{
LoadChartDataResponse {
}
)
type(
ChartComponentSearchRequest{
type (
ChartComponentSearchRequest {
Name string `json:"name,optional"`
}
ChartComponentSearchResponse{
ChartComponentSearchResponse {
List []ChartComponentItem `json:"list"`
Total int64 `json:"total"`
}
ChartComponentItem struct{
Name string `json:"name,optional"`// 名称
Code string `json:"code,optional"`// 编码
ChartComponentItem {
Name string `json:"name,optional"` // 名称
Code string `json:"code,optional"` // 编码
Cover string `json:"cover,optional"` // 封面
Desc string `json:"desc,optional"`// 描述
Desc string `json:"desc,optional"` // 描述
}
)
type(
ChartProperty struct {
type (
ChartProperty {
Title Title `json:"title,optional"` // 标题
TableAbility TableAbility `json:"table,optional"` // 表筛选功能
Series []Series `json:"series,optional"` // 系列(数据源)
Other Other `json:"other,optional"` // 其他额外配置
}
Other struct {
Other {
Quarter *Quarter `json:"quarter,optional,omitempty"` // 四分图
Divider *Divider `json:"divider,optional,omitempty"` // 分割线
Rank *Rank `json:"rank,optional,omitempty"` // 排名图
Deviation *Deviation `json:"deviation,optional,omitempty"` // 偏差图
Notepaper *Notepaper `json:"notepaper,optional,omitempty"` // 便签(富文本)
}
Quarter struct {
Quarter {
XAxisLabel string `json:"xAxisLabel"` // x轴标签名
XAxisFirstLabel string `json:"xAxisFirstLabel"` // 签名1
XAxisSecondLabel string `json:"xAxisSecondLabel"` // 签名2
XAxisFirstColor string `json:"xAxisFirstColor,optional,omitempty"` // x轴标签1默认颜色
XAxisSecondColor string `json:"xAxisSecondColor,optional,omitempty"` // x轴标签2默认颜色
YAxisLabel string `json:"yAxisLabel"` // y轴标签名
YAxisFirstLabel string `json:"yAxisFirstLabel"` // y标签1
YAxisSecondLabel string `json:"yAxisSecondLabel"` // y标签2
YAxisFirstColor string `json:"yAxisFirstColor,optional,omitempty"` // y轴标签1默认颜色
YAxisSecondColor string `json:"yAxisSecondColor,optional,omitempty"` // y轴标签2默认颜色
Area string `json:"area"` // 图形面积
AreaColor bool `json:"areaColor"` // 颜色
SeriesList []QuarterSeries `json:"seriesList"` // 图形系列
TableSwitch bool `json:"tableSwitch"` // 是否展示记录型表格
}
QuarterSeries struct {
QuarterSeries {
SeriesValue string `json:"seriesValue"`
}
Title struct {
Divider {
SelectedIdx string `json:"selectedIdx,optional,omitempty"` // 选择的分割线样式
TextSwitch bool `json:"textSwitch,optional,omitempty"` // 是否展示组件文本
Text string `json:"text"` // 组件文本内容
}
Rank {
FirstLine []RankLine `json:"firstLine,optional,omitempty"` // 第一名设置
SecondLine []RankLine `json:"secondLine,optional,omitempty"` // 第二名设置
SortBySwitch bool `json:"sortBySwitch,optional,omitempty"` // 排序开关
SortBySeries string `json:"sortBySeries,optional,omitempty"` // 排序依据
SortByArrow string `json:"sortByArrow,optional,omitempty"` // 排序方向 1-降序 2-升序
}
RankLine {
SeriesValue string `json:"seriesValue"` // 排名图序列值
LabelSwitch bool `json:"labelSwitch"` // 标签开关
Label string `json:"label"` // 标签
ArrowSwitch bool `json:"arrowSwitch"` // 箭头开关
Unit string `json:"unit"` // 单位
}
Title {
TitleSwitch bool `json:"titleSwitch,optional"` // 组件标题开关
IntroduceSwitch bool `json:"introduceSwitch,optional"` // 组件说明开关
TitleType string `json:"titleType"` // 标题类型
... ... @@ -187,11 +215,17 @@ type(
HeadingAlign string `json:"headingAlign,optional"` // 主标题 文本对齐方式 left center right
SubAlign string `json:"subAlign,optional"` // 副标题 文本对齐方式 left center right
}
TableAbility struct {
TableAbility {
FilterSwitch bool `json:"filterSwitch,optional"` // 表筛选功能开关
DimensionList []Dimension `json:"dimensionList,optional"` // 维度列表
CardSwitch bool `json:"cardSwitch,optional"` // 顺序标识开关
CardIdent string `json:"cardIdent,optional"` // 顺序标识
CardOrderList []CardOrderItem `json:"cardOrderList,optional"` // 卡片列表顺序
}
CardOrderItem {
CardId string `json:"cardId,optional"`
}
Series struct {// 图表类型 (记录型表格:RecordTable-1 总体指标:MetricsCard-1 容器卡片:ContainerCard-1 四分图:QuarterChart-1)
Series { // 图表类型 (记录型表格:RecordTable-1 总体指标:MetricsCard-1 容器卡片:ContainerCard-1 四分图:QuarterChart-1)
Name string `json:"name"` // 名称 (例如 指标1、指标2)
SourceFrom string `json:"from,options=[ByteBank,User]"` // 数据源类型 ByteBank:字库 User:用户自定义
DataSourceId int64 `json:"dataSourceId,optional,omitempty"` // 数据源ID(from值为ByteBank时有值)
... ... @@ -201,13 +235,46 @@ type(
TargetNum string `json:"targetNum,optional,omitempty"` // 指标数值
TargetUnit string `json:"targetUnit,optional,omitempty"` // 指标单位
}
Expression struct {
Expression {
Operator string `json:"operator"` // 操作符号 <,>,==,<>,<=,>=
CompareValue string `json:"compareValue"` // 比较值
ToValue string `json:"toValue"` // 显示值(转为)
}
Dimension struct{
Dimension {
Name string `json:"name,optional,omitempty"`
Value string `json:"dimensionVal,optional"`
}
)
type (
Deviation struct {
XAxisLabel string `json:"xAxisLabel,optional,omitempty"` // 分类标签
TopChart TopChart `json:"topChart,optional,omitempty"`
MidChart MidChart `json:"midChart,optional,omitempty"`
BotChart []BotChart `json:"botChart,optional,omitempty"`
}
Notepaper struct {
Text string `json:"text,optional,omitempty"` // 富文本内容
Theme string `json:"theme,optional,omitempty"` // 主题风格
}
TopChart struct {
SeriesValue string `json:"seriesValue,optional,omitempty"` // 系列
Legend string `json:"legend,optional,omitempty"` // 图例
FormatType string `json:"formatType,optional,omitempty"` //
FormatPoint string `json:"formatPoint,optional,omitempty"` //
}
MidChart struct {
SeriesValue string `json:"seriesValue,optional,omitempty"` // 系列
Legend string `json:"legend,optional,omitempty"` // 图例
FormatType string `json:"formatType,optional,omitempty"` //
FormatPoint string `json:"formatPoint,optional,omitempty"` //
}
BotChart struct {
SeriesSwitch bool `json:"seriesSwitch,optional,omitempty"` // 是否显示
Type string `json:"type,optional,omitempty"` // 图表类型
SeriesValue string `json:"seriesValue,optional,omitempty"` // 系列
Legend string `json:"legend,optional,omitempty"` // 图例
FormatType string `json:"formatType,optional,omitempty"` //
FormatPoint string `json:"formatPoint,optional,omitempty"` //
}
)
\ No newline at end of file
... ...
... ... @@ -13,6 +13,7 @@ info(
prefix: v1
group: chart-setting
jwt: JwtAuth
middleware: LoginStatusCheck,LogRequest
)
service Core {
@handler getChartSetting
... ...
... ... @@ -26,12 +26,17 @@ service Core {
@doc "源数据表-数据"
@handler searchTableData
post /table/data (SearchTableDataRequest) returns (SearchTableDataResponse)
@doc "源数据表-初始化同步表(首次使用本地存储执行一次)"
@handler syncTable
get /table/sync returns (SyncTableResponse)
}
@server(
prefix: v1
group: table
jwt: JwtAuth
middleware: LoginStatusCheck,LogRequest
//middleware: Authority
)
service Core {
... ... @@ -41,14 +46,24 @@ service Core {
}
type (
SearchTableByModuleRequest struct{
SearchTableByModuleRequest {
Token string `header:"x-mmm-accesstoken,optional"`
}
SearchTableByModuleResponse struct{
SearchTableByModuleResponse {
Count int `json:"count"`
List []SearchTableByModuleItem `json:"list"`
}
SearchTableByModuleItem {
Id int `json:"id"` //ID
TableId int `json:"tableId"` //表ID
Name string `json:"name"` //表名
TableType string `json:"tableType"` //表类型
ParentId int `json:"parentId"` //父级ID
Flag string `json:"flag"` //分组:Group 集合:Set
IsLocal bool `json:"isLocal"` //是否本地存储
}
SearchTableFieldOptionalValuesRequest struct{
SearchTableFieldOptionalValuesRequest {
Token string `header:"x-mmm-accesstoken,optional"`
ObjectId int `json:"objectId"` // 对象ID
Field string `json:"field"` // 当前选择的字段
... ... @@ -58,11 +73,11 @@ type (
//PageSize int `json:"pageSize,optional"` // 页码
Condition []*Condition `json:"conditions,optional"` // 条件
}
SearchTableFieldOptionalValuesResponse struct{
SearchTableFieldOptionalValuesResponse {
Values []string `json:"values"`
Total int64 `json:"total"`
}
Condition struct {
Condition {
FieldName string `json:"field"` // 条件字段
//SqlName string `json:"sqlName,optional"` // 字段SqlName
Like string `json:"like,optional"` // 模糊匹配
... ... @@ -70,22 +85,28 @@ type (
Order string `json:"order,optional,options=ASC||DESC"` // 排序 ASC DESC 默认ASC
}
GetTableDetailRequest struct {
GetTableDetailRequest {
Token string `header:"x-mmm-accesstoken,optional"`
TableId int `path:"tableId"` // 表ID
}
GetTableDetailResponse struct{
GetTableDetailResponse {
}
SearchTableDataRequest struct{
SearchTableDataRequest {
Token string `header:"x-mmm-accesstoken,optional"`
ObjectId int `json:"objectId,optional"` // 对象ID
PageNumber int `json:"page,optional"` // 分页数
PageSize int `json:"size,optional"` // 页码
Condition []*Condition `json:"conditions,optional"` // 条件
}
SearchTableDataResponse struct{
SearchTableDataResponse {
}
SyncTableDataPusher {
CompanyId int64 `json:"companyId,string"` //公司ID
ObjectId int `json:"objectId"`
}
SyncTableResponse {
}
)
\ No newline at end of file
... ...
CREATE TABLE `chart` (
CREATE TABLE `chart`
(
`id` bigint(0) NOT NULL COMMENT 'ID',
`pid` bigint(0) NOT NULL COMMENT '父级ID',
`type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '类型',
... ... @@ -8,7 +8,8 @@ CREATE TABLE `chart` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `chart_setting` (
CREATE TABLE `chart_setting`
(
`id` bigint(0) NOT NULL COMMENT 'ID ',
`chart_id` bigint(0) NOT NULL COMMENT '图表ID',
`property` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '属性',
... ... @@ -17,7 +18,26 @@ CREATE TABLE `chart_setting` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `app_page` (
CREATE TABLE `app_page`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
Create Table `object_table`
(
`id` int not null comment 'ID',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
Create Table `object_field`
(
`id` int not null comment 'ID',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
Create Table `object_notice`
(
`id` int not null comment 'ID',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
\ No newline at end of file
... ...
... ... @@ -6,10 +6,14 @@ require (
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/jinzhu/copier v0.4.0
github.com/jinzhu/now v1.1.5
github.com/magiconair/properties v1.8.0
github.com/pkg/errors v0.9.1
github.com/samber/lo v1.38.1
github.com/stretchr/testify v1.8.4
github.com/tiptok/gocomm v1.0.14
github.com/zeromicro/go-queue v1.1.8
github.com/zeromicro/go-zero v1.5.5
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17
google.golang.org/grpc v1.57.0
gorm.io/driver/mysql v1.5.1
gorm.io/driver/postgres v1.5.2
... ... @@ -37,7 +41,6 @@ require (
github.com/garyburd/redigo v1.6.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.5.0 // indirect
github.com/go-gota/gota v0.12.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
... ... @@ -73,7 +76,6 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/leodido/go-urn v1.1.0 // indirect
github.com/magiconair/properties v1.8.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
... ... @@ -93,7 +95,7 @@ require (
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/samber/lo v1.38.1 // indirect
github.com/segmentio/kafka-go v0.4.38 // indirect
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.2.2 // indirect
... ... @@ -121,7 +123,6 @@ require (
go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sys v0.11.0 // indirect
... ... @@ -137,7 +138,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/datatypes v1.2.0 // indirect
gorm.io/driver/sqlite v1.4.3 // indirect
k8s.io/api v0.26.3 // indirect
k8s.io/apimachinery v0.27.0-alpha.3 // indirect
k8s.io/client-go v0.26.3 // indirect
... ...
此 diff 太大无法显示。
package rd
import (
"fmt"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/rest"
"net/http"
"strings"
)
func Routers(rd *redis.Redis, appName string) []rest.Route {
return []rest.Route{
{
Method: http.MethodGet,
Path: "/rd/clean",
Handler: CleanCache(rd, appName),
},
}
}
func CleanCache(rd *redis.Redis, appName string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var (
success int
)
if strings.TrimSpace(appName) == "" {
return
}
keyPattern := fmt.Sprintf("%s*", appName)
list, err := rd.Keys(keyPattern)
if err != nil {
return
}
for _, key := range list {
if _, err = rd.Del(key); err == nil {
success++
}
}
logx.Infof("清理缓存:%d/%d", success, len(list))
w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf("清理缓存:%d/%d", success, len(list))))
return
}
}
... ...