├── .eslintignore
├── .gitignore
├── LICENSE
├── README.md
├── application
├── app.go
└── init.go
├── build_all_linux.bat
├── build_all_mac.bat
├── build_all_win.bat
├── build_init_app_linux.bat
├── build_manager_linux.bat
├── build_report_linux.bat
├── build_sinker_linux.bat
├── cmd
├── init_app
│ ├── ck
│ │ └── init.go
│ ├── kafka
│ │ └── init.go
│ ├── main.go
│ └── mysql
│ │ ├── bi.sql
│ │ └── init.go
├── manager
│ └── main.go
├── report_server
│ └── main.go
└── sinker
│ ├── action
│ └── action.go
│ ├── geoip
│ ├── GeoLite2-City.mmdb
│ └── geoip.go
│ └── main.go
├── config
└── config.json
├── controller
├── app_controller.go
├── base_controller.go
├── behavior_analysis_controller.go
├── debug_data_controller.go
├── gm_operater_log.go
├── manager_role_controller.go
├── manager_user_controller.go
├── metadata_controller.go
├── panel_controller.go
├── rbac_controller.go
├── realdata_controller.go
├── report_controller.go
├── user_group_controller.go
└── word_controller.go
├── engine
├── db
│ ├── kafka.go
│ ├── redis.go
│ └── sqlx.go
└── logs
│ └── log.go
├── go.mod
├── go.sum
├── init_app_start.bat
├── manager_start.bat
├── middleware
├── Exception.go
├── analysis_cache.go
├── fasthttp.go
├── filter_appid.go
├── jwt.go
├── operater_log.go
├── rbac.go
└── time.go
├── model
├── app.go
├── config.go
├── crud.go
├── debug_device.go
├── event_data.go
├── gm_operater_log.go
├── gm_role.go
├── gm_user.go
├── message.go
├── pannel_folder.go
├── report_table.go
└── user_group.go
├── platform-basic-libs
├── api_config
│ └── api_router_config.go
├── jwt
│ ├── Jwt.go
│ └── exception.go
├── my_error
│ └── my_error.go
├── rbac
│ └── index.go
├── request
│ ├── Exception.go
│ ├── Model.go
│ └── Request.go
├── response
│ ├── Model.go
│ └── Response.go
├── service
│ ├── analysis
│ │ ├── behavior_analysis_service.go
│ │ ├── cache.go
│ │ ├── event.go
│ │ ├── exception.go
│ │ ├── funnel.go
│ │ ├── interface.go
│ │ ├── retention.go
│ │ ├── trace.go
│ │ ├── user_attr.go
│ │ ├── user_event_count.go
│ │ ├── user_event_detail.go
│ │ ├── user_list.go
│ │ ├── utils.go
│ │ └── utils
│ │ │ ├── count.go
│ │ │ ├── sql.go
│ │ │ └── user_group.go
│ ├── app
│ │ └── app_service.go
│ ├── consumer_data
│ │ ├── real_time_warehousing.go
│ │ ├── report_accpet_status.go
│ │ └── reportdata2ck.go
│ ├── debug_data
│ │ └── debug_data.go
│ ├── gm_operater_log
│ │ └── gm_operater_log_service.go
│ ├── gm_role
│ │ └── gm_role_service.go
│ ├── gm_user
│ │ ├── exception.go
│ │ └── gm_user_service.go
│ ├── meta_data
│ │ └── meta_data.go
│ ├── myapp
│ │ ├── redis.go
│ │ └── utils.go
│ ├── pannel
│ │ └── pannel_service.go
│ ├── realdata
│ │ └── real_data_service.go
│ ├── report
│ │ ├── Exception.go
│ │ ├── report_interface.go
│ │ └── report_service.go
│ └── user_group
│ │ └── user_group_service.go
├── sinker
│ ├── clickhouse.go
│ ├── kafka_sarama.go
│ ├── model
│ │ ├── metric.go
│ │ └── topic.go
│ └── parse
│ │ ├── fastjson.go
│ │ ├── parser.go
│ │ └── value.go
└── util
│ ├── array.go
│ ├── charset.go
│ ├── config.go
│ ├── convert.go
│ ├── datatype.go
│ ├── dir.go
│ ├── ecb.go
│ ├── errors.go
│ ├── exec.go
│ ├── gzip.go
│ ├── hash.go
│ ├── http.go
│ ├── interface.go
│ ├── json.go
│ ├── t_util.go
│ ├── time.go
│ └── token.go
├── report_start.bat
├── router
├── analysis.go
├── app.go
├── index.go
├── manager_user.go
├── metadata.go
├── operater_log.go
├── panel.go
├── realdata.go
├── user_group.go
└── ws.go
├── sdk
├── cocos-creator
│ ├── Hello.ts
│ ├── report.d.ts
│ └── report.js
├── egert
│ ├── report.d.ts
│ └── report.min.js
└── web
│ └── report_sdk.js
├── sinker_start.bat
├── views
└── fs.go
├── vue
├── .editorconfig
├── .env.development
├── .env.production
├── .env.staging
├── .eslintignore
├── .eslintrc.js
├── .travis.yml
├── LICENSE
├── README.es.md
├── README.ja.md
├── README.md
├── README.zh-CN.md
├── babel.config.js
├── build
│ └── index.js
├── debug.log
├── jest.config.js
├── jsconfig.json
├── mock
│ ├── article.js
│ ├── index.js
│ ├── mock-server.js
│ ├── remote-search.js
│ └── user.js
├── package.json
├── plop-templates
│ ├── component
│ │ ├── index.hbs
│ │ └── prompt.js
│ ├── utils.js
│ └── view
│ │ ├── index.hbs
│ │ └── prompt.js
├── plopfile.js
├── postcss.config.js
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── api
│ │ ├── analysis.js
│ │ ├── api-rbac.js
│ │ ├── app.js
│ │ ├── metadata.js
│ │ ├── operate.js
│ │ ├── pannel.js
│ │ ├── realdata.js
│ │ ├── role.js
│ │ ├── user-group.js
│ │ ├── user.js
│ │ └── 接口管理
│ ├── assets
│ │ ├── 401_images
│ │ │ └── 401.gif
│ │ ├── 404_images
│ │ │ ├── 404.png
│ │ │ └── 404_cloud.png
│ │ ├── custom-theme
│ │ │ ├── fonts
│ │ │ │ ├── element-icons.ttf
│ │ │ │ └── element-icons.woff
│ │ │ └── index.css
│ │ ├── img
│ │ │ ├── arrow-v.svg
│ │ │ └── loginbg.jpg
│ │ ├── index.ico
│ │ └── 静态文件
│ ├── components
│ │ ├── AnalyseTools
│ │ │ ├── CountSelect.vue
│ │ │ ├── FilterDate
│ │ │ │ └── Date.vue
│ │ │ ├── FilterGroup
│ │ │ │ └── index.vue
│ │ │ ├── FilterUserGroup
│ │ │ │ └── index.vue
│ │ │ ├── FilterWhere
│ │ │ │ ├── ActionRow.vue
│ │ │ │ ├── SmallSelect.vue
│ │ │ │ ├── index.vue
│ │ │ │ └── values.vue
│ │ │ └── Select2
│ │ │ │ └── Select.vue
│ │ ├── BackToTop
│ │ │ └── index.vue
│ │ ├── Breadcrumb
│ │ │ └── index.vue
│ │ ├── Charts
│ │ │ ├── EventCountBar.vue
│ │ │ ├── EventCountPie.vue
│ │ │ ├── FunnelBar.vue
│ │ │ ├── FunnelLine.vue
│ │ │ ├── RetentionLine.vue
│ │ │ ├── RetentionLine2.vue
│ │ │ ├── TraceSankey.vue
│ │ │ ├── UserAttrBar.vue
│ │ │ ├── UserAttrBar2.vue
│ │ │ └── mixins
│ │ │ │ ├── resize.js
│ │ │ │ └── utils.js
│ │ ├── Date
│ │ │ └── index.vue
│ │ ├── DivEdit
│ │ │ └── index.vue
│ │ ├── ErrorLog
│ │ │ └── index.vue
│ │ ├── Hamburger
│ │ │ └── index.vue
│ │ ├── HeaderSearch
│ │ │ └── index.vue
│ │ ├── JsonEditor
│ │ │ └── index.vue
│ │ ├── PageTable
│ │ │ └── index.vue
│ │ ├── Pagination
│ │ │ └── index.vue
│ │ ├── Reload
│ │ │ └── index.vue
│ │ ├── RightPanel
│ │ │ └── index.vue
│ │ ├── Screenfull
│ │ │ └── index.vue
│ │ ├── SelectLink
│ │ │ └── index.vue
│ │ ├── SizeSelect
│ │ │ └── index.vue
│ │ ├── SqlEditor
│ │ │ └── index.vue
│ │ ├── Sticky
│ │ │ └── index.vue
│ │ ├── SvgIcon
│ │ │ └── index.vue
│ │ ├── ThemePicker
│ │ │ └── index.vue
│ │ └── 常用组件
│ ├── directive
│ │ ├── clipboard
│ │ │ ├── clipboard.js
│ │ │ └── index.js
│ │ ├── el-drag-dialog
│ │ │ ├── drag.js
│ │ │ └── index.js
│ │ ├── el-table
│ │ │ ├── adaptive.js
│ │ │ └── index.js
│ │ ├── permission
│ │ │ ├── index.js
│ │ │ └── permission.js
│ │ ├── sticky.js
│ │ ├── waves
│ │ │ ├── index.js
│ │ │ ├── waves.css
│ │ │ └── waves.js
│ │ └── 自定义指示
│ ├── filters
│ │ ├── index.js
│ │ └── 过滤
│ ├── icons
│ │ ├── icon
│ │ ├── index.js
│ │ ├── svg
│ │ │ ├── 404.svg
│ │ │ ├── bug.svg
│ │ │ ├── chart.svg
│ │ │ ├── clipboard.svg
│ │ │ ├── component.svg
│ │ │ ├── dashboard.svg
│ │ │ ├── documentation.svg
│ │ │ ├── drag.svg
│ │ │ ├── edit.svg
│ │ │ ├── education.svg
│ │ │ ├── email.svg
│ │ │ ├── example.svg
│ │ │ ├── excel.svg
│ │ │ ├── exit-fullscreen.svg
│ │ │ ├── eye-open.svg
│ │ │ ├── eye.svg
│ │ │ ├── form.svg
│ │ │ ├── fullscreen.svg
│ │ │ ├── guide.svg
│ │ │ ├── icon.svg
│ │ │ ├── international.svg
│ │ │ ├── language.svg
│ │ │ ├── link.svg
│ │ │ ├── list.svg
│ │ │ ├── lock.svg
│ │ │ ├── message.svg
│ │ │ ├── money.svg
│ │ │ ├── nested.svg
│ │ │ ├── password.svg
│ │ │ ├── pdf.svg
│ │ │ ├── people.svg
│ │ │ ├── peoples.svg
│ │ │ ├── qq.svg
│ │ │ ├── search.svg
│ │ │ ├── shopping.svg
│ │ │ ├── size.svg
│ │ │ ├── skill.svg
│ │ │ ├── star.svg
│ │ │ ├── tab.svg
│ │ │ ├── table.svg
│ │ │ ├── theme.svg
│ │ │ ├── tree-table.svg
│ │ │ ├── tree.svg
│ │ │ ├── user.svg
│ │ │ ├── wechat.svg
│ │ │ └── zip.svg
│ │ └── svgo.yml
│ ├── layout
│ │ ├── components
│ │ │ ├── AppMain.vue
│ │ │ ├── HeadNavbar
│ │ │ │ ├── FixiOSBug.js
│ │ │ │ ├── Item.vue
│ │ │ │ ├── Link.vue
│ │ │ │ ├── Logo.vue
│ │ │ │ ├── SidebarItem.vue
│ │ │ │ ├── VerticalItem.vue
│ │ │ │ └── index.vue
│ │ │ ├── ModifyPassword
│ │ │ │ └── index.vue
│ │ │ ├── Navbar.vue
│ │ │ ├── Settings
│ │ │ │ └── index.vue
│ │ │ ├── Sidebar
│ │ │ │ ├── FixiOSBug.js
│ │ │ │ ├── Item.vue
│ │ │ │ ├── Link.vue
│ │ │ │ ├── Logo.vue
│ │ │ │ ├── SidebarItem.vue
│ │ │ │ └── index.vue
│ │ │ ├── TagsView
│ │ │ │ ├── ScrollPane.vue
│ │ │ │ └── index.vue
│ │ │ └── index.js
│ │ ├── index.vue
│ │ ├── mixin
│ │ │ └── ResizeHandler.js
│ │ └── 总布局文件
│ ├── main.js
│ ├── permission.js
│ ├── router
│ │ ├── index.js
│ │ └── 路由
│ ├── settings.js
│ ├── store
│ │ ├── getters.js
│ │ ├── index.js
│ │ ├── modules
│ │ │ ├── .idea
│ │ │ │ ├── $PRODUCT_WORKSPACE_FILE$
│ │ │ │ ├── .gitignore
│ │ │ │ ├── inspectionProfiles
│ │ │ │ │ └── profiles_settings.xml
│ │ │ │ ├── misc.xml
│ │ │ │ ├── modules.iml
│ │ │ │ ├── modules.xml
│ │ │ │ └── vcs.xml
│ │ │ ├── app.js
│ │ │ ├── baseData.js
│ │ │ ├── errorLog.js
│ │ │ ├── permission.js
│ │ │ ├── settings.js
│ │ │ ├── tagsView.js
│ │ │ └── user.js
│ │ └── vuex相关
│ ├── styles
│ │ ├── EventResult.css
│ │ ├── UserAttrResult.css
│ │ ├── btn.scss
│ │ ├── dashbord-index.css
│ │ ├── debug.css
│ │ ├── element-ui.scss
│ │ ├── element-variables.scss
│ │ ├── event.css
│ │ ├── funnel-res.css
│ │ ├── funnel.css
│ │ ├── index.scss
│ │ ├── log.css
│ │ ├── login.css
│ │ ├── manager-event.css
│ │ ├── mixin.scss
│ │ ├── real-time.css
│ │ ├── retention-res.css
│ │ ├── retention.css
│ │ ├── sidebar.scss
│ │ ├── trace-res.css
│ │ ├── trace.css
│ │ ├── track-data.css
│ │ ├── transition.scss
│ │ ├── user-as.css
│ │ ├── variables.scss
│ │ └── 样式
│ ├── utils
│ │ ├── auth.js
│ │ ├── base-data.js
│ │ ├── clipboard.js
│ │ ├── date.js
│ │ ├── download.js
│ │ ├── error-log.js
│ │ ├── flexible.js
│ │ ├── format.js
│ │ ├── get-page-title.js
│ │ ├── global.js
│ │ ├── help
│ │ ├── http.js
│ │ ├── index.js
│ │ ├── json.js
│ │ ├── open-window.js
│ │ ├── permission.js
│ │ ├── request.js
│ │ ├── router-bash.js
│ │ ├── router.js
│ │ ├── scroll-to.js
│ │ ├── singleMsg.js
│ │ ├── table.js
│ │ ├── time.js
│ │ └── validate.js
│ ├── vendor
│ │ ├── Export2Excel.js
│ │ └── Export2Zip.js
│ └── views
│ │ ├── app
│ │ └── index.vue
│ │ ├── behavior-analysis
│ │ ├── components
│ │ │ ├── AddReportTable.vue
│ │ │ ├── AddUserGroup.vue
│ │ │ ├── EventResult.vue
│ │ │ ├── FunnelResult.vue
│ │ │ ├── FunnelStep.vue
│ │ │ ├── ReportTableList.vue
│ │ │ ├── RetentionResult.vue
│ │ │ ├── TraceResult.vue
│ │ │ └── UserAttrResult.vue
│ │ ├── event.vue
│ │ ├── funnel.vue
│ │ ├── retention.vue
│ │ └── trace.vue
│ │ ├── dashboard
│ │ ├── components
│ │ │ ├── ManagerDir.vue
│ │ │ ├── ManagerRt.vue
│ │ │ └── analysis
│ │ │ │ ├── event.vue
│ │ │ │ ├── funnel.vue
│ │ │ │ ├── retention.vue
│ │ │ │ ├── trace.vue
│ │ │ │ └── user_attr.vue
│ │ └── index.vue
│ │ ├── error-page
│ │ ├── 401.vue
│ │ └── 404.vue
│ │ ├── login
│ │ ├── auth-redirect.vue
│ │ ├── components
│ │ │ └── SocialSignin.vue
│ │ └── index.vue
│ │ ├── manager
│ │ ├── components
│ │ │ ├── FailData.vue
│ │ │ ├── TrackData.vue
│ │ │ ├── debug.vue
│ │ │ ├── eventAttr.vue
│ │ │ ├── metaAttr.vue
│ │ │ ├── realData2Es.vue
│ │ │ └── realTime.vue
│ │ ├── event.vue
│ │ └── log.vue
│ │ ├── permission
│ │ ├── operater_log.vue
│ │ ├── role.vue
│ │ └── user.vue
│ │ ├── redirect
│ │ └── index.vue
│ │ └── user-analysis
│ │ ├── components
│ │ └── UserInfoRes.vue
│ │ ├── group.vue
│ │ ├── index.vue
│ │ ├── user_info.vue
│ │ └── user_list.vue
├── tests
│ └── unit
│ │ ├── .eslintrc.js
│ │ ├── components
│ │ ├── Hamburger.spec.js
│ │ └── SvgIcon.spec.js
│ │ └── utils
│ │ ├── formatTime.spec.js
│ │ ├── parseTime.spec.js
│ │ └── validate.spec.js
└── vue.config.js
└── vue_start.bat
/.eslintignore:
--------------------------------------------------------------------------------
1 | /views/
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin/background.exe
2 | /bin/report_server.exe
3 | /bin/sinker.exe
4 | /logs/
5 | /task/
6 | /vue/node_modules/
7 | ....
8 | /bin/
9 | /.idea/
10 | /views/dist/static/
11 | /views/dist/favicon.ico
12 | /views/dist/index.html
13 | /bin/linux/
14 | /bin/win/
15 | /.idea/
16 | /bin/linux/
17 | /bin/win/
18 | /views/dist/
19 | main.go
20 | task
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## 作者求工作,tel:13298692154
3 |
4 | ## 铸龙-用户行为分析系统
5 | -----------
6 | > 铸龙-用户行为分析系统 是一款用于分析用户行为事件的BI软件,功能如下
7 | * 事件分析
8 | * 漏斗分析
9 | * 留存分析
10 | * 智能路径分析
11 | * 报表,面板管理
12 |
13 | > 技术栈主要用
14 | * 前端:vue+elementui+antdv
15 | * 后端:go
16 |
17 | > 所需中间件
18 | * mysql
19 | * redis
20 | * kafka
21 | * clickhouse
22 |
23 | 欢迎大家提出自己的issue。
24 |
25 |
26 | > 相关
27 |
28 | *[下载地址]( https://gitee.com/cynthia520/xwl_bi/releases/v1.0.0 )
29 |
30 | *[文档地址]( https://www.yuque.com/jianghurenchenggolang/oehqme/hen7qy )
31 |
32 | *[用户端体验地址]( http://www.ycvod.net )
33 |
34 | *[后台体验地址]( http://110.42.167.155:8090/#/dashboard ) 用户名: test ,密码: test123456 (因本人穷,所以只是一台1核2g的服务器撑着,望同是开发人,手下留情)
35 |
36 | ## 其他开源项目
37 | * ElasticSearch可视化工具 https://github.com/1340691923/ElasticView
38 | * 软考成绩快查工具 https://github.com/1340691923/SoftTestMonitor
39 |
40 | ### 求职中,个人微信二维码
41 |
42 |
43 |
44 |
45 |
46 | ### QQ群
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/build_all_linux.bat:
--------------------------------------------------------------------------------
1 | cd vue && npm run build:prod && cd .. && set goos=linux&&go build -ldflags="-w -s" -o bin/linux/manager cmd/manager/main.go && go build -ldflags="-w -s" -o bin/linux/report_server cmd/report_server/main.go && go build -ldflags="-w -s" -o bin/linux/sinker cmd/sinker/main.go && go build -ldflags="-w -s" -o bin/linux/init_app cmd/init_app/main.go
2 | echo "build success"
--------------------------------------------------------------------------------
/build_all_mac.bat:
--------------------------------------------------------------------------------
1 | cd vue && npm run build:prod && cd .. && SET CGO_ENABLED=0&& SET GOOS=darwin&& SET GOARCH=amd64&& go build -ldflags="-w -s" -o bin/mac/manager cmd/manager/main.go && go build -ldflags="-w -s" -o bin/mac/report_server cmd/report_server/main.go && go build -ldflags="-w -s" -o bin/mac/sinker cmd/sinker/main.go && go build -ldflags="-w -s" -o bin/mac/init_app cmd/init_app/main.go
2 | echo "build success"
--------------------------------------------------------------------------------
/build_all_win.bat:
--------------------------------------------------------------------------------
1 | cd vue && npm run build:prod && cd .. && go build -ldflags="-w -s" -o bin/win/manager.exe cmd/manager/main.go && go build -ldflags="-w -s" -o bin/win/report_server.exe cmd/report_server/main.go && go build -ldflags="-w -s" -o bin/win/sinker.exe cmd/sinker/main.go && go build -ldflags="-w -s" -o bin/win/init_app.exe cmd/init_app/main.go
2 | echo "build success"
--------------------------------------------------------------------------------
/build_init_app_linux.bat:
--------------------------------------------------------------------------------
1 | set goos=linux&& go build -ldflags="-w -s" -o bin/linux/init_app cmd/init_app/main.go
2 | echo "build success"
3 |
--------------------------------------------------------------------------------
/build_manager_linux.bat:
--------------------------------------------------------------------------------
1 | cd vue && npm run build:prod && cd .. && set goos=linux&&go build -ldflags="-w -s" -o bin/linux/manager cmd/manager/main.go
2 | echo "build success"
3 |
--------------------------------------------------------------------------------
/build_report_linux.bat:
--------------------------------------------------------------------------------
1 | set goos=linux&& go build -ldflags="-w -s" -o bin/linux/report_server cmd/report_server/main.go
2 | echo "build success"
3 |
--------------------------------------------------------------------------------
/build_sinker_linux.bat:
--------------------------------------------------------------------------------
1 | set goos=linux&& go build -ldflags="-w -s" -o bin/linux/sinker cmd/sinker/main.go
2 | echo "build success"
3 |
--------------------------------------------------------------------------------
/cmd/init_app/kafka/init.go:
--------------------------------------------------------------------------------
1 | package kafka
2 |
3 | import (
4 | "fmt"
5 | "github.com/1340691923/xwl_bi/model"
6 | "github.com/Shopify/sarama"
7 | "log"
8 | "time"
9 | )
10 |
11 | //初始化kafka数据
12 | func Init() {
13 | config := sarama.NewConfig()
14 |
15 | config.Version = sarama.V2_0_0_0
16 | if model.GlobConfig.Comm.Kafka.Username != "" {
17 | config.Net.SASL.Enable = true
18 | config.Net.SASL.User = model.GlobConfig.Comm.Kafka.Username
19 | config.Net.SASL.Password = model.GlobConfig.Comm.Kafka.Password
20 | config.Net.SASL.Handshake = true
21 | }
22 |
23 | config.Consumer.Group.Session.Timeout = 15 * time.Second
24 | config.Consumer.Group.Heartbeat.Interval = 5 * time.Second
25 |
26 | conn, err := sarama.NewClusterAdmin(model.GlobConfig.Comm.Kafka.Addresses, config)
27 | if err != nil {
28 | log.Println(fmt.Sprintf("kafka 链接初始化失败:%s", err.Error()))
29 | panic(err)
30 | }
31 | s, err := conn.ListTopics()
32 | for topic := range s {
33 | log.Println("您所拥有的TOPIC为:", topic)
34 | }
35 |
36 | if _, ok := s[model.GlobConfig.Comm.Kafka.ReportTopicName]; !ok {
37 | detail := sarama.TopicDetail{NumPartitions: model.GlobConfig.Comm.Kafka.NumPartitions, ReplicationFactor: 1}
38 | err = conn.CreateTopic(model.GlobConfig.Comm.Kafka.ReportTopicName, &detail, false)
39 | if err != nil {
40 | log.Println("创建TOPIC失败!", model.GlobConfig.Comm.Kafka.ReportTopicName)
41 | panic(err)
42 | }
43 |
44 | err = conn.Close()
45 | if err != nil {
46 | panic(err)
47 | }
48 | log.Println("初始化TOPIC完成!", model.GlobConfig.Comm.Kafka.ReportTopicName)
49 | } else {
50 | log.Println("您已拥有该TOPIC:", model.GlobConfig.Comm.Kafka.ReportTopicName)
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/cmd/init_app/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "github.com/1340691923/xwl_bi/application"
7 | "github.com/1340691923/xwl_bi/cmd/init_app/ck"
8 | "github.com/1340691923/xwl_bi/cmd/init_app/kafka"
9 | "github.com/1340691923/xwl_bi/cmd/init_app/mysql"
10 | _ "github.com/ClickHouse/clickhouse-go"
11 | _ "github.com/go-sql-driver/mysql"
12 | "log"
13 | )
14 |
15 | var (
16 | configFileDir string
17 | configFileName string
18 | configFileExt string
19 | )
20 |
21 | func init() {
22 | flag.StringVar(&configFileDir, "configFileDir", "config", "配置文件夹名")
23 | flag.StringVar(&configFileName, "configFileName", "config", "配置文件名")
24 | flag.StringVar(&configFileExt, "configFileExt", "json", "配置文件后缀")
25 | flag.Parse()
26 | }
27 |
28 | // 初始化程序
29 | // By 肖文龙
30 | func main() {
31 |
32 | app := application.NewApp(
33 | "init_app",
34 | application.WithConfigFileDir(configFileDir),
35 | application.WithConfigFileName(configFileName),
36 | application.WithConfigFileExt(configFileExt),
37 | application.RegisterInitFnObserver(application.InitLogs),
38 | application.RegisterInitFnObserver(application.InitMysql),
39 | application.RegisterInitFnObserver(application.InitClickHouse),
40 | )
41 |
42 | err := app.InitConfig().
43 | NotifyInitFnObservers().
44 | Error()
45 |
46 | if err != nil {
47 | log.Println(fmt.Sprintf("初始化失败%s", err.Error()))
48 | panic(err)
49 | }
50 |
51 | defer app.Close()
52 |
53 | kafka.Init()
54 | ck.Init()
55 | mysql.Init()
56 | log.Println("数据已全部初始化完毕!")
57 | }
58 |
--------------------------------------------------------------------------------
/cmd/init_app/mysql/init.go:
--------------------------------------------------------------------------------
1 | package mysql
2 |
3 | import (
4 | _ "embed"
5 | "fmt"
6 | "github.com/1340691923/xwl_bi/engine/db"
7 | "github.com/1340691923/xwl_bi/model"
8 | "github.com/1340691923/xwl_bi/platform-basic-libs/util"
9 | "log"
10 | "strings"
11 | )
12 |
13 | //go:embed bi.sql
14 | var SqlByte []byte
15 |
16 | //初始化mysql数据
17 | func Init() {
18 | var err error
19 |
20 | _, err = db.Sqlx.Exec(` create database if not exists ` + model.GlobConfig.Comm.Mysql.DbName)
21 |
22 | if err != nil {
23 | log.Println(fmt.Sprintf("mysql 执行建库语句失败:%s", err.Error()))
24 | panic(err)
25 | }
26 |
27 | execSqlArr := strings.Split(util.Bytes2str(SqlByte), ";")
28 |
29 | for _, execSql := range execSqlArr {
30 | _, err = db.Sqlx.Exec(execSql)
31 | if err != nil {
32 | log.Println(fmt.Sprintf("mysql 执行建表语句sql:%v失败:%s", execSql, err.Error()))
33 | panic(err)
34 | }
35 | }
36 |
37 | log.Println("初始化mysql数据完成!")
38 | }
39 |
--------------------------------------------------------------------------------
/cmd/manager/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "github.com/1340691923/xwl_bi/application"
6 | "github.com/1340691923/xwl_bi/engine/logs"
7 | _ "github.com/ClickHouse/clickhouse-go"
8 | _ "github.com/go-sql-driver/mysql"
9 | "go.uber.org/zap"
10 | )
11 |
12 | var (
13 | configFileDir string
14 | configFileName string
15 | configFileExt string
16 | )
17 |
18 | func init() {
19 | flag.StringVar(&configFileDir, "configFileDir", "config", "配置文件夹名")
20 | flag.StringVar(&configFileName, "configFileName", "config", "配置文件名")
21 | flag.StringVar(&configFileExt, "configFileExt", "json", "配置文件后缀")
22 | flag.Parse()
23 | }
24 |
25 | // 管理后台
26 | // By 肖文龙
27 | func main() {
28 |
29 | app := application.NewApp(
30 | "manager",
31 | application.WithConfigFileDir(configFileDir),
32 | application.WithConfigFileName(configFileName),
33 | application.WithConfigFileExt(configFileExt),
34 | application.RegisterInitFnObserver(application.InitLogs),
35 | application.RegisterInitFnObserver(application.InitMysql),
36 | application.RegisterInitFnObserver(application.InitTask),
37 | application.RegisterInitFnObserver(application.InitRbac),
38 | application.RegisterInitFnObserver(application.InitOpenWinBrowser),
39 | application.RegisterInitFnObserver(application.InitClickHouse),
40 | application.RegisterInitFnObserver(application.InitRedisPool),
41 | application.RegisterInitFnObserver(application.InitDebugSarama),
42 | )
43 |
44 | err := app.
45 | InitConfig().
46 | NotifyInitFnObservers().
47 | Error()
48 |
49 | if err != nil {
50 | logs.Logger.Error("BI 初始化失败", zap.String("err.Error()", err.Error()))
51 | panic(err)
52 | }
53 |
54 | defer app.Close()
55 |
56 | app.RunManager()
57 |
58 | app.WaitForExitSign(func() {
59 | logs.Logger.Sugar().Infof("BI 服务停止成功...")
60 | })
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/cmd/sinker/geoip/GeoLite2-City.mmdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/1340691923/xwl_bi/9337120b09f855a22c4c5a4e78b84436ef37dc30/cmd/sinker/geoip/GeoLite2-City.mmdb
--------------------------------------------------------------------------------
/controller/base_controller.go:
--------------------------------------------------------------------------------
1 | //控制器层
2 | package controller
3 |
4 | import (
5 | "github.com/1340691923/xwl_bi/platform-basic-libs/request"
6 | "github.com/1340691923/xwl_bi/platform-basic-libs/response"
7 | )
8 |
9 | //父控制器结构体
10 | type BaseController struct {
11 | response.Response
12 | request.Request
13 | }
14 |
--------------------------------------------------------------------------------
/controller/gm_operater_log.go:
--------------------------------------------------------------------------------
1 | package controller
2 |
3 | import (
4 | "github.com/1340691923/xwl_bi/platform-basic-libs/request"
5 | "github.com/1340691923/xwl_bi/platform-basic-libs/response"
6 | "github.com/1340691923/xwl_bi/platform-basic-libs/service/gm_operater_log"
7 | "github.com/gofiber/fiber/v2"
8 | )
9 |
10 | type GmOperaterController struct {
11 | BaseController
12 | }
13 |
14 | //查看后台操作日志
15 | func (this GmOperaterController) ListAction(ctx *fiber.Ctx) error {
16 |
17 | var reqData request.GmOperaterLogList
18 |
19 | if err := ctx.BodyParser(&reqData); err != nil {
20 | return this.Error(ctx, err)
21 | }
22 |
23 | gmOperaterLogService := gm_operater_log.GmOperaterLogService{}
24 |
25 | list, count, err := gmOperaterLogService.List(reqData)
26 |
27 | if err != nil {
28 | return this.Error(ctx, err)
29 | }
30 |
31 | return this.Success(ctx, response.SearchSuccess, map[string]interface{}{"list": list, "count": count})
32 | }
33 |
--------------------------------------------------------------------------------
/controller/rbac_controller.go:
--------------------------------------------------------------------------------
1 | package controller
2 |
3 | import (
4 | "github.com/1340691923/xwl_bi/platform-basic-libs/api_config"
5 | "github.com/1340691923/xwl_bi/platform-basic-libs/response"
6 | fiber "github.com/gofiber/fiber/v2"
7 | )
8 |
9 | //接口访问权限管理 直接放缓存
10 | type RbacController struct {
11 | BaseController
12 | }
13 |
14 | //获取接口路由信息
15 | func (this RbacController) UrlConfig(ctx *fiber.Ctx) error {
16 | apiRouterConfig := api_config.NewApiRouterConfig()
17 | return this.Success(ctx, response.SearchSuccess, apiRouterConfig.GetRouterConfigs())
18 | }
19 |
--------------------------------------------------------------------------------
/engine/db/redis.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "fmt"
5 | "github.com/garyburd/redigo/redis"
6 | "log"
7 | "strings"
8 | )
9 |
10 | var RedisPool *redis.Pool
11 |
12 | // NewRedisPool 新建一个Redis连接池 URL优先
13 | func NewRedisPool(addr, passwd string, db, maxIdle, MaxActive int) *redis.Pool {
14 | b := strings.HasPrefix(addr, "redis://")
15 | var dialFunc func() (redis.Conn, error)
16 | switch {
17 | case b && passwd == "":
18 | dialFunc = func() (redis.Conn, error) {
19 | return redis.DialURL(addr, redis.DialDatabase(db))
20 | }
21 | case b && passwd != "":
22 | dialFunc = func() (redis.Conn, error) {
23 | return redis.DialURL(addr, redis.DialDatabase(db), redis.DialPassword(passwd))
24 | }
25 | case !b && passwd == "":
26 | dialFunc = func() (redis.Conn, error) {
27 | return redis.Dial("tcp", addr, redis.DialDatabase(db))
28 | }
29 | case !b && passwd != "":
30 | dialFunc = func() (redis.Conn, error) {
31 | return redis.Dial("tcp", addr, redis.DialDatabase(db), redis.DialPassword(passwd))
32 | }
33 | }
34 |
35 | return &redis.Pool{
36 | MaxIdle: maxIdle,
37 | MaxActive: MaxActive,
38 | Dial: func() (redis.Conn, error) {
39 | c, err := dialFunc()
40 | if err != nil {
41 | log.Println(fmt.Errorf("redis 连接失败:%v", err))
42 | }
43 | return c, err
44 | },
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/engine/db/sqlx.go:
--------------------------------------------------------------------------------
1 | //MySql引擎层
2 | package db
3 |
4 | import (
5 | "fmt"
6 | "github.com/Masterminds/squirrel"
7 | "github.com/jmoiron/sqlx"
8 | "log"
9 | "time"
10 | )
11 |
12 | // sqlx 全局变量
13 | var Sqlx *sqlx.DB
14 | var ClickHouseSqlx *sqlx.DB
15 |
16 | // 用squirrel生成sql语句
17 | var SqlBuilder = squirrel.StatementBuilder
18 |
19 | type Eq = squirrel.Eq
20 | type Or = squirrel.Or
21 | type And = squirrel.And
22 |
23 | type NotEq = squirrel.NotEq
24 | type Gt = squirrel.Gt
25 | type Lt = squirrel.Lt
26 | type GtOrEq = squirrel.GtOrEq
27 | type LtOrEq = squirrel.LtOrEq
28 |
29 | type Like = squirrel.Like
30 | type Gte = squirrel.GtOrEq
31 | type Lte = squirrel.LtOrEq
32 | type SelectBuilder = squirrel.SelectBuilder
33 | type InsertBuilder = squirrel.InsertBuilder
34 | type UpdateBuilder = squirrel.UpdateBuilder
35 |
36 | // NewMySQL 创建一个连接MySQL的实体池
37 | func NewSQLX(driverName, dbSource string, maxOpenConns, maxIdleConns int) (db *sqlx.DB, err error) {
38 |
39 | db, err = sqlx.Open(driverName, dbSource)
40 | if err != nil {
41 | return
42 | }
43 | if maxOpenConns > 0 {
44 | db.SetMaxOpenConns(maxOpenConns)
45 | }
46 |
47 | if maxIdleConns > 0 {
48 | db.SetMaxIdleConns(maxIdleConns)
49 | }
50 | err = db.Ping()
51 | if err != nil {
52 | return
53 | }
54 | go func() {
55 | for {
56 | err = db.Ping()
57 | if err != nil {
58 | log.Println("mysql db can't connect!")
59 | }
60 | time.Sleep(time.Minute)
61 | }
62 | }()
63 | return
64 | }
65 |
66 | // 创建分页查询
67 | func CreatePage(page, limit uint64) uint64 {
68 | tmp := (page - 1) * limit
69 | return tmp
70 | }
71 |
72 | // 创建模糊查询
73 | func CreateLike(column string) string {
74 | return fmt.Sprint("%", column, "%")
75 | }
76 |
--------------------------------------------------------------------------------
/init_app_start.bat:
--------------------------------------------------------------------------------
1 | set dir = %cd%
2 |
3 | set args = "-configFileDir=%cd%\config"
4 |
5 | gowatch -p cmd/init_app/main.go -args=args -o bin/win/init_app.exe
--------------------------------------------------------------------------------
/manager_start.bat:
--------------------------------------------------------------------------------
1 | set dir = %cd%
2 |
3 | set args = "-configFileDir=%cd%\config"
4 |
5 | gowatch -p cmd/manager/main.go -args=args -o bin/win/manager.exe
--------------------------------------------------------------------------------
/middleware/Exception.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | // 内置异常
4 | const (
5 | INVALID_PARAMS int = 40001
6 | ERROR_AUTH_CHECK_TOKEN_FAIL int = 40002
7 | ERROR_AUTH_CHECK_TOKEN_TIMEOUT int = 40003
8 | ERROR_RBAC_LOAD int = 40004
9 | ERROR_RBAC_AUTH int = 40005
10 | )
11 |
12 | // 内置异常表 TOKEN_ERROR
13 | var TOKEN_ERROR = map[int]string{
14 | INVALID_PARAMS: "Token不能为空",
15 | ERROR_AUTH_CHECK_TOKEN_FAIL: "Token鉴权失败",
16 | ERROR_AUTH_CHECK_TOKEN_TIMEOUT: "Token已超时",
17 | ERROR_RBAC_LOAD: "读取rdbc权限列表失败",
18 | ERROR_RBAC_AUTH: "您没有该资源的访问权限",
19 | }
20 |
--------------------------------------------------------------------------------
/middleware/analysis_cache.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "github.com/1340691923/xwl_bi/platform-basic-libs/service/analysis"
5 | "github.com/1340691923/xwl_bi/platform-basic-libs/util"
6 | "github.com/gofiber/fiber/v2"
7 | "net/http"
8 | "time"
9 | )
10 |
11 | //防止狂点设置3秒的缓存
12 | func AnalysisCache(ctx *fiber.Ctx) error {
13 | cache := analysis.NewCache(time.Second*3, ctx.Path(), ctx.Body())
14 |
15 | resData, redisErr := cache.LoadData()
16 | if util.FilterRedisNilErr(redisErr) {
17 | return res.Error(ctx, redisErr)
18 | }
19 |
20 | if len(resData) > 0 {
21 | return ctx.Send(resData)
22 | }
23 |
24 | err := ctx.Next()
25 | if err != nil {
26 | return res.Error(ctx, err)
27 | }
28 | if ctx.Response().StatusCode() == http.StatusOK {
29 | err = cache.SetData(ctx.Response().Body())
30 | if err != nil {
31 | return res.Error(ctx, err)
32 | }
33 | }
34 |
35 | return err
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/middleware/filter_appid.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "errors"
5 | "github.com/1340691923/xwl_bi/platform-basic-libs/service/myapp"
6 | "github.com/1340691923/xwl_bi/platform-basic-libs/util"
7 | "github.com/gofiber/fiber/v2"
8 | "github.com/tidwall/gjson"
9 | )
10 |
11 | func FilterAppid(ctx *fiber.Ctx) error {
12 |
13 | appid := gjson.GetBytes(ctx.Body(), "appid").Int()
14 |
15 | if appid == 0 {
16 | return res.Error(ctx, errors.New("请先在左上角选择您的应用"))
17 | }
18 |
19 | list, err := myapp.GetAppidsByToken(util.GetToken(ctx))
20 |
21 | if err != nil {
22 | return res.Error(ctx, err)
23 | }
24 | haveApp := false
25 | for _, v := range list {
26 | if v.Id == int(appid) {
27 | haveApp = true
28 | break
29 | }
30 | }
31 |
32 | if !haveApp {
33 | return res.Error(ctx, errors.New("您不属于该应用成员"))
34 | }
35 |
36 | err = ctx.Next()
37 |
38 | return err
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/middleware/jwt.go:
--------------------------------------------------------------------------------
1 | // 中间件层
2 | package middleware
3 |
4 | import (
5 | "time"
6 |
7 | "github.com/1340691923/xwl_bi/platform-basic-libs/jwt"
8 | "github.com/1340691923/xwl_bi/platform-basic-libs/my_error"
9 | "github.com/1340691923/xwl_bi/platform-basic-libs/response"
10 | "github.com/1340691923/xwl_bi/platform-basic-libs/service/gm_user"
11 | "github.com/1340691923/xwl_bi/platform-basic-libs/util"
12 | fiber "github.com/gofiber/fiber/v2"
13 | )
14 |
15 | var res response.Response
16 |
17 | func JwtMiddleware(c *fiber.Ctx) error {
18 |
19 | var err error
20 | var claims *jwt.Claims
21 | token := util.GetToken(c)
22 | if _, logoff := util.TokenBucket.Load(token); logoff {
23 | err = my_error.NewBusiness(TOKEN_ERROR, ERROR_AUTH_CHECK_TOKEN_FAIL)
24 | return res.Error(c, err)
25 | }
26 |
27 | if util.GetToken(c) == "" {
28 | err = my_error.NewBusiness(TOKEN_ERROR, INVALID_PARAMS)
29 | return res.Error(c, err)
30 | }
31 |
32 | var service gm_user.GmUserService
33 | claims, err = jwt.ParseToken(token)
34 | if err != nil {
35 | err = my_error.NewBusiness(TOKEN_ERROR, ERROR_AUTH_CHECK_TOKEN_FAIL)
36 | return res.Error(c, err)
37 | }
38 | if time.Now().Unix() > claims.ExpiresAt {
39 | err = my_error.NewBusiness(TOKEN_ERROR, ERROR_AUTH_CHECK_TOKEN_TIMEOUT)
40 | return res.Error(c, err)
41 | }
42 | if !service.IsExitUser(claims) {
43 | err = my_error.NewBusiness(TOKEN_ERROR, ERROR_AUTH_CHECK_TOKEN_TIMEOUT)
44 | return res.Error(c, err)
45 | }
46 |
47 | return c.Next()
48 | }
49 |
--------------------------------------------------------------------------------
/middleware/operater_log.go:
--------------------------------------------------------------------------------
1 | // 中间件层
2 | package middleware
3 |
4 | import (
5 | "github.com/1340691923/xwl_bi/engine/logs"
6 | "github.com/1340691923/xwl_bi/model"
7 | "github.com/1340691923/xwl_bi/platform-basic-libs/jwt"
8 | "github.com/1340691923/xwl_bi/platform-basic-libs/util"
9 | fiber "github.com/gofiber/fiber/v2"
10 | "go.uber.org/zap"
11 | )
12 |
13 | //fiber 没有将fasthttp的
14 | func OperaterLog(ctx *fiber.Ctx) error {
15 |
16 | var err error
17 | token := util.GetToken(ctx)
18 | var claims *jwt.Claims
19 | claims, err = jwt.ParseToken(token)
20 | if err != nil {
21 | logs.Logger.Error("OperaterLog jwt err", zap.Error(err))
22 | return err
23 | }
24 |
25 | gmOperaterLog := model.GmOperaterLog{
26 | OperaterName: claims.Username,
27 | OperaterId: int(claims.UserID),
28 | OperaterAction: ctx.Path(),
29 | Method: ctx.Method(),
30 | Body: ctx.Body(),
31 | OperaterRoleId: int(claims.RoleId),
32 | }
33 |
34 | err = gmOperaterLog.Insert()
35 |
36 | if err != nil {
37 | logs.Logger.Error("OperaterLog", zap.Error(err))
38 | }
39 |
40 | return ctx.Next()
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/middleware/rbac.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "go.uber.org/zap"
5 | "strconv"
6 |
7 | "github.com/1340691923/xwl_bi/engine/logs"
8 | "github.com/1340691923/xwl_bi/platform-basic-libs/api_config"
9 | "github.com/1340691923/xwl_bi/platform-basic-libs/jwt"
10 | "github.com/1340691923/xwl_bi/platform-basic-libs/my_error"
11 | "github.com/1340691923/xwl_bi/platform-basic-libs/rbac"
12 | "github.com/1340691923/xwl_bi/platform-basic-libs/util"
13 | fiber "github.com/gofiber/fiber/v2"
14 | )
15 |
16 | const ADMIN_ROLE = 1
17 |
18 | func Rbac(ctx *fiber.Ctx) error {
19 | var err error
20 | token := util.GetToken(ctx)
21 | var claims *jwt.Claims
22 | claims, err = jwt.ParseToken(token)
23 | if err != nil {
24 | logs.Logger.Error("Rbac ", zap.Error(err))
25 | return err
26 | }
27 | obj := ctx.Path()
28 |
29 | sub := int(claims.RoleId)
30 | apiRouterConfig := api_config.NewApiRouterConfig()
31 | //最高权限用户可免接口鉴权
32 | if sub == ADMIN_ROLE {
33 | return ctx.Next()
34 | }
35 | for _, routerConfig := range apiRouterConfig.GetRouterConfigs() {
36 | if obj == routerConfig.Url {
37 | ok, err := rbac.Enforcer.EnforceSafe(strconv.Itoa(sub), obj, "*")
38 | if err != nil {
39 | return res.Error(ctx, my_error.NewBusiness(TOKEN_ERROR, ERROR_RBAC_LOAD))
40 | }
41 | if !ok {
42 | return res.Error(ctx, my_error.NewBusiness(TOKEN_ERROR, ERROR_RBAC_AUTH))
43 | }
44 | }
45 | }
46 | return ctx.Next()
47 | }
48 |
--------------------------------------------------------------------------------
/middleware/time.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/1340691923/xwl_bi/engine/logs"
7 | fiber "github.com/gofiber/fiber/v2"
8 | "go.uber.org/zap"
9 | )
10 |
11 | func Timer(ctx *fiber.Ctx) error {
12 |
13 | // start timer
14 | start := time.Now()
15 | // next routes
16 | err := ctx.Next()
17 | // stop timer
18 | stop := time.Now()
19 |
20 | logs.Logger.Info("时间拦截器",
21 | zap.String("访问资源",ctx.Path()),
22 | zap.Reflect("body",string(ctx.Body())),
23 | zap.String("消耗时间:", stop.Sub(start).String()))
24 | return err
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/model/app.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | type App struct {
4 | Page uint64 `json:"page" db:"-"`
5 | Limit uint64 `json:"limit" db:"-"`
6 | IsClose *int `db:"is_close" json:"is_close"`
7 | Id int `db:"id" json:"id"`
8 | CreateBy int `db:"create_by" json:"create_by"`
9 | UpdateBy int `db:"update_by" json:"update_by"`
10 | SaveMonth int `db:"save_mouth" json:"save_mouth"`
11 | AppName string `db:"app_name" json:"app_name"`
12 | Descibe string `db:"descibe" json:"descibe"`
13 | AppId string `db:"app_id" json:"app_id"`
14 | AppKey string `db:"app_key" json:"app_key"`
15 | CreateTime string `db:"create_time" json:"create_time"`
16 | UpdateTime string `db:"update_time" json:"update_time"`
17 | AppManager string `db:"app_manager" json:"app_manager"`
18 | }
19 |
--------------------------------------------------------------------------------
/model/crud.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "github.com/1340691923/xwl_bi/engine/db"
5 | )
6 |
7 | type Curd interface {
8 | ProcessSqlWhere(sqlA db.SelectBuilder) db.SelectBuilder
9 | TableName() string
10 | ProcessSqlInsert(sqlA db.InsertBuilder) db.InsertBuilder
11 | ProcessSqlUpdate(id int, sqlA db.UpdateBuilder) db.UpdateBuilder
12 | }
13 |
14 | func SearchList(curd Curd, page, limit int, columns string, list interface{}) (err error) {
15 | sqlA := db.
16 | SqlBuilder.
17 | Select(columns).
18 | From(curd.TableName())
19 | sqlA = curd.ProcessSqlWhere(sqlA)
20 | sql, args, err := sqlA.
21 | Limit(uint64(limit)).
22 | Offset(db.CreatePage(uint64(page), uint64(limit))).
23 | OrderBy("id desc").
24 | ToSql()
25 | err = db.Sqlx.Select(list, sql, args...)
26 | return
27 | }
28 |
29 | func Count(curd Curd) (count int, err error) {
30 | sqlA := db.SqlBuilder.
31 | Select("count(*)").
32 | From(curd.TableName())
33 | sqlA = curd.ProcessSqlWhere(sqlA)
34 | sql, args, err := sqlA.ToSql()
35 | err = db.Sqlx.Get(&count, sql, args...)
36 | return
37 | }
38 |
--------------------------------------------------------------------------------
/model/debug_device.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | type DebugDevice struct {
4 | Id int `db:"id" json:"id"`
5 | Appid int `db:"appid" json:"appid"`
6 | DeviceId string `db:"device_id" json:"device_id"`
7 | Remark string `db:"remark" json:"remark"`
8 | CreateBy int `db:"create_by" json:"create_by"`
9 | CreateTime string `db:"create_time" json:"create_time"`
10 | }
11 |
--------------------------------------------------------------------------------
/model/gm_role.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import "github.com/1340691923/xwl_bi/engine/db"
4 |
5 | // GmRoleModel
6 | type GmRoleModel struct {
7 | ID int `json:"id" db:"id"`
8 | RoleName string `json:"name" db:"role_name"`
9 | Description string `json:"description" db:"description"`
10 | RoleList string `json:"routes" db:"role_list"`
11 | }
12 |
13 | // GetById
14 | func (this *GmRoleModel) GetById(roleId int) (model GmRoleModel, err error) {
15 | err = db.Sqlx.Get(&model, "select id,role_name,description,role_list from gm_role where id = ?;", roleId)
16 | return
17 | }
18 |
19 | // Update
20 | func (this *GmRoleModel) Update() (err error) {
21 | _, err = db.Sqlx.Exec(
22 | "update gm_role set role_name = ?,description=?,role_list=? where id = ?;",
23 | this.RoleName, this.Description, this.RoleList, this.ID)
24 | return
25 | }
26 |
27 | // Delete
28 | func (this *GmRoleModel) Delete() (err error) {
29 | _, err = db.Sqlx.Exec("delete from gm_role where id = ? ;", this.ID)
30 | return
31 | }
32 |
33 | // Insert
34 | func (this *GmRoleModel) Insert() (id int64, err error) {
35 | rlt, err := db.Sqlx.Exec(
36 | "insert into gm_role (role_name,description,role_list) values (?,?,?);",
37 | this.RoleName, this.Description, this.RoleList)
38 | if err != nil {
39 | return
40 | }
41 | id, err = rlt.LastInsertId()
42 | if err != nil {
43 | return
44 | }
45 | return
46 | }
47 |
48 | // Select
49 | func (this *GmRoleModel) Select() (model []GmRoleModel, err error) {
50 | err = db.Sqlx.Select(&model, "select role_name,description,role_list,id from gm_role;")
51 | return
52 | }
53 |
--------------------------------------------------------------------------------
/model/message.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import "time"
4 |
5 | type InputMessage struct {
6 | Topic string
7 | Partition int
8 | Key []byte
9 | Value []byte
10 | Offset int64
11 | Timestamp *time.Time
12 | }
13 |
--------------------------------------------------------------------------------
/model/pannel_folder.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | type PannelFolder struct {
4 | Id int `db:"id" json:"id"`
5 | FolderName string `db:"folder_name" json:"folder_name"`
6 | FolderType int8 `db:"folder_type" json:"folder_type"` //0为自己创建的
7 | CreateBy int `db:"create_by" json:"create_by"`
8 | CreateTime string `db:"create_time" json:"create_time"`
9 | UpdateTime string `db:"update_time" json:"update_time"`
10 | Appid int `db:"appid" json:"appid"`
11 | }
12 |
13 | type Pannel struct {
14 | Id int `db:"id" json:"id"`
15 | FolderId int `db:"folder_id" json:"folder_id"`
16 | PannelName string `db:"pannel_name" json:"pannel_name"`
17 | Managers string `db:"managers" json:"managers"`
18 | CreateBy int `db:"create_by" json:"create_by"`
19 | CreateTime int64 `db:"create_time" json:"create_time"`
20 | UpdateTime int64 `db:"update_time" json:"update_time"`
21 | ReportTables string `db:"report_tables" json:"report_tables"`
22 | }
23 |
--------------------------------------------------------------------------------
/model/report_table.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import "github.com/1340691923/xwl_bi/engine/db"
4 |
5 | type ReportTable struct {
6 | Id int `db:"id" json:"id"`
7 | Appid int `db:"appid" json:"appid"`
8 | UserId int `db:"user_id" json:"user_id"`
9 | Name string `db:"name" json:"name"`
10 | RtType int8 `db:"rt_type" json:"rt_type"`
11 | Data string `db:"data" json:"data"`
12 | CreateTime string `db:"create_time" json:"create_time"`
13 | UpdateTime string `db:"update_time" json:"update_time"`
14 | Remark string `db:"remark" json:"remark"`
15 | }
16 |
17 | func (this *ReportTable) InsertOrUpdate() (err error) {
18 | sql := `insert into report_table(appid,user_id,name,rt_type,data,remark)values(?,?,?,?,?,?) on duplicate key update data=?,remark=?`
19 | _, err = db.Sqlx.Exec(sql, this.Appid, this.UserId, this.Name, this.RtType, this.Data, this.Remark, this.Data, this.Remark)
20 | return
21 | }
22 |
--------------------------------------------------------------------------------
/platform-basic-libs/jwt/exception.go:
--------------------------------------------------------------------------------
1 | package jwt
2 |
3 | // 内置异常
4 | const (
5 | ERROR_AUTH_TOKEN = 40006
6 | )
7 |
8 | var TOKEN_ERROR = map[int]string{
9 | ERROR_AUTH_TOKEN: "Token生成失败",
10 | }
11 |
--------------------------------------------------------------------------------
/platform-basic-libs/my_error/my_error.go:
--------------------------------------------------------------------------------
1 | //自定义异常层
2 | package my_error
3 |
4 | //自定义异常结构体 实现Error方法
5 | type MyError struct {
6 | code int
7 | msg string
8 | }
9 |
10 | // 自定义业务异常
11 | func NewBusiness(ErrEnum map[int]string, code int) error {
12 | text := ErrEnum[code]
13 | return &MyError{code, text}
14 | }
15 |
16 | func NewError(text string, code int) error {
17 | return &MyError{code, text}
18 | }
19 |
20 | func (this *MyError) Error() string {
21 | return this.msg
22 | }
23 |
24 | func (this *MyError) Code() int {
25 | return this.code
26 | }
27 |
--------------------------------------------------------------------------------
/platform-basic-libs/rbac/index.go:
--------------------------------------------------------------------------------
1 | package rbac
2 |
3 | import (
4 | "github.com/casbin/casbin"
5 | xormadapter "github.com/casbin/xorm-adapter"
6 | )
7 |
8 | var Enforcer *casbin.Enforcer
9 |
10 | func Run(driverName string, datasource string) (err error) {
11 | text := `
12 | [request_definition]
13 | r = sub, obj, act
14 |
15 | [policy_definition]
16 | p = sub, obj, act
17 |
18 | [policy_effect]
19 | e = some(where (p.eft == allow))
20 |
21 | [matchers]
22 | m = r.sub == p.sub && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*") || r.sub == "1"
23 | `
24 | policy := casbin.NewModel(text)
25 |
26 | model := xormadapter.NewAdapter(driverName, datasource, true)
27 | Enforcer = casbin.NewEnforcer(policy, model)
28 | err = Enforcer.LoadPolicy()
29 |
30 | return
31 | }
32 |
--------------------------------------------------------------------------------
/platform-basic-libs/request/Exception.go:
--------------------------------------------------------------------------------
1 | //自定义请求辅助方法层
2 | package request
3 |
4 | //自定义业务异常
5 | const (
6 | IdNullError = 100002
7 | EmptyParmasError = 100003
8 | EmptyEventError = 100004
9 | )
10 |
11 | var ErrorMap = map[int]string{
12 | IdNullError: "id不能为空!",
13 | EmptyParmasError: "请求参数不能为空",
14 | EmptyEventError: "事件名不能为空",
15 | }
16 |
--------------------------------------------------------------------------------
/platform-basic-libs/request/Request.go:
--------------------------------------------------------------------------------
1 | package request
2 |
3 | import (
4 | "github.com/tidwall/gjson"
5 | "strconv"
6 | "strings"
7 |
8 | "github.com/1340691923/xwl_bi/platform-basic-libs/my_error"
9 | fiber "github.com/gofiber/fiber/v2"
10 | )
11 |
12 | //自定义请求 辅助方法
13 | type Request struct {
14 | }
15 |
16 | type CheckConfigStruct struct {
17 | Code int
18 | Key string
19 | }
20 |
21 | //检查请求参数
22 | func (this Request) CheckParameter(checkConfig []CheckConfigStruct, ctx *fiber.Ctx) (err error) {
23 | method := strings.ToUpper(ctx.Method())
24 | for _, config := range checkConfig {
25 | switch method {
26 | case "GET":
27 | if ctx.FormValue(config.Key) == "" {
28 | err = my_error.NewBusiness(ErrorMap, config.Code)
29 | return
30 | }
31 | case "POST":
32 | if !gjson.GetBytes(ctx.Body(), config.Key).Exists() {
33 | err = my_error.NewBusiness(ErrorMap, config.Code)
34 | return
35 | }
36 | }
37 |
38 | }
39 | return
40 | }
41 |
42 | // FormIntDefault 获取Form参数 如果出错则返回默认值
43 | func (this Request) FormIntDefault(ctx *fiber.Ctx, key string, def int) int {
44 | i, err := strconv.Atoi(ctx.FormValue(key))
45 | if err != nil {
46 | return def
47 | }
48 | return i
49 | }
50 |
51 | //获取用户token信息
52 | func (this Request) GetToken(ctx *fiber.Ctx) (token string) {
53 | return ctx.Get("X-Token")
54 | }
55 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/analysis/cache.go:
--------------------------------------------------------------------------------
1 | package analysis
2 |
3 | import (
4 | "fmt"
5 | "github.com/1340691923/xwl_bi/engine/db"
6 | "github.com/1340691923/xwl_bi/engine/logs"
7 | "github.com/1340691923/xwl_bi/platform-basic-libs/util"
8 | "github.com/garyburd/redigo/redis"
9 | "go.uber.org/zap"
10 | "time"
11 | )
12 |
13 | type Cache struct {
14 | overTime int `json:"over_time"`
15 | analysisType string `json:"cache_key"`
16 | reqData []byte `json:"req_data"`
17 | }
18 |
19 | func ClearCacheByAppid(key string) (err error) {
20 | conn := db.RedisPool.Get()
21 | defer conn.Close()
22 | _, err = conn.Do("unlink", key)
23 | if err != nil {
24 | _, err = conn.Do("del", key)
25 | if err != nil {
26 | logs.Logger.Error("err", zap.Error(err))
27 | }
28 | }
29 | return
30 | }
31 |
32 | func NewCache(overTime time.Duration, analysisType string, reqData []byte) *Cache {
33 | return &Cache{overTime: int(overTime.Seconds()), analysisType: analysisType, reqData: reqData}
34 | }
35 |
36 | func (this *Cache) getKey() string {
37 | return fmt.Sprintf("%s_%s", this.analysisType, util.MD5HexHash(this.reqData))
38 | }
39 |
40 | func (this *Cache) LoadData() (b []byte, err error) {
41 | conn := db.RedisPool.Get()
42 | defer conn.Close()
43 | b, err = redis.Bytes(conn.Do("get", this.getKey()))
44 | return
45 | }
46 |
47 | func (this *Cache) SetData(b []byte) (err error) {
48 | conn := db.RedisPool.Get()
49 | defer conn.Close()
50 | _, err = conn.Do("SETEX", this.getKey(), this.overTime, b)
51 | return
52 | }
53 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/analysis/exception.go:
--------------------------------------------------------------------------------
1 | package analysis
2 |
3 | // 内置异常
4 | const (
5 | TimeError int = 60001
6 | ZhiBiaoNumError int = 60002
7 | GroupNumError int = 60003
8 | GroupEmptyError int = 60004
9 | UIEmptyError int = 60005
10 | EventNameEmptyError int = 60006
11 | )
12 |
13 | // 内置异常表
14 | var ERROR_TABLE = map[int]string{
15 | TimeError: "筛选时间异常",
16 | ZhiBiaoNumError: "筛选指标个数异常",
17 | GroupNumError: "筛选分组个数异常",
18 | GroupEmptyError: "筛选分组不能为空字段",
19 | UIEmptyError: "用户id列表不能为空",
20 | EventNameEmptyError: "事件名不能为空",
21 | }
22 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/analysis/interface.go:
--------------------------------------------------------------------------------
1 | package analysis
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | )
7 |
8 | type Ianalysis interface {
9 | GetList() (interface{}, error)
10 | GetExecSql() (SQL string, allArgs []interface{}, err error) //后续开发 查看执行sql功能
11 | }
12 |
13 | type Command int
14 |
15 | const (
16 | FunnelComand Command = 1
17 | RetentionComand Command = 2
18 | TraceComand Command = 3
19 | EventComand Command = 4
20 | UserAttrCommand Command = 5
21 | UserListCommand Command = 6
22 | UserEventDetailListCommand Command = 7
23 | UserEventCountCommand Command = 8
24 | )
25 |
26 | var commandMap = map[Command]func(reqData []byte) (Ianalysis, error){
27 | FunnelComand: NewFunnel,
28 | RetentionComand: NewRetention,
29 | TraceComand: NewTrace,
30 | EventComand: NewEvent,
31 | UserAttrCommand: NewUserAttr,
32 | UserListCommand: NewUserList,
33 | UserEventDetailListCommand: NewUserEventDetailList,
34 | UserEventCountCommand: NewUserEventCountList,
35 | }
36 |
37 | func NewAnalysisByCommand(command Command, reqData []byte) (i Ianalysis, err error) {
38 | var fn func(reqData []byte) (Ianalysis, error)
39 | var found bool
40 | if fn, found = commandMap[command]; !found {
41 | return nil, errors.New(fmt.Sprintf("没有找到该命令:%v", command))
42 | }
43 |
44 | return fn(reqData)
45 | }
46 |
47 | func GetAnalysisRes(i Ianalysis) (res interface{}, err error) {
48 | return i.GetList()
49 | }
50 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/analysis/utils.go:
--------------------------------------------------------------------------------
1 | package analysis
2 |
3 | import (
4 | "fmt"
5 | "github.com/1340691923/xwl_bi/engine/logs"
6 | "github.com/1340691923/xwl_bi/platform-basic-libs/request"
7 | "github.com/1340691923/xwl_bi/platform-basic-libs/service/analysis/utils"
8 | )
9 |
10 | func getUserfilterSqlArgs(analysisFilter request.AnalysisFilter, appid int) (userFilterSql string, userFilterArgs []interface{}, err error) {
11 | if len(analysisFilter.Filts) > 0 {
12 | var colArr []string
13 | var sql string
14 | sql, userFilterArgs, colArr, err = utils.GetWhereSql(analysisFilter)
15 | if err != nil {
16 | return
17 | }
18 | userFilterSql = ` and xwl_distinct_id in ( select xwl_distinct_id from ` + utils.GetUserTableView(appid, colArr) + ` where ` + sql + ") "
19 | }
20 | return
21 | }
22 |
23 | func getZhibiaoFilterSqlArgs(zhibiaoArr []request.Zhibiao) (windowSql string, allArgs []interface{}, err error) {
24 |
25 | for _, zhibiao := range zhibiaoArr {
26 | windowSql = windowSql + ","
27 |
28 | windowSql = windowSql + fmt.Sprintf(" xwl_part_event = '%v' ", zhibiao.EventName)
29 |
30 | if len(zhibiao.Relation.Filts) > 0 {
31 | windowSql = windowSql + " and "
32 | sql, args, _, err := utils.GetWhereSql(zhibiao.Relation)
33 |
34 | if err != nil {
35 | logs.Logger.Sugar().Errorf("zhibiao.Relation", zhibiao)
36 | return windowSql, allArgs, err
37 | }
38 |
39 | allArgs = append(allArgs, args...)
40 |
41 | windowSql = windowSql + sql
42 | }
43 | }
44 |
45 | return windowSql, allArgs, err
46 | }
47 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/analysis/utils/user_group.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "github.com/1340691923/xwl_bi/engine/db"
5 | "github.com/1340691923/xwl_bi/model"
6 | "github.com/1340691923/xwl_bi/platform-basic-libs/util"
7 | "github.com/Masterminds/squirrel"
8 | "strings"
9 | )
10 |
11 | func GetUserGroupSqlAndArgs(ids []int, appid int) (SQL string, Args []interface{}, err error) {
12 | if len(ids) == 0 {
13 | return " and ( 1 = 1 ) ", nil, err
14 | }
15 |
16 | sql, args, err := db.
17 | SqlBuilder.
18 | Select("user_list").
19 | From("user_group").
20 | Where(db.Eq{"appid": appid, "id": ids}).
21 | ToSql()
22 |
23 | var userGroupList []model.UserGroup
24 |
25 | err = db.Sqlx.Select(&userGroupList, sql, args...)
26 |
27 | if err != nil {
28 | return "", nil, err
29 | }
30 |
31 | or := squirrel.Or{}
32 |
33 | for index := range userGroupList {
34 | idStr, err := util.GzipUnCompress(userGroupList[index].UserList)
35 | if err != nil {
36 | return "", nil, err
37 | }
38 | id := strings.Split(idStr, ",")
39 | or = append(or, db.Eq{"xwl_distinct_id": [][]string{id}})
40 | }
41 |
42 | SQL, Args, err = or.ToSql()
43 | SQL = " and " + SQL
44 | return SQL, Args, err
45 | }
46 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/debug_data/debug_data.go:
--------------------------------------------------------------------------------
1 | package debug_data
2 |
3 | import (
4 | "github.com/1340691923/xwl_bi/engine/db"
5 | "github.com/1340691923/xwl_bi/model"
6 | )
7 |
8 | type DebugData struct {
9 | }
10 |
11 | func (this *DebugData) AddDebugDeviceID(appid, deviceID, remark string, managerUid int32) (err error) {
12 |
13 | _, err = db.
14 | SqlBuilder.
15 | Insert("debug_device").
16 | SetMap(map[string]interface{}{
17 | "remark": remark,
18 | "device_id": deviceID,
19 | "appid": appid,
20 | "create_by": managerUid,
21 | }).RunWith(db.Sqlx).Exec()
22 |
23 | if err != nil {
24 | return
25 | }
26 |
27 | Hash := "DebugDeviceID_" + appid
28 | conn := db.RedisPool.Get()
29 | defer conn.Close()
30 | _, err = conn.Do("sadd", Hash, deviceID)
31 |
32 | if err != nil {
33 | return
34 | }
35 |
36 | return
37 | }
38 |
39 | func (this *DebugData) DelDebugDeviceID(appid, deviceID string, managerUid int32) (err error) {
40 |
41 | _, err = db.SqlBuilder.
42 | Delete("debug_device").
43 | Where(db.Eq{"device_id": deviceID, "appid": appid, "create_by": managerUid}).
44 | RunWith(db.Sqlx).
45 | Exec()
46 | if err != nil {
47 | return
48 | }
49 | Hash := "DebugDeviceID_" + appid
50 | conn := db.RedisPool.Get()
51 | defer conn.Close()
52 | _, err = conn.Do("srem", Hash, deviceID)
53 |
54 | if err != nil {
55 | return
56 | }
57 |
58 | return
59 | }
60 |
61 | func (this *DebugData) DebugDeviceIDList(appid int, managerUid int32) (res []model.DebugDevice, err error) {
62 |
63 | sql, args, err := db.SqlBuilder.
64 | Select("*").
65 | From("debug_device").
66 | Where(db.Eq{"appid": appid, "create_by": managerUid}).
67 | ToSql()
68 | if err != nil {
69 | return
70 | }
71 |
72 | err = db.Sqlx.Select(&res, sql, args...)
73 | if err != nil {
74 | return
75 | }
76 |
77 | return
78 | }
79 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/gm_operater_log/gm_operater_log_service.go:
--------------------------------------------------------------------------------
1 | package gm_operater_log
2 |
3 | import (
4 | "github.com/1340691923/xwl_bi/engine/logs"
5 | "github.com/1340691923/xwl_bi/model"
6 | "github.com/1340691923/xwl_bi/platform-basic-libs/request"
7 | "github.com/1340691923/xwl_bi/platform-basic-libs/util"
8 | "go.uber.org/zap"
9 | )
10 |
11 | type GmOperaterLogService struct {
12 | }
13 |
14 | func (this *GmOperaterLogService) List(reqData request.GmOperaterLogList) (list []model.GmOperaterLog, count int, err error) {
15 | if reqData.Page <= 0 {
16 | reqData.Page = 1
17 | }
18 | if reqData.Limit <= 0 {
19 | reqData.Limit = 10
20 | }
21 |
22 | page := reqData.Page
23 | limit := reqData.Limit
24 |
25 | operater_action := reqData.OperaterAction
26 |
27 | gmOperaterModel := &model.GmOperaterLog{
28 | OperaterRoleId: reqData.RoleId,
29 | OperaterId: reqData.UserId,
30 | OperaterAction: operater_action,
31 | FilterDate: reqData.Date,
32 | }
33 | listP := &list
34 | err = model.SearchList(gmOperaterModel, page, limit, "*", listP)
35 | if err != nil {
36 | return
37 | }
38 | count, err = model.Count(gmOperaterModel)
39 | if err != nil {
40 | return
41 | }
42 |
43 | for index := range list {
44 |
45 | body, err := util.GzipUnCompress(list[index].Body)
46 | if err != nil {
47 | logs.Logger.Error("err", zap.Error(err))
48 | continue
49 | }
50 |
51 | list[index].BodyStr = body
52 | }
53 | return
54 | }
55 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/gm_user/exception.go:
--------------------------------------------------------------------------------
1 | package gm_user
2 |
3 | // 自定义业务异常
4 | const (
5 | ERROR_AUTH_TOKEN = 40006
6 | ERROR_AUTH = 40007
7 | )
8 |
9 | var AUTH_ERROR = map[int]string{
10 | ERROR_AUTH_TOKEN: "Token生成失败",
11 | ERROR_AUTH: "用户验证失败",
12 | }
13 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/gm_user/gm_user_service.go:
--------------------------------------------------------------------------------
1 | //BI用户层
2 | package gm_user
3 |
4 | import (
5 | "errors"
6 | "github.com/1340691923/xwl_bi/engine/db"
7 | "github.com/1340691923/xwl_bi/engine/logs"
8 | "github.com/1340691923/xwl_bi/model"
9 | "github.com/1340691923/xwl_bi/platform-basic-libs/jwt"
10 | "github.com/1340691923/xwl_bi/platform-basic-libs/util"
11 | "go.uber.org/zap"
12 | "time"
13 | )
14 |
15 | // GmUserService
16 | type GmUserService struct {
17 | }
18 |
19 | func (this GmUserService) CheckLogin(username, password string) (token string, err error) {
20 | var model2 model.GmUserModel
21 | model2.Password = password
22 | model2.Username = username
23 | gmUser, err := model2.GetUserByUP()
24 |
25 | if err != nil {
26 | logs.Logger.Error("登陆失败", zap.Error(err))
27 | err = errors.New("用户验证失败")
28 | return
29 | }
30 |
31 | if gmUser.IsDel == 1 {
32 | err = errors.New("您的账号已被封禁")
33 | return
34 | }
35 |
36 | db.SqlBuilder.
37 | Update("gm_user").
38 | SetMap(map[string]interface{}{"last_login_time": time.Now().Format(util.TimeFormat)}).
39 | Where(db.Eq{"id": gmUser.ID}).
40 | RunWith(db.Sqlx).
41 | Exec()
42 |
43 | token, err = jwt.GenerateToken(gmUser)
44 | if err != nil {
45 | return
46 | }
47 | return
48 | }
49 |
50 | func (this GmUserService) GetRoleInfo(roleId int32) (gminfo model.GmRoleModel, err error) {
51 | var model2 model.GmRoleModel
52 | gminfo, err = model2.GetById(int(roleId))
53 | if err != nil {
54 | return
55 | }
56 | return
57 | }
58 |
59 | func (this GmUserService) IsExitUser(claims *jwt.Claims) bool {
60 | var model2 model.GmUserModel
61 | model2.Username = claims.Username
62 | model2.RoleId = claims.RoleId
63 | return model2.Exsit()
64 | }
65 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/myapp/redis.go:
--------------------------------------------------------------------------------
1 | package myapp
2 |
3 | import (
4 | "fmt"
5 | "github.com/1340691923/xwl_bi/engine/db"
6 | "github.com/1340691923/xwl_bi/engine/logs"
7 | "github.com/garyburd/redigo/redis"
8 | "go.uber.org/zap"
9 | )
10 |
11 | const AppidToTableidHash = "AppidToTableid"
12 |
13 | func SetAppidToTableid(appid, appkey string, tableID int) (err error) {
14 | conn := db.RedisPool.Get()
15 | defer conn.Close()
16 | _, err = conn.Do("hset", AppidToTableidHash, fmt.Sprintf("%s_xwl_%s", appid, appkey), tableID)
17 | if err != nil {
18 | logs.Logger.Error("SetAppidToTableid err", zap.Error(err))
19 | }
20 | return
21 | }
22 |
23 | func GetAppidToTableid(conn redis.Conn, key string) (tableID string, err error) {
24 | tableID, err = redis.String(conn.Do("hget", AppidToTableidHash, key))
25 | return
26 | }
27 |
28 | func DeleteAppidToTableid(appid, appkey string) (err error) {
29 | conn := db.RedisPool.Get()
30 | defer conn.Close()
31 | _, err = conn.Do("hdel", AppidToTableidHash, fmt.Sprintf("%s_xwl_%s", appid, appkey))
32 | if err != nil {
33 | logs.Logger.Error("DeleteAppidToTableid", zap.Error(err))
34 | }
35 | return
36 | }
37 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/myapp/utils.go:
--------------------------------------------------------------------------------
1 | package myapp
2 |
3 | import (
4 | "fmt"
5 | "github.com/1340691923/xwl_bi/engine/db"
6 | "github.com/1340691923/xwl_bi/model"
7 | "github.com/1340691923/xwl_bi/platform-basic-libs/jwt"
8 | )
9 |
10 | func GetAppidsByToken(token string) (list []model.App, err error) {
11 | c, _ := jwt.ParseToken(token)
12 |
13 | selectBuilder := db.SqlBuilder.
14 | Select("id,app_name").
15 | From("app")
16 |
17 | if c.UserID != 1 {
18 | selectBuilder = selectBuilder.Where(fmt.Sprintf("FIND_IN_SET(%v,app_manager)", c.UserID)).Where(db.Eq{"is_close": 0})
19 | }
20 |
21 | sql, args, err := selectBuilder.ToSql()
22 |
23 | if err != nil {
24 | return
25 | }
26 |
27 | err = db.Sqlx.Select(&list, sql, args...)
28 | if err != nil {
29 | return
30 | }
31 |
32 | return
33 | }
34 |
--------------------------------------------------------------------------------
/platform-basic-libs/service/report/Exception.go:
--------------------------------------------------------------------------------
1 | package report
2 |
3 | // 内置异常
4 | const (
5 | ServerErr int = 10001
6 | AppParmasErr int = 10002
7 | ReportTypeErr int = 10003
8 | )
9 |
10 | // 内置异常表 TOKEN_ERROR
11 | var ERROR_TABLE = map[int]string{
12 | ServerErr: "服务异常",
13 | AppParmasErr: "appid错误或者appkey错误",
14 | ReportTypeErr: "上报类型错误",
15 | }
16 |
--------------------------------------------------------------------------------
/platform-basic-libs/sinker/model/metric.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "sync"
5 | )
6 |
7 | type Metric interface {
8 | GetInt(key string, nullable bool) (val interface{})
9 | GetFloat(key string, nullable bool) (val interface{})
10 | GetString(key string, nullable bool) (val interface{})
11 | GetDateTime(key string, nullable bool) (val interface{})
12 | GetElasticDateTime(key string, nullable bool) (val interface{})
13 | GetArray(key string, t int) (val interface{})
14 | GetNewKeys(knownKeys *sync.Map, newKeys *sync.Map) bool
15 | }
16 |
17 | type DimMetrics struct {
18 | Dims []*ColumnWithType
19 | Fields []*ColumnWithType
20 | }
21 |
22 | type ColumnWithType struct {
23 | Name string
24 | Type int
25 | Nullable bool
26 | SourceName string
27 | }
28 |
--------------------------------------------------------------------------------
/platform-basic-libs/sinker/model/topic.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | const ReportEventProperties = "reportEvent"
4 | const ReportUserProperties = "reportUser"
5 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/config.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "encoding/json"
5 | "io/ioutil"
6 | "strconv"
7 | "strings"
8 | )
9 |
10 | // LoadJSONConfig 读取配置文件 json格式
11 | func LoadJSONConfig(filename string, v interface{}) error {
12 | b, err := ioutil.ReadFile(filename)
13 | if err != nil {
14 | return err
15 | }
16 | err = json.Unmarshal(b, v)
17 | if err != nil {
18 | return err
19 | }
20 | return nil
21 | }
22 |
23 | func JoinInt(s []int, sp string) string {
24 | var tmp = make([]string, 0, len(s))
25 | for i, _ := range s {
26 | tmp = append(tmp, strconv.Itoa(s[i]))
27 | }
28 | return strings.Join(tmp, sp)
29 | }
30 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/convert.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import jsoniter "github.com/json-iterator/go"
4 |
5 | func Model2Map(m interface{}, needZeroByInt, needZeroByString bool) (res map[string]interface{}) {
6 | res = map[string]interface{}{}
7 | var json = jsoniter.ConfigCompatibleWithStandardLibrary
8 | b, _ := json.Marshal(m)
9 | json.Unmarshal(b, &res)
10 | for k, v := range res {
11 | switch v.(type) {
12 | case float64:
13 | if v.(float64) == 0 && !needZeroByInt {
14 | delete(res, k)
15 | }
16 | case int64:
17 | if v.(int64) == 0 && !needZeroByInt {
18 | delete(res, k)
19 | }
20 | case int:
21 | if v.(int) == 0 && !needZeroByInt {
22 | delete(res, k)
23 | }
24 | case string:
25 | if v.(string) == "" && !needZeroByString {
26 | delete(res, k)
27 | }
28 | }
29 | }
30 | return
31 | }
32 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/datatype.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import "sync"
4 |
5 | type Set struct {
6 | m map[interface{}]bool
7 | sync.RWMutex
8 | }
9 |
10 | func NewSet() *Set {
11 | return &Set{
12 | m: map[interface{}]bool{},
13 | }
14 | }
15 |
16 | func (s *Set) Add(item interface{}) {
17 | //写锁
18 | s.Lock()
19 | defer s.Unlock()
20 | s.m[item] = true
21 | }
22 |
23 | func (s *Set) Remove(item interface{}) {
24 | //写锁
25 | s.Lock()
26 | defer s.Unlock()
27 | delete(s.m, item)
28 | }
29 |
30 | func (s *Set) Has(item interface{}) bool {
31 | //允许读
32 | s.RLock()
33 | defer s.RUnlock()
34 | _, ok := s.m[item]
35 | return ok
36 | }
37 |
38 | func (s *Set) List() []interface{} {
39 | //允许读
40 | s.RLock()
41 | defer s.RUnlock()
42 | var outList []interface{}
43 | for value := range s.m {
44 | outList = append(outList, value)
45 | }
46 | return outList
47 | }
48 |
49 | func (s *Set) Len() int {
50 | return len(s.List())
51 | }
52 |
53 | func (s *Set) Clear() {
54 | s.Lock()
55 | defer s.Unlock()
56 | s.m = map[interface{}]bool{}
57 | }
58 |
59 | func (s *Set) IsEmpty() bool {
60 | if s.Len() == 0 {
61 | return true
62 | }
63 | return false
64 | }
65 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/dir.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "log"
5 | "os"
6 | "path/filepath"
7 | "strings"
8 | )
9 |
10 | func substr(s string, pos, length int) string {
11 | runes := []rune(s)
12 | l := pos + length
13 | if l > len(runes) {
14 | l = len(runes)
15 | }
16 | return string(runes[pos:l])
17 | }
18 |
19 | func GetParentDirectory(dirctory string) string {
20 | return substr(dirctory, 0, strings.LastIndex(dirctory, "/"))
21 | }
22 |
23 | func GetCurrentDirectory() string {
24 | dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
25 | if err != nil {
26 | log.Fatal(err)
27 | }
28 | return strings.Replace(dir, "\\", "/", -1)
29 | }
30 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/errors.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "database/sql"
5 | "strings"
6 |
7 | "github.com/garyburd/redigo/redis"
8 | )
9 |
10 | func FilterMysqlNilErr(err error) bool {
11 | if err != nil && err != sql.ErrNoRows {
12 | return true
13 | }
14 | return false
15 | }
16 |
17 | func IsMysqlRepeatError(err error) bool {
18 | if err != nil && strings.Contains(err.Error(), "Error 1062") {
19 | return true
20 | }
21 | return false
22 | }
23 |
24 | func FilterRedisNilErr(err error) bool {
25 | if err != nil && err != redis.ErrNil {
26 | return true
27 | }
28 | return false
29 | }
30 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/exec.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "log"
5 | "os/exec"
6 | "runtime"
7 | "syscall"
8 | )
9 |
10 | func OpenWinBrowser(uri string) error {
11 | switch runtime.GOOS {
12 | case "windows":
13 | cmd := exec.Command(`cmd`, `/c`, `start`, uri)
14 | cmd.SysProcAttr = &syscall.SysProcAttr{}
15 | err := cmd.Start()
16 | if err != nil {
17 | log.Println(err)
18 | return err
19 | }
20 | }
21 | return nil
22 | }
23 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/gzip.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "bytes"
5 | "compress/gzip"
6 | "io/ioutil"
7 | )
8 |
9 | func GzipCompressByte(data []byte) ([]byte, error) {
10 | buf := bytes.NewBuffer(nil)
11 | gzW := gzip.NewWriter(buf)
12 | _, err := gzW.Write(data)
13 | if err != nil {
14 | return nil, err
15 | }
16 | gzW.Close()
17 | return buf.Bytes(), err
18 | }
19 |
20 | func GzipCompress(data string) ([]byte, error) {
21 | buf := bytes.NewBuffer(nil)
22 | gzW := gzip.NewWriter(buf)
23 | _, err := gzW.Write(Str2bytes(data))
24 | if err != nil {
25 | return nil, err
26 | }
27 | gzW.Close()
28 | return buf.Bytes(), err
29 | }
30 |
31 | func GzipUnCompress(data []byte) (string, error) {
32 | gzR, err := gzip.NewReader(bytes.NewReader(data))
33 | if err != nil {
34 | return "", err
35 | }
36 | b, err := ioutil.ReadAll(gzR)
37 | return Bytes2str(b), err
38 | }
39 |
40 | func GzipUnCompressByte(data []byte) ([]byte, error) {
41 | gzR, err := gzip.NewReader(bytes.NewReader(data))
42 | if err != nil {
43 | return nil, err
44 | }
45 | b, err := ioutil.ReadAll(gzR)
46 | return b, err
47 | }
48 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/interface.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import "reflect"
4 |
5 | // interface{}转为 []interface{}
6 | func CreateAnyTypeSlice(slice interface{}) ([]interface{}, bool) {
7 | val, ok := isSlice(slice)
8 |
9 | if !ok {
10 | return nil, false
11 | }
12 |
13 | sliceLen := val.Len()
14 |
15 | out := make([]interface{}, sliceLen)
16 |
17 | for i := 0; i < sliceLen; i++ {
18 | out[i] = val.Index(i).Interface()
19 | }
20 |
21 | return out, true
22 | }
23 |
24 | // 判断是否为slcie数据
25 | func isSlice(arg interface{}) (val reflect.Value, ok bool) {
26 | val = reflect.ValueOf(arg)
27 |
28 | if val.Kind() == reflect.Slice {
29 | ok = true
30 | }
31 |
32 | return
33 | }
34 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/json.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | jsoniter "github.com/json-iterator/go"
5 | )
6 |
7 | func IsJson(str string) bool {
8 | maps := make(map[string]interface{})
9 | var json = jsoniter.ConfigCompatibleWithStandardLibrary
10 | err := json.Unmarshal(Str2bytes(str), &maps)
11 | if err != nil {
12 | return false
13 | }
14 | return true
15 | }
16 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/t_util.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "go.uber.org/zap"
5 | "time"
6 | )
7 |
8 | type Tutil struct {
9 | startT time.Time
10 | tag string
11 | logFloag bool
12 | logger *zap.Logger
13 | }
14 |
15 | func NewTutil(tagP string, logFloag bool, logger *zap.Logger) *Tutil {
16 | return &Tutil{startT: time.Now(), tag: tagP, logFloag: logFloag, logger: logger}
17 | }
18 |
19 | func (this *Tutil) EndT(tagC string, haveNext ...bool) {
20 | if len(haveNext) == 0 {
21 | this.startT = time.Now()
22 | } else {
23 | if this.logFloag {
24 | this.logger.Sugar().Infof("%s(%s):lost time:%v", this.tag, tagC, time.Now().Sub(this.startT).String())
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/time.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import "time"
4 |
5 | const (
6 | TimeFormat = "2006-01-02 15:04:05"
7 | TimeFormatDay = "20060102"
8 | TimeFormatDay2 = "2006-01-02"
9 | TimeFormatDay3 = "2006/01/02"
10 | TimeFormatDay4 = "2006.01.02_15"
11 | )
12 |
13 | /**
14 | * 二个时间戳是否同一天
15 | * @return true 是 false 不是今天
16 | */
17 | func IsSameDay(oldDay, anotherDay int64) bool {
18 | tm := time.Unix(oldDay, 0)
19 | tmAnother := time.Unix(anotherDay, 0)
20 | if tm.Format(TimeFormatDay2) == tmAnother.Format(TimeFormatDay2) {
21 | return true
22 | }
23 | return false
24 | }
25 |
26 | /**字符串->时间对象*/
27 | func Str2Time(formatTimeStr, timeFormat string) time.Time {
28 | loc, _ := time.LoadLocation("Local")
29 | theTime, _ := time.ParseInLocation(timeFormat, formatTimeStr, loc) //使用模板在对应时区转化为time.time类型
30 | return theTime
31 | }
32 |
--------------------------------------------------------------------------------
/platform-basic-libs/util/token.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "github.com/sony/sonyflake"
5 | "log"
6 | "strconv"
7 | "sync"
8 | )
9 |
10 | var TokenBucket sync.Map
11 |
12 | func GetUUid() string {
13 | flake := sonyflake.NewSonyflake(sonyflake.Settings{})
14 | id, err := flake.NextID()
15 | if err != nil {
16 | log.Println("err", err)
17 | }
18 | return strconv.Itoa(int(id))
19 | }
20 |
--------------------------------------------------------------------------------
/report_start.bat:
--------------------------------------------------------------------------------
1 | set dir = %cd%
2 |
3 | set args = "-configFileDir=%cd%\config"
4 |
5 | gowatch -p cmd/report_server/main.go -args=args -o bin/win/report_server.exe
--------------------------------------------------------------------------------
/router/app.go:
--------------------------------------------------------------------------------
1 | package router
2 |
3 | import (
4 | . "github.com/1340691923/xwl_bi/controller"
5 | "github.com/1340691923/xwl_bi/middleware"
6 | "github.com/1340691923/xwl_bi/platform-basic-libs/api_config"
7 | "github.com/gofiber/fiber/v2"
8 | )
9 |
10 | func runApp(app *fiber.App) {
11 | apiRouterConfig := api_config.NewApiRouterConfig()
12 | const AbsolutePath = "/api/app"
13 | appG := app.Group(AbsolutePath)
14 | {
15 | apiRouterConfig.MountApi(api_config.MountApiBasePramas{Remark: "查询应用列表", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), AppController{}.List)
16 |
17 | apiRouterConfig.MountApi(api_config.MountApiBasePramas{Remark: "获取应用下拉选", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), AppController{}.Config)
18 |
19 | appG = appG.Use(middleware.OperaterLog)
20 |
21 | apiRouterConfig.MountApi(api_config.MountApiBasePramas{Remark: "创建应用", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), AppController{}.Create)
22 |
23 | apiRouterConfig.MountApi(api_config.MountApiBasePramas{Remark: "重置秘钥", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), AppController{}.ResetAppkey)
24 |
25 | apiRouterConfig.MountApi(api_config.MountApiBasePramas{Remark: "修改应用成员", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), AppController{}.UpdateManager)
26 |
27 | apiRouterConfig.MountApi(api_config.MountApiBasePramas{Remark: "修改应用状态", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), AppController{}.StatusAction)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/router/index.go:
--------------------------------------------------------------------------------
1 | //路由层
2 | package router
3 |
4 | import (
5 | . "github.com/1340691923/xwl_bi/controller"
6 | . "github.com/1340691923/xwl_bi/middleware"
7 | "github.com/1340691923/xwl_bi/views"
8 | . "github.com/gofiber/fiber/v2"
9 | "github.com/gofiber/fiber/v2/middleware/compress"
10 | "github.com/gofiber/fiber/v2/middleware/cors"
11 | "github.com/gofiber/fiber/v2/middleware/filesystem"
12 | "github.com/gofiber/fiber/v2/middleware/pprof"
13 | jsoniter "github.com/json-iterator/go"
14 | )
15 |
16 | func Init() *App {
17 | var json = jsoniter.ConfigCompatibleWithStandardLibrary
18 | app := New(Config{
19 | AppName: "铸龙-BI",
20 | JSONDecoder: json.Unmarshal,
21 | JSONEncoder: json.Marshal,
22 | })
23 |
24 | app.Use(compress.New(compress.Config{
25 | Level: compress.LevelBestCompression,
26 | }))
27 |
28 | app.Use("/", filesystem.New(filesystem.Config{
29 | Root: views.GetFileSystem(),
30 | }))
31 |
32 | app.Use(
33 | cors.New(),
34 | pprof.New(),
35 | )
36 |
37 | app.Post("/api/gm_user/login", ManagerUserController{}.Login)
38 | routerWebsocket(app)
39 | app.Use(
40 | Timer,
41 | JwtMiddleware,
42 | Rbac,
43 | )
44 |
45 | return runRouterGroupFn(
46 | app,
47 | runOperaterLog,
48 | runGmUser,
49 | runRealData,
50 | runMetaData,
51 | runAnalysis,
52 | runPannel,
53 | runApp,
54 | runUserGroup,
55 | )
56 | }
57 |
58 | type routerGroupFn func(app *App)
59 |
60 | func runRouterGroupFn(app *App, fns ...routerGroupFn) *App {
61 | for _, fn := range fns {
62 | fn(app)
63 | }
64 | return app
65 | }
66 |
--------------------------------------------------------------------------------
/router/operater_log.go:
--------------------------------------------------------------------------------
1 | package router
2 |
3 | import (
4 | . "github.com/1340691923/xwl_bi/controller"
5 | "github.com/1340691923/xwl_bi/platform-basic-libs/api_config"
6 | "github.com/gofiber/fiber/v2"
7 | )
8 |
9 | func runOperaterLog(app *fiber.App) {
10 | apiRouterConfig := api_config.NewApiRouterConfig()
11 | const AbsolutePath = "/api/operater_log"
12 | appG := app.Group(AbsolutePath)
13 | {
14 | apiRouterConfig.MountApi(api_config.MountApiBasePramas{Remark: "查看后台操作日志", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), GmOperaterController{}.ListAction)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/router/user_group.go:
--------------------------------------------------------------------------------
1 | package router
2 |
3 | import (
4 | . "github.com/1340691923/xwl_bi/controller"
5 | "github.com/1340691923/xwl_bi/middleware"
6 | "github.com/1340691923/xwl_bi/platform-basic-libs/api_config"
7 | "github.com/gofiber/fiber/v2"
8 | )
9 |
10 | func runUserGroup(app *fiber.App) {
11 | c := api_config.NewApiRouterConfig()
12 | const AbsolutePath = "/api/user_group"
13 | appG := app.Group(AbsolutePath).Use(middleware.FilterAppid)
14 | {
15 |
16 | appG = appG.Use(middleware.OperaterLog)
17 |
18 | c.MountApi(api_config.MountApiBasePramas{Remark: "新增用户分群", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), UserGroupController{}.AddUserGroup)
19 |
20 | c.MountApi(api_config.MountApiBasePramas{Remark: "修改用户分群", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), UserGroupController{}.ModifyUserGroup)
21 |
22 | c.MountApi(api_config.MountApiBasePramas{Remark: "删除用户分群", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), UserGroupController{}.DeleteUserGroup)
23 |
24 | c.MountApi(api_config.MountApiBasePramas{Remark: "用户分群列表", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), UserGroupController{}.UserGroupList)
25 |
26 | c.MountApi(api_config.MountApiBasePramas{Remark: "用户分群下拉选", AbsolutePath: AbsolutePath}, appG.(*fiber.Group), UserGroupController{}.UserGroupSelect)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/router/ws.go:
--------------------------------------------------------------------------------
1 | package router
2 |
3 | import (
4 | . "github.com/1340691923/xwl_bi/controller"
5 | "github.com/gofiber/fiber/v2"
6 | "github.com/gofiber/websocket/v2"
7 | )
8 |
9 | func routerWebsocket(app *fiber.App) {
10 | app.Use("/ws", func(c *fiber.Ctx) error {
11 |
12 | if websocket.IsWebSocketUpgrade(c) {
13 | c.Locals("allowed", true)
14 | return c.Next()
15 | }
16 | return fiber.ErrUpgradeRequired
17 | })
18 |
19 | app.Get("/ws", websocket.New(DebugDataWs))
20 | }
21 |
--------------------------------------------------------------------------------
/sdk/cocos-creator/Hello.ts:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | import { _decorator, Component, Node } from 'cc';
4 | const { ccclass, property } = _decorator;
5 |
6 |
7 | @ccclass('Hello')
8 | export class Hello extends Component {
9 |
10 | start () {
11 |
12 | let parmas = {"appid":"389261007232434486","appkey":"a3f2b1db196e60f2f627358b429d52d7"}
13 |
14 | var foo = new report.EventReport("http://127.0.0.1:8091", parmas["appid"], parmas["appkey"], 0)
15 |
16 | foo.track("test",{})
17 |
18 | }
19 |
20 | }
21 | */
22 |
--------------------------------------------------------------------------------
/sdk/cocos-creator/report.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace report {
2 |
3 | export class EventReport {
4 |
5 | constructor(serverUrl: string, appid: string, appkey: string, debug: number);
6 |
7 | public identify(uuid :string): void;
8 |
9 | public login(uid :string): void;
10 |
11 | public logout(): void;
12 |
13 | public getDistinctId():string;
14 |
15 | public track(eventName :string,properties :any): void;
16 |
17 | public userSet(properties :any):EventReport;
18 |
19 | public userUnset(key :string):void;
20 |
21 | public userAdd(properties :any):void;
22 |
23 | public userSetOnce(properties :any):void;
24 |
25 | public getSuperProperties():any;
26 |
27 | public getUserProperties():any;
28 |
29 | public setSuperProperties(properties :any):void;
30 |
31 | public unsetSuperProperties(key :string):void;
32 |
33 | public clearSuperProperties():void;
34 |
35 | public getUserProperties():any;
36 |
37 | public trackUserData():void;
38 |
39 | }
40 | }
--------------------------------------------------------------------------------
/sdk/egert/report.d.ts:
--------------------------------------------------------------------------------
1 | declare class EventReport {
2 |
3 | constructor(serverUrl: string, appid: string, appkey: string, debug: number);
4 |
5 | public identify(uuid :string): void;
6 |
7 | public login(uid :string): void;
8 |
9 | public logout(): void;
10 |
11 | public track(eventName :string,properties :any): void;
12 |
13 | public userSet(properties :any):EventReport;
14 |
15 | public userUnset(key :string):void;
16 |
17 | public getDistinctId():string;
18 |
19 | public userAdd(properties :any):void;
20 |
21 | public userSetOnce(properties :any):void;
22 |
23 | public getSuperProperties():any;
24 |
25 | public getUserProperties():any;
26 |
27 | public setSuperProperties(properties :any):void;
28 |
29 | public unsetSuperProperties(key :string):void;
30 |
31 | public clearSuperProperties():void;
32 |
33 | public getUserProperties():any;
34 |
35 | public trackUserData():void;
36 | }
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/sinker_start.bat:
--------------------------------------------------------------------------------
1 | set dir = %cd%
2 |
3 | set args = "-configFileDir=%cd%\config"
4 |
5 | gowatch -p cmd/sinker/main.go -args=args -o bin/win/sinker.exe
--------------------------------------------------------------------------------
/views/fs.go:
--------------------------------------------------------------------------------
1 | package views
2 |
3 | import (
4 | "embed"
5 | "io/fs"
6 | "net/http"
7 | )
8 |
9 | //go:embed dist
10 | var StatisFs embed.FS
11 |
12 | func GetFileSystem() http.FileSystem {
13 | fsys, err := fs.Sub(StatisFs, "dist")
14 | if err != nil {
15 | panic(err)
16 | }
17 | return http.FS(fsys)
18 | }
19 |
--------------------------------------------------------------------------------
/vue/.editorconfig:
--------------------------------------------------------------------------------
1 | # https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | insert_final_newline = false
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/vue/.env.development:
--------------------------------------------------------------------------------
1 | # just a flag
2 | ENV = 'development'
3 |
4 | # base api
5 | # 开发环境
6 | VUE_APP_BASE_API = 'http://localhost:8090/'
7 | VUE_APP_BASE_TITLE = '铸龙-埋点数据分析平台(开发)'
8 | # vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
9 | # to control whether the babel-plugin-dynamic-import-node plugin is enabled.
10 | # It only does one thing by converting all import() to require().
11 | # This configuration can significantly increase the speed of hot updates,
12 | # when you have a large number of pages.
13 | # Detail: https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
14 |
15 | VUE_CLI_BABEL_TRANSPILE_MODULES = true
16 |
17 |
--------------------------------------------------------------------------------
/vue/.env.production:
--------------------------------------------------------------------------------
1 | NODE_ENV = production
2 |
3 | # just a flag
4 | ENV = 'staging'
5 |
6 | # base api
7 | # 生产环境
8 | VUE_APP_BASE_API = ''
9 | VUE_APP_BASE_TITLE = '铸龙-埋点数据分析平台'
10 |
--------------------------------------------------------------------------------
/vue/.env.staging:
--------------------------------------------------------------------------------
1 | NODE_ENV = production
2 |
3 | # just a flag
4 | ENV = 'staging'
5 |
6 | # base api
7 | # 测试环境
8 | VUE_APP_BASE_API = ''
9 | VUE_APP_BASE_TITLE = '铸龙-埋点数据分析平台(测试)'
10 |
11 |
--------------------------------------------------------------------------------
/vue/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*.js
2 | src/assets
3 | public
4 | dist
5 |
--------------------------------------------------------------------------------
/vue/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js: 10
3 | script: npm run test
4 | notifications:
5 | email: false
6 |
--------------------------------------------------------------------------------
/vue/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017-present PanJiaChen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/vue/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/vue/build/index.js:
--------------------------------------------------------------------------------
1 | const { run } = require('runjs')
2 | const chalk = require('chalk')
3 | const config = require('../vue.config.js')
4 | const rawArgv = process.argv.slice(2)
5 | const args = rawArgv.join(' ')
6 |
7 | if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
8 | const report = rawArgv.includes('--report')
9 |
10 | run(`vue-cli-service build ${args}`)
11 |
12 | const port = 9526
13 | const publicPath = config.publicPath
14 |
15 | var connect = require('connect')
16 | var serveStatic = require('serve-static')
17 | const app = connect()
18 |
19 | app.use(
20 | publicPath,
21 | serveStatic('./dist', {
22 | index: ['index.html', '/']
23 | })
24 | )
25 |
26 | app.listen(port, function () {
27 | console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
28 | if (report) {
29 | console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
30 | }
31 |
32 | })
33 | } else {
34 | run(`vue-cli-service build ${args}`)
35 | }
36 |
--------------------------------------------------------------------------------
/vue/debug.log:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/1340691923/xwl_bi/9337120b09f855a22c4c5a4e78b84436ef37dc30/vue/debug.log
--------------------------------------------------------------------------------
/vue/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
3 | transform: {
4 | '^.+\\.vue$': 'vue-jest',
5 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
6 | 'jest-transform-stub',
7 | '^.+\\.jsx?$': 'babel-jest'
8 | },
9 | moduleNameMapper: {
10 | '^@/(.*)$': '/src/$1'
11 | },
12 | snapshotSerializers: ['jest-serializer-vue'],
13 | testMatch: [
14 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
15 | ],
16 | collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
17 | coverageDirectory: '/tests/unit/coverage',
18 | // 'collectCoverage': true,
19 | 'coverageReporters': [
20 | 'lcov',
21 | 'text-summary'
22 | ],
23 | testURL: 'http://localhost/'
24 | }
25 |
--------------------------------------------------------------------------------
/vue/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./",
4 | "paths": {
5 | "@/*": ["src/*"]
6 | }
7 | },
8 | "exclude": ["node_modules", "dist"]
9 | }
--------------------------------------------------------------------------------
/vue/mock/remote-search.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 |
3 | const NameList = []
4 | const count = 100
5 |
6 | for (let i = 0; i < count; i++) {
7 | NameList.push(Mock.mock({
8 | name: '@first'
9 | }))
10 | }
11 | NameList.push({ name: 'mock-Pan' })
12 |
13 | export default [
14 | // username search
15 | {
16 | url: '/search/user',
17 | type: 'get',
18 | response: config => {
19 | const { name } = config.query
20 | const mockNameList = NameList.filter(item => {
21 | const lowerCaseName = item.name.toLowerCase()
22 | return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0)
23 | })
24 | return {
25 | code: 20000,
26 | data: { items: mockNameList }
27 | }
28 | }
29 | },
30 |
31 | // transaction list
32 | {
33 | url: '/transaction/list',
34 | type: 'get',
35 | response: _ => {
36 | return {
37 | code: 20000,
38 | data: {
39 | total: 20,
40 | 'items|20': [{
41 | order_no: '@guid()',
42 | timestamp: +Mock.Random.date('T'),
43 | username: '@name()',
44 | price: '@float(1000, 15000, 0, 2)',
45 | 'status|1': ['success', 'pending']
46 | }]
47 | }
48 | }
49 | }
50 | }
51 | ]
52 |
--------------------------------------------------------------------------------
/vue/plop-templates/component/index.hbs:
--------------------------------------------------------------------------------
1 | {{#if template}}
2 |
3 |
4 |
5 | {{/if}}
6 |
7 | {{#if script}}
8 |
20 | {{/if}}
21 |
22 | {{#if style}}
23 |
26 | {{/if}}
27 |
--------------------------------------------------------------------------------
/vue/plop-templates/component/prompt.js:
--------------------------------------------------------------------------------
1 | const { notEmpty } = require('../utils.js')
2 |
3 | module.exports = {
4 | description: 'generate vue component',
5 | prompts: [{
6 | type: 'input',
7 | name: 'name',
8 | message: 'component name please',
9 | validate: notEmpty('name')
10 | },
11 | {
12 | type: 'checkbox',
13 | name: 'blocks',
14 | message: 'Blocks:',
15 | choices: [{
16 | name: '',
17 | value: 'template',
18 | checked: true
19 | },
20 | {
21 | name: '
20 | {{/if}}
21 |
22 | {{#if style}}
23 |
26 | {{/if}}
27 |
--------------------------------------------------------------------------------
/vue/plop-templates/view/prompt.js:
--------------------------------------------------------------------------------
1 | const { notEmpty } = require('../utils.js')
2 |
3 | module.exports = {
4 | description: 'generate a view',
5 | prompts: [{
6 | type: 'input',
7 | name: 'name',
8 | message: 'view name please',
9 | validate: notEmpty('name')
10 | },
11 | {
12 | type: 'checkbox',
13 | name: 'blocks',
14 | message: 'Blocks:',
15 | choices: [{
16 | name: '',
17 | value: 'template',
18 | checked: true
19 | },
20 | {
21 | name: '
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | <%= webpackConfig.name %>
28 |
29 |
30 |
31 |
32 |
33 |