├── Makefile
├── .github
└── .gitkeep
├── docker
└── .gitkeep
├── scripts
└── .gitkeep
├── li-app
├── resource
│ ├── template
│ │ └── .gitkeep
│ └── public
│ │ └── locales
│ │ ├── zh-CN.json
│ │ └── en-US.json
├── internal
│ ├── app
│ │ └── admin
│ │ │ ├── service
│ │ │ └── .gitkeep
│ │ │ ├── consts
│ │ │ └── view.go
│ │ │ ├── dto
│ │ │ └── user.go
│ │ │ ├── view
│ │ │ ├── blog.tag.go
│ │ │ ├── blog.post.go
│ │ │ ├── system.user.go
│ │ │ ├── blog.comment.go
│ │ │ ├── app.sign.go
│ │ │ ├── dashboard.workplace.go
│ │ │ └── app.nav.go
│ │ │ ├── controller
│ │ │ └── user.go
│ │ │ └── admin.go
│ ├── data
│ │ ├── data.go
│ │ ├── ent
│ │ │ ├── generate.go
│ │ │ ├── schema
│ │ │ │ ├── role.go
│ │ │ │ └── tag.go
│ │ │ └── entc.go
│ │ ├── user.go
│ │ └── hook
│ │ │ └── user.go
│ ├── pkg
│ │ └── wf
│ │ │ ├── executor
│ │ │ └── approval_task.go
│ │ │ └── wf.go
│ ├── shared
│ │ ├── shared.go
│ │ └── context.go
│ ├── middleware
│ │ ├── cors.go
│ │ ├── err.go
│ │ ├── auth.go
│ │ └── ctx.go
│ └── cmd
│ │ ├── cmd_migrate.go
│ │ ├── cmd_user.go
│ │ ├── cmd_run.go
│ │ └── cmd.go
├── docker
│ └── docker-compose.yaml
├── li.go
├── Makefile
├── script
│ └── entclean.sh
├── go.mod
└── config
│ └── config.dev.yaml
├── li-engine
├── view
│ ├── mixin
│ │ └── .gitkeep
│ ├── node
│ │ ├── node_calendar.go
│ │ ├── node_cascader.go
│ │ ├── node_code.go
│ │ ├── node_image.go
│ │ ├── node_markdown.go
│ │ ├── node_richtext.go
│ │ ├── node_table.go
│ │ ├── node_treeselect.go
│ │ ├── node_phone.go
│ │ ├── node_chart.go
│ │ ├── node_email.go
│ │ ├── node_form.go
│ │ ├── node_actionformmodalcancel.go
│ │ ├── node_actionformdrawercancel.go
│ │ ├── node_dropdownmenuitem.go
│ │ ├── node_arrayitemsindex.go
│ │ ├── node_arraytableindex.go
│ │ ├── node_arrayitemsremove.go
│ │ ├── node_arrayitemsmoveup.go
│ │ ├── node_arraytablemoveup.go
│ │ ├── node_arraytableremove.go
│ │ ├── node_dropdownmenusubmenu.go
│ │ ├── node_arrayitemsmovedown.go
│ │ ├── node_arraytablemovedown.go
│ │ ├── node_arrayitemssorthandle.go
│ │ ├── node_arraytablesorthandle.go
│ │ ├── node_tabstabpane.go
│ │ ├── node_listaction.go
│ │ ├── node_dropdownmenuurl.go
│ │ ├── node_listcard.go
│ │ ├── node_checkbox.go
│ │ ├── node_colorselect.go
│ │ ├── node_divider.go
│ │ ├── node_gridcol.go
│ │ ├── node_listactionsearch.go
│ │ ├── node_percent.go
│ │ ├── node_gridrow.go
│ │ ├── node_actionformmodalsubmit.go
│ │ ├── node_avatar.go
│ │ ├── node_actionformdrawersubmit.go
│ │ ├── node_arrayitems.go
│ │ ├── node_rate.go
│ │ ├── node_money.go
│ │ ├── node_password.go
│ │ ├── node_uploadavatar.go
│ │ ├── node_dropdownmenu.go
│ │ ├── node_space.go
│ │ └── node_checkboxgroup.go
│ └── com
│ │ ├── com_langswitch.go
│ │ └── com_themeswitch.go
├── contrib
│ ├── lient
│ │ ├── internal
│ │ │ ├── main.go
│ │ │ └── ent
│ │ │ │ ├── generate.go
│ │ │ │ ├── entc.go
│ │ │ │ └── schema
│ │ │ │ └── tag.go
│ │ ├── extension.go
│ │ ├── util.go
│ │ ├── template
│ │ │ ├── import.tmpl
│ │ │ └── db.tmpl
│ │ ├── sqlx
│ │ │ ├── utils.go
│ │ │ └── sqlx.go
│ │ ├── template.go
│ │ ├── mixin
│ │ │ ├── id_mixin.go
│ │ │ └── time_mixin.go
│ │ └── driver
│ │ │ └── helper.go
│ ├── liflow
│ │ ├── ent
│ │ │ ├── generate.go
│ │ │ ├── runtime
│ │ │ │ └── runtime.go
│ │ │ ├── entc.go
│ │ │ ├── predicate
│ │ │ │ └── predicate.go
│ │ │ ├── context.go
│ │ │ ├── db.go
│ │ │ ├── schema
│ │ │ │ ├── flow_instance_data.go
│ │ │ │ ├── flow_node_instance_log.go
│ │ │ │ ├── flow_instance.go
│ │ │ │ ├── flow_deployment.go
│ │ │ │ ├── flow_definition.go
│ │ │ │ ├── flow_node_instance.go
│ │ │ │ └── flow_instance_comment.go
│ │ │ └── config.go
│ │ ├── executor
│ │ │ ├── sequence_flow.go
│ │ │ ├── exclusive_gateway.go
│ │ │ ├── start_event.go
│ │ │ └── end_event.go
│ │ ├── liflow_test.go
│ │ ├── liflow.go
│ │ ├── processor
│ │ │ ├── processor.go
│ │ │ └── terminate_process.go
│ │ └── enthook.go
│ └── lifile
│ │ └── lifile.go
├── go.mod
├── controller
│ ├── internal
│ │ └── reflection
│ │ │ └── reflection.go
│ ├── file_preview.go
│ └── file_upload.go
└── service
│ └── file.go
├── li-web
├── README.md
├── packages
│ ├── pro-components
│ │ ├── src
│ │ │ ├── li-flow
│ │ │ │ ├── index.less
│ │ │ │ ├── nodes
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── SequenceFlow.ts
│ │ │ │ │ └── ExclusiveGateway.ts
│ │ │ │ └── components
│ │ │ │ │ └── NodePanel
│ │ │ │ │ └── index.tsx
│ │ │ ├── index.ts
│ │ │ ├── li-editor
│ │ │ │ └── index.tsx
│ │ │ ├── docs
│ │ │ │ ├── li-editor.md
│ │ │ │ └── li-flow.md
│ │ │ └── locale
│ │ │ │ ├── index.ts
│ │ │ │ ├── types.ts
│ │ │ │ ├── zh-CN.ts
│ │ │ │ └── en-US.ts
│ │ ├── .eslintrc.js
│ │ ├── tsconfig.json
│ │ ├── .umirc.ts
│ │ └── package.json
│ ├── pro-utils
│ │ ├── src
│ │ │ ├── nanoid
│ │ │ │ └── index.ts
│ │ │ └── index.ts
│ │ ├── .eslintrc.js
│ │ ├── tsconfig.json
│ │ └── package.json
│ ├── schema-components
│ │ ├── src
│ │ │ ├── components
│ │ │ │ ├── list
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── List.Card.tsx
│ │ │ │ │ └── context.ts
│ │ │ │ ├── action
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── Action.Modal.tsx
│ │ │ │ │ ├── Action.tsx
│ │ │ │ │ └── types.ts
│ │ │ │ ├── chart
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── context.ts
│ │ │ │ │ ├── utils.ts
│ │ │ │ │ ├── Chart.tsx
│ │ │ │ │ └── index.less
│ │ │ │ ├── input-number
│ │ │ │ │ ├── utils
│ │ │ │ │ │ └── supportUtil.ts
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── __builtins__
│ │ │ │ │ ├── hooks
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── getPrefixCls.ts
│ │ │ │ │ │ ├── getLocale.ts
│ │ │ │ │ │ ├── usePrefixCls.ts
│ │ │ │ │ │ └── useCollapseGrid.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── utils.ts
│ │ │ │ │ ├── pickDataProps.ts
│ │ │ │ │ ├── loading.ts
│ │ │ │ │ └── icon.tsx
│ │ │ │ ├── form-grid
│ │ │ │ │ └── index.less
│ │ │ │ ├── text-editor
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── input
│ │ │ │ │ └── index.less
│ │ │ │ ├── switch
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── card-item
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── divider
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── form-button-group
│ │ │ │ │ └── index.less
│ │ │ │ ├── grid
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── upload
│ │ │ │ │ └── types.ts
│ │ │ │ ├── avatar
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── select
│ │ │ │ │ └── shared.ts
│ │ │ │ ├── array-base
│ │ │ │ │ └── index.less
│ │ │ │ ├── space
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── time-picker
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── radio
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── array-table
│ │ │ │ │ └── index.less
│ │ │ │ ├── reset
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── tabs
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── date-picker
│ │ │ │ │ └── index.tsx
│ │ │ │ └── array-items
│ │ │ │ │ └── index.less
│ │ │ ├── locale
│ │ │ │ ├── index.ts
│ │ │ │ ├── types.ts
│ │ │ │ ├── zh-CN.tsx
│ │ │ │ └── en-US.tsx
│ │ │ ├── index.ts
│ │ │ ├── hooks
│ │ │ │ ├── index.ts
│ │ │ │ ├── useSchemaComponentContext.ts
│ │ │ │ ├── useComponent.ts
│ │ │ │ ├── useCompile.ts
│ │ │ │ ├── useAttach.ts
│ │ │ │ └── useFieldProps.ts
│ │ │ ├── context.ts
│ │ │ ├── core
│ │ │ │ ├── index.ts
│ │ │ │ ├── RecordProvider.tsx
│ │ │ │ ├── SchemaComponentOptions.tsx
│ │ │ │ ├── SchemaFormField.tsx
│ │ │ │ └── SchemaComponent.tsx
│ │ │ └── types.ts
│ │ ├── .eslintrc.js
│ │ ├── tsconfig.json
│ │ ├── .umirc.ts
│ │ └── package.json
│ ├── tsconfig
│ │ ├── package.json
│ │ ├── react-library.json
│ │ └── base.json
│ └── config
│ │ ├── eslint-preset.js
│ │ └── package.json
├── .npmrc
├── apps
│ └── admin
│ │ ├── src
│ │ ├── vite-env.d.ts
│ │ ├── modules
│ │ │ ├── components
│ │ │ │ ├── index.ts
│ │ │ │ └── Loading.tsx
│ │ │ ├── schema-components
│ │ │ │ ├── index.ts
│ │ │ │ ├── theme-switch
│ │ │ │ │ └── index.tsx
│ │ │ │ └── lang-switch
│ │ │ │ │ └── index.tsx
│ │ │ ├── route-switch
│ │ │ │ ├── index.ts
│ │ │ │ ├── context.ts
│ │ │ │ ├── RouteSwitchProvider.tsx
│ │ │ │ ├── types.ts
│ │ │ │ ├── hooks.ts
│ │ │ │ └── RouteSwitch.tsx
│ │ │ ├── index.ts
│ │ │ ├── application
│ │ │ │ └── index.tsx
│ │ │ ├── record-provider
│ │ │ │ └── index.tsx
│ │ │ ├── async-data-provider
│ │ │ │ └── index.tsx
│ │ │ ├── i18n
│ │ │ │ └── index.ts
│ │ │ ├── document-title
│ │ │ │ └── index.tsx
│ │ │ └── sign-page
│ │ │ │ └── index.tsx
│ │ ├── context.ts
│ │ ├── assets
│ │ │ ├── dark.svg
│ │ │ └── logo.svg
│ │ └── style
│ │ │ └── global.less
│ │ ├── .eslintrc.js
│ │ ├── tsconfig.json
│ │ ├── mock
│ │ ├── getCurrentUser.ts
│ │ ├── getUv.ts
│ │ └── listUser.ts
│ │ ├── index.html
│ │ ├── config
│ │ └── proxy.ts
│ │ └── vite.config.ts
├── pnpm-workspace.yaml
├── Makefile
├── turbo.json
├── .editorconfig
├── .prettierignore
├── .gitignore
└── package.json
├── go.mod
├── docs
└── assets
│ ├── li1.png
│ └── li2.png
├── .gitignore
└── README.md
/Makefile:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docker/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/scripts/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/li-app/resource/template/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/li-engine/view/mixin/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/li-web/README.md:
--------------------------------------------------------------------------------
1 | # li-web
2 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/service/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/li-app/internal/data/data.go:
--------------------------------------------------------------------------------
1 | package data
2 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/BeanWei/li
2 |
3 | go 1.16
--------------------------------------------------------------------------------
/li-app/docker/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_calendar.go:
--------------------------------------------------------------------------------
1 | package node
2 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_cascader.go:
--------------------------------------------------------------------------------
1 | package node
2 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_code.go:
--------------------------------------------------------------------------------
1 | package node
2 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_image.go:
--------------------------------------------------------------------------------
1 | package node
2 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_markdown.go:
--------------------------------------------------------------------------------
1 | package node
2 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_richtext.go:
--------------------------------------------------------------------------------
1 | package node
2 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_table.go:
--------------------------------------------------------------------------------
1 | package node
2 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/li-flow/index.less:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/internal/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_treeselect.go:
--------------------------------------------------------------------------------
1 | package node
2 |
--------------------------------------------------------------------------------
/li-web/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npmmirror.com
2 |
--------------------------------------------------------------------------------
/li-web/packages/pro-utils/src/nanoid/index.ts:
--------------------------------------------------------------------------------
1 | export * from "nanoid";
2 |
--------------------------------------------------------------------------------
/li-app/resource/public/locales/zh-CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "Li Admin": "❤️璃❤️"
3 | }
--------------------------------------------------------------------------------
/li-web/apps/admin/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/li-web/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - "apps/*"
3 | - "packages/*"
4 |
--------------------------------------------------------------------------------
/li-web/apps/admin/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require("eslint-preset-acme");
2 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./Loading";
2 |
--------------------------------------------------------------------------------
/docs/assets/li1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BeanWei/li/HEAD/docs/assets/li1.png
--------------------------------------------------------------------------------
/docs/assets/li2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BeanWei/li/HEAD/docs/assets/li2.png
--------------------------------------------------------------------------------
/li-web/packages/pro-utils/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require("eslint-preset-acme");
2 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/list/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./List";
2 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require("eslint-preset-acme");
2 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require("eslint-preset-acme");
2 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/action/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./Action";
2 |
--------------------------------------------------------------------------------
/li-app/internal/data/ent/generate.go:
--------------------------------------------------------------------------------
1 | package ent
2 |
3 | //go:generate go run -mod=mod entc.go
4 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/generate.go:
--------------------------------------------------------------------------------
1 | package ent
2 |
3 | //go:generate go run -mod=mod entc.go
4 |
--------------------------------------------------------------------------------
/li-web/packages/pro-utils/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./request";
2 | export * from "./nanoid";
3 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/consts/view.go:
--------------------------------------------------------------------------------
1 | package consts
2 |
3 | const (
4 | AppEntry = "/admin"
5 | )
6 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./li-editor";
2 | export * from "./li-flow";
3 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/internal/ent/generate.go:
--------------------------------------------------------------------------------
1 | package ent
2 |
3 | //go:generate go run -mod=mod entc.go
4 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/locale/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./zh-CN";
2 | export * from "./en-US";
3 |
--------------------------------------------------------------------------------
/li-app/resource/public/locales/en-US.json:
--------------------------------------------------------------------------------
1 | {
2 | "登录": "Login",
3 | "邮箱": "Email",
4 | "密码": "Password"
5 | }
6 |
--------------------------------------------------------------------------------
/li-app/internal/data/ent/schema/role.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | const (
4 | RoleSystemManager = "SystemManager"
5 | )
6 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/schema-components/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./lang-switch";
2 | export * from "./theme-switch";
3 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/chart/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./ChartItem";
2 | export * from "./Chart";
3 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/executor/sequence_flow.go:
--------------------------------------------------------------------------------
1 | package executor
2 |
3 | type SequenceFlowExecutor struct {
4 | ElementExecutor
5 | }
6 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/liflow_test.go:
--------------------------------------------------------------------------------
1 | package liflow
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func Test_LiFlow(t *testing.T) {
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/li-web/apps/admin/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tsconfig/react-library.json",
3 | "exclude": ["dist", "build", "node_modules"],
4 | "include": ["src"]
5 | }
6 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/input-number/utils/supportUtil.ts:
--------------------------------------------------------------------------------
1 | export function supportBigInt() {
2 | return typeof BigInt === "function";
3 | }
4 |
--------------------------------------------------------------------------------
/li-web/packages/pro-utils/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tsconfig/react-library.json",
3 | "include": ["."],
4 | "exclude": ["dist", "build", "node_modules"]
5 | }
6 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tsconfig/react-library.json",
3 | "include": ["."],
4 | "exclude": ["dist", "build", "node_modules"]
5 | }
6 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tsconfig/react-library.json",
3 | "include": ["."],
4 | "exclude": ["dist", "build", "node_modules"]
5 | }
6 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./components";
2 | export * from "./context";
3 | export * from "./core";
4 | export * from "./types";
5 | export * from "./locale";
6 |
--------------------------------------------------------------------------------
/li-app/li.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/cmd"
5 | "github.com/gogf/gf/v2/os/gctx"
6 | )
7 |
8 | func main() {
9 | cmd.Li.Run(gctx.New())
10 | }
11 |
--------------------------------------------------------------------------------
/li-app/Makefile:
--------------------------------------------------------------------------------
1 | generate:
2 | go generate ./...
3 |
4 | migrate:
5 | go run li.go migrate
6 |
7 | entclean:
8 | bash ./script/entclean.sh
9 |
10 | run:
11 | go run li.go run --gf.gmode=develop
12 |
--------------------------------------------------------------------------------
/li-web/apps/admin/mock/getCurrentUser.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | nickname: "阿璃",
3 | avatar:
4 | "https://lf1-xgcdn-tos.pstatp.com/obj/vcloud/vadmin/start.8e0e4855ee346a46ccff8ff3e24db27b.png",
5 | };
6 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/li-editor/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export const LiEditor: React.FC = () => {
4 | return
LiEditor
;
5 | };
6 |
7 | export default LiEditor;
8 |
--------------------------------------------------------------------------------
/li-app/internal/pkg/wf/executor/approval_task.go:
--------------------------------------------------------------------------------
1 | package executor
2 |
3 | import "github.com/BeanWei/li/li-engine/contrib/liflow/executor"
4 |
5 | type ApprovalTask struct {
6 | executor.UserTaskExecutor
7 | }
8 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/route-switch/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./context";
2 | export * from "./hooks";
3 | export * from "./RouteSwitch";
4 | export * from "./RouteSwitchProvider";
5 | export * from "./types";
6 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/action/Action.Modal.tsx:
--------------------------------------------------------------------------------
1 | import { Fragment } from "react";
2 |
3 | export const ActionModal = () => {
4 | return ;
5 | };
6 |
7 | export default ActionModal;
8 |
--------------------------------------------------------------------------------
/li-web/Makefile:
--------------------------------------------------------------------------------
1 | clean:
2 | rm -rf node_modules
3 | rm -rf apps/admin/node_modules
4 | rm -rf packages/pro-components/node_modules
5 | rm -rf packages/pro-utils/node_modules
6 | rm -rf packages/schema-components/node_modules
7 |
--------------------------------------------------------------------------------
/li-web/packages/tsconfig/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tsconfig",
3 | "version": "0.0.0",
4 | "private": true,
5 | "main": "index.js",
6 | "files": [
7 | "base.json",
8 | "react-library.json"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./useAttach";
2 | export * from "./useCompile";
3 | export * from "./useComponent";
4 | export * from "./useFieldProps";
5 | export * from "./useSchemaComponentContext";
6 |
--------------------------------------------------------------------------------
/li-app/internal/shared/shared.go:
--------------------------------------------------------------------------------
1 | package shared
2 |
3 | import "github.com/gogf/gf/v2/container/garray"
4 |
5 | // CtxUser 上下文用户信息
6 | type CtxUser struct {
7 | ID string
8 | IsAdmin bool
9 | Roles *garray.StrArray
10 | }
11 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/docs/li-editor.md:
--------------------------------------------------------------------------------
1 | # LiEditor
2 |
3 | ```tsx
4 | import React from "react";
5 | import { LiEditor } from "pro-components";
6 |
7 | export default () => {
8 | return ;
9 | };
10 | ```
11 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from "react";
2 | import { ISchemaComponentContext } from "./types";
3 |
4 | export const SchemaComponentContext = createContext(
5 | {}
6 | );
7 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/__builtins__/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./getLocale";
2 | export * from "./getPrefixCls";
3 | export * from "./useClickAway";
4 | export * from "./useCollapseGrid";
5 | export * from "./usePrefixCls";
6 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/__builtins__/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./hooks";
2 | export * from "./icon";
3 | export * from "./portal";
4 | export * from "./loading";
5 | export * from "./pickDataProps";
6 | export * from "./utils";
7 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/form-grid/index.less:
--------------------------------------------------------------------------------
1 | @import '~@arco-design/web-react/lib/style/theme/default.less';
2 |
3 | @form-grid-prefix-cls: ~'@{prefix}-formily-grid';
4 |
5 | .@{form-grid-prefix-cls}-layout {
6 | display: grid;
7 | }
8 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/.umirc.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | chainWebpack: (memo, { env, webpack, createCSSRule }) => {
3 | memo.module
4 | .rule("ts-in-node_modules")
5 | .include.add(require("path").join(__dirname, "../../packages/"));
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/.umirc.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | chainWebpack: (memo, { env, webpack, createCSSRule }) => {
3 | memo.module
4 | .rule("ts-in-node_modules")
5 | .include.add(require("path").join(__dirname, "../../packages/"));
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/text-editor/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { LiEditor } from "pro-components";
3 |
4 | export const TextEditor: React.FC<{}> = (props) => {
5 | return ;
6 | };
7 |
8 | export default TextEditor;
9 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/hooks/useSchemaComponentContext.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { SchemaComponentContext } from "../context";
3 |
4 | export function useSchemaComponentContext() {
5 | return useContext(SchemaComponentContext);
6 | }
7 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/dto/user.go:
--------------------------------------------------------------------------------
1 | package dto
2 |
3 | type UserSignInReq struct {
4 | Email string `v:"required|email"`
5 | Password string `v:"required"`
6 | }
7 |
8 | type UserSignInRes struct {
9 | ID string `json:"id"`
10 | Sid string `json:"sid"`
11 | }
12 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/input/index.less:
--------------------------------------------------------------------------------
1 | @import '~@arco-design/web-react/lib/style/theme/default.less';
2 |
3 | @description-cls: ~'@{prefix}-description';
4 |
5 | .@{description-cls}-textarea
6 | .@{description-cls}-input{
7 | line-height: 1.612;
8 | }
9 |
--------------------------------------------------------------------------------
/li-web/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "pipeline": {
3 | "build": {
4 | "dependsOn": ["^build"],
5 | "outputs": ["dist/**", ".next/**"]
6 | },
7 | "lint": {
8 | "outputs": []
9 | },
10 | "dev": {
11 | "cache": false
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/li-app/script/entclean.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | git ls-files --others --ignored --exclude-standard | awk '{print}' |
4 | while read -r line
5 | do
6 | if [[ $line == *"/ent/"* ]]; then
7 | echo "Delete: $line"
8 | rm $line
9 | fi
10 | done
11 |
12 |
13 |
--------------------------------------------------------------------------------
/li-web/packages/config/eslint-preset.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["prettier"],
4 | settings: {
5 | next: {
6 | rootDir: ["apps/*/", "packages/*/"],
7 | },
8 | },
9 | rules: {
10 | "react/jsx-key": "off",
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/docs/li-flow.md:
--------------------------------------------------------------------------------
1 | # LiFlow
2 |
3 | ```tsx
4 | import React from "react";
5 | import { LiFlow } from "pro-components";
6 | import "@arco-design/web-react/dist/css/arco.css";
7 |
8 | export default () => {
9 | return ;
10 | };
11 | ```
12 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/route-switch/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from "react";
2 | import { RouteProps } from "./types";
3 |
4 | export const RouteSwitchContext = createContext({
5 | components: {},
6 | });
7 |
8 | export const RouteContext = createContext({ path: "/" });
9 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/list/List.Card.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from "@arco-design/web-react";
2 | import React from "react";
3 |
4 | const ListCard: React.FC> = (props) => {
5 | return {props.children};
6 | };
7 |
8 | export default ListCard;
9 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/core/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./RecordProvider";
2 | export * from "./SchemaComponent";
3 | export * from "./SchemaComponentOptions";
4 | export * from "./SchemaComponentProvider";
5 | export * from "./SchemaFormField";
6 | export * from "./UiSchemaComponentProvider";
7 |
--------------------------------------------------------------------------------
/li-web/apps/admin/mock/getUv.ts:
--------------------------------------------------------------------------------
1 | export default [
2 | { ds: "2020-12-31", uv: 20 },
3 | { ds: "2021-01-01", uv: 21 },
4 | { ds: "2021-01-02", uv: 15 },
5 | { ds: "2021-01-03", uv: 40 },
6 | { ds: "2021-01-04", uv: 31 },
7 | { ds: "2021-01-05", uv: 32 },
8 | { ds: "2021-01-06", uv: 30 },
9 | ];
10 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/__builtins__/hooks/getPrefixCls.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { ConfigProvider } from "@arco-design/web-react";
3 |
4 | export const getPrefixCls = () => {
5 | const { prefixCls } = useContext(ConfigProvider.ConfigContext);
6 | return prefixCls;
7 | };
8 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/__builtins__/utils.ts:
--------------------------------------------------------------------------------
1 | export const isUrl = (path: string): boolean => {
2 | if (!path.startsWith("http")) {
3 | return false;
4 | }
5 | try {
6 | const url = new URL(path);
7 | return !!url;
8 | } catch (error) {
9 | return false;
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/li-web/packages/tsconfig/react-library.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "React Library",
4 | "extends": "./base.json",
5 | "compilerOptions": {
6 | "lib": ["ESNext", "DOM"],
7 | "module": "ESNext",
8 | "target": "ES6",
9 | "jsx": "react-jsx"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/li-web/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
15 | [Makefile]
16 | indent_style = tab
17 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/switch/index.tsx:
--------------------------------------------------------------------------------
1 | import { Switch as ArcoSwitch } from "@arco-design/web-react";
2 | import { connect, mapProps } from "@formily/react";
3 |
4 | export const Switch = connect(
5 | ArcoSwitch,
6 | mapProps({
7 | value: "checked",
8 | })
9 | );
10 |
11 | export default Switch;
12 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/__builtins__/pickDataProps.ts:
--------------------------------------------------------------------------------
1 | export const pickDataProps = (props: any = {}) => {
2 | const results: Record = {};
3 |
4 | for (let key in props) {
5 | if (key.indexOf("data-") > -1) {
6 | results[key] = props[key];
7 | }
8 | }
9 |
10 | return results;
11 | };
12 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/extension.go:
--------------------------------------------------------------------------------
1 | package lient
2 |
3 | import (
4 | "entgo.io/ent/entc"
5 | "entgo.io/ent/entc/gen"
6 | )
7 |
8 | type Extension struct {
9 | entc.DefaultExtension
10 | }
11 |
12 | func (Extension) Templates() []*gen.Template {
13 | return []*gen.Template{Templates}
14 | }
15 |
16 | var _ entc.Extension = (*Extension)(nil)
17 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./application";
2 | export * from "./async-data-provider";
3 | export * from "./document-title";
4 | export * from "./i18n";
5 | export * from "./layout";
6 | export * from "./record-provider";
7 | export * from "./route-switch";
8 | export * from "./schema-components";
9 | export * from "./sign-page";
10 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/util.go:
--------------------------------------------------------------------------------
1 | package lient
2 |
3 | import (
4 | "github.com/rs/xid"
5 | "github.com/yitter/idgenerator-go/idgen"
6 | )
7 |
8 | func init() {
9 | idgen.SetIdGenerator(idgen.NewIdGeneratorOptions(1))
10 | }
11 |
12 | func NewID() int64 {
13 | return idgen.NextId()
14 | }
15 |
16 | func NewXid() string {
17 | return xid.New().String()
18 | }
19 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/__builtins__/hooks/getLocale.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { ConfigProvider } from "@arco-design/web-react";
3 | import { Locale } from "../../../locale/types";
4 |
5 | export const getLocale = (): Locale => {
6 | const { locale } = useContext(ConfigProvider.ConfigContext);
7 | return locale as Locale;
8 | };
9 |
--------------------------------------------------------------------------------
/li-engine/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/BeanWei/li/li-engine
2 |
3 | go 1.16
4 |
5 | require (
6 | entgo.io/ent v0.10.2-0.20220510065209-fc03c8d283d3
7 | github.com/antonmedv/expr v1.9.0
8 | github.com/aws/aws-sdk-go v1.44.10
9 | github.com/gogf/gf/v2 v2.0.6
10 | github.com/hexops/valast v1.4.1
11 | github.com/rs/xid v1.4.0
12 | github.com/yitter/idgenerator-go v1.2.2
13 | )
14 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/card-item/index.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from "@arco-design/web-react";
2 |
3 | export const CardItem: React.FC> = (props) => {
4 | return (
5 |
6 | {props.children}
7 |
8 | );
9 | };
10 |
11 | export default CardItem;
12 |
--------------------------------------------------------------------------------
/li-app/internal/pkg/wf/wf.go:
--------------------------------------------------------------------------------
1 | package wf
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/pkg/wf/executor"
5 | "github.com/BeanWei/li/li-engine/contrib/liflow"
6 | )
7 |
8 | func init() {
9 | liflow.RegisterExecutor(
10 | &liflow.RegisterExecutorInput{
11 | ElementType: "ApprovalTask",
12 | ElementExecutor: new(executor.ApprovalTask),
13 | },
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/chart/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from "react";
2 |
3 | export type ChartItemContextProps = {
4 | data: Record[];
5 | loading: boolean;
6 | chartRef?: React.MutableRefObject;
7 | };
8 |
9 | export const ChartItemContext = createContext({
10 | data: [],
11 | loading: false,
12 | });
13 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from "react";
2 |
3 | export const GlobalContext = createContext<{
4 | app?: Record;
5 | lang?: string;
6 | setLang?: (value: string) => void;
7 | theme?: string;
8 | setTheme?: (value: string) => void;
9 | currentUser?: Record;
10 | setCurrentUser?: (value: Record) => void;
11 | }>({});
12 |
--------------------------------------------------------------------------------
/li-web/packages/config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "config",
3 | "version": "0.0.0",
4 | "main": "index.js",
5 | "files": [
6 | "eslint-preset.js"
7 | ],
8 | "dependencies": {
9 | "eslint-config-next": "^12.0.8",
10 | "eslint-config-prettier": "^8.3.0",
11 | "eslint-plugin-react": "7.28.0"
12 | },
13 | "devDependencies": {
14 | "typescript": "^4.5.3"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/li-app/internal/middleware/cors.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "github.com/gogf/gf/v2/frame/g"
5 | "github.com/gogf/gf/v2/net/ghttp"
6 | )
7 |
8 | // CORS 允许跨域请求中间件
9 | func CORS(r *ghttp.Request) {
10 | corsOpts := r.Response.DefaultCORSOptions()
11 | corsOpts.AllowDomain = g.Cfg().MustGet(r.Context(), "server.corsAllowDomain").Strings()
12 | r.Response.CORS(corsOpts)
13 | r.Middleware.Next()
14 | }
15 |
--------------------------------------------------------------------------------
/li-web/.prettierignore:
--------------------------------------------------------------------------------
1 | **/*.svg
2 | **/dist
3 | **/lib
4 | **/es
5 | package.json
6 | .umi
7 | .umi-production
8 | dist
9 | .dockerignore
10 | .DS_Store
11 | .eslintignore
12 | *.png
13 | *.toml
14 | docker
15 | .editorconfig
16 | Dockerfile*
17 | .gitignore
18 | .gitkeep
19 | .prettierignore
20 | LICENSE
21 | .eslintcache
22 | *.lock
23 | yarn-error.log
24 | .history
25 | CNAME
26 | build
27 | public
28 | *.ejs
29 | assets
30 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/divider/index.tsx:
--------------------------------------------------------------------------------
1 | import { Divider as ArcoDivider } from "@arco-design/web-react";
2 | import React from "react";
3 |
4 | export const Divider: React.FC> = (props) => {
5 | return (
6 |
7 | {props.children}
8 |
9 | );
10 | };
11 |
12 | export default Divider;
13 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/runtime/runtime.go:
--------------------------------------------------------------------------------
1 | // Code generated by entc, DO NOT EDIT.
2 |
3 | package runtime
4 |
5 | // The schema-stitching logic is generated in github.com/BeanWei/li/li-engine/contrib/liflow/ent/runtime.go
6 |
7 | const (
8 | Version = "v0.10.2-0.20220408082730-6e4e4da89674" // Version of ent codegen.
9 | Sum = "h1:YMUBe+itzJQhVTkrV3sRzoX7EwUVwQc5ZQ+oXxIsQIg=" // Sum of ent codegen.
10 | )
11 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/__builtins__/hooks/usePrefixCls.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { ConfigProvider } from "@arco-design/web-react";
3 |
4 | export const usePrefixCls = (
5 | tag: string,
6 | props?: {
7 | prefixCls?: string;
8 | }
9 | ) => {
10 | const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
11 | return getPrefixCls?.(tag, props?.prefixCls);
12 | };
13 |
--------------------------------------------------------------------------------
/li-app/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/BeanWei/li/li-app
2 |
3 | go 1.16
4 |
5 | require (
6 | entgo.io/ent v0.10.2-0.20220510065209-fc03c8d283d3
7 | github.com/BeanWei/li/li-engine v0.0.0
8 | github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.0.0-20220427091526-ae5891068e0e
9 | github.com/gogf/gf/v2 v2.0.6
10 | golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064
11 | )
12 |
13 | replace github.com/BeanWei/li/li-engine v0.0.0 => ../li-engine
14 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/route-switch/RouteSwitchProvider.tsx:
--------------------------------------------------------------------------------
1 | import { RouteSwitchContext } from "./context";
2 | import { RouteSwitchProviderProps } from "./types";
3 |
4 | export function RouteSwitchProvider(props: RouteSwitchProviderProps) {
5 | const { children, components } = props;
6 | return (
7 |
8 | {children}
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/route-switch/types.ts:
--------------------------------------------------------------------------------
1 | export interface RouteProps {
2 | path: string;
3 | index?: boolean;
4 | redirect?: string;
5 | component?: any;
6 | // routes?: RouteProps[];
7 | [key: string]: any;
8 | }
9 |
10 | export interface RouteSwitchProviderProps {
11 | components?: any;
12 | children?: any;
13 | }
14 |
15 | export interface RouteSwitchProps {
16 | routes?: RouteProps[];
17 | components?: any;
18 | }
19 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/form-button-group/index.less:
--------------------------------------------------------------------------------
1 | @import '~@arco-design/web-react/lib/style/theme/default.less';
2 |
3 | @btn-group-prefix-cls: ~'@{prefix}-formily-button-group';;
4 |
5 | .@{btn-group-prefix-cls}-sticky {
6 | padding: 10px 0;
7 | border-top: 1px solid #eee;
8 | z-index: 999;
9 |
10 | &-inner {
11 | display: flex;
12 | .@{prefix}formily-item {
13 | flex: 2;
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/action/Action.tsx:
--------------------------------------------------------------------------------
1 | import { Fragment } from "react";
2 | import ActionFormDrawer from "./Action.FormDrawer";
3 | import ActionFormModal from "./Action.FormModal";
4 | import { ComposedAction } from "./types";
5 |
6 | export const Action: ComposedAction = (props) => {
7 | return ;
8 | };
9 |
10 | Action.FormDrawer = ActionFormDrawer;
11 | Action.FormModal = ActionFormModal;
12 |
13 | export default Action;
14 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_phone.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import "github.com/BeanWei/li/li-engine/view/ui"
4 |
5 | func Phone(name string) *phoneBuilder {
6 | return &phoneBuilder{&NodeBuilder{
7 | schema: &ui.Schema{
8 | Name: name,
9 | Type: ui.SchemaTypeString,
10 | XComponent: ui.ComponentInput,
11 | XDecorator: ui.DecoratorFormItem,
12 | XValidator: "phone",
13 | },
14 | }}
15 | }
16 |
17 | type phoneBuilder struct {
18 | *NodeBuilder
19 | }
20 |
--------------------------------------------------------------------------------
/li-engine/view/com/com_langswitch.go:
--------------------------------------------------------------------------------
1 | package com
2 |
3 | import "github.com/BeanWei/li/li-engine/view/ui"
4 |
5 | func LangSwitch(name string) *langswitchBuilder {
6 | return &langswitchBuilder{schema: &ui.Schema{
7 | Name: name,
8 | Type: ui.SchemaTypeVoid,
9 | XComponent: "LangSwitch",
10 | }}
11 | }
12 |
13 | type langswitchBuilder struct {
14 | schema *ui.Schema
15 | }
16 |
17 | func (b *langswitchBuilder) Schema() *ui.Schema {
18 | return b.schema
19 | }
20 |
--------------------------------------------------------------------------------
/li-app/internal/data/ent/entc.go:
--------------------------------------------------------------------------------
1 | //go:build ignore
2 | // +build ignore
3 |
4 | package main
5 |
6 | // package ent
7 |
8 | import (
9 | "log"
10 |
11 | "entgo.io/ent/entc"
12 | "entgo.io/ent/entc/gen"
13 | "github.com/BeanWei/li/li-engine/contrib/lient"
14 | )
15 |
16 | func main() {
17 | err := entc.Generate("./schema",
18 | &gen.Config{},
19 | entc.Extensions(&lient.Extension{}),
20 | )
21 | if err != nil {
22 | log.Fatal("running ent codegen:", err)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/locale/index.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { ConfigProvider } from "@arco-design/web-react";
3 | import { Locale } from "./types";
4 | import enUS from "./en-US";
5 | import zhCN from "./zh-CN";
6 |
7 | function useLocale(): Locale {
8 | const lang = useContext(ConfigProvider.ConfigContext).locale?.locale;
9 | if (lang === "en-US") {
10 | return enUS;
11 | }
12 | return zhCN;
13 | }
14 |
15 | export default useLocale;
16 |
--------------------------------------------------------------------------------
/li-engine/view/com/com_themeswitch.go:
--------------------------------------------------------------------------------
1 | package com
2 |
3 | import "github.com/BeanWei/li/li-engine/view/ui"
4 |
5 | func ThemeSwitch(name string) *themeswitchBuilder {
6 | return &themeswitchBuilder{schema: &ui.Schema{
7 | Name: name,
8 | Type: ui.SchemaTypeVoid,
9 | XComponent: "ThemeSwitch",
10 | }}
11 | }
12 |
13 | type themeswitchBuilder struct {
14 | schema *ui.Schema
15 | }
16 |
17 | func (b *themeswitchBuilder) Schema() *ui.Schema {
18 | return b.schema
19 | }
20 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/locale/types.ts:
--------------------------------------------------------------------------------
1 | export type Locale = {
2 | LiFlow: {
3 | tooltipUndo: string;
4 | tooltipRedo: string;
5 | tooltipZoomIn: string;
6 | tooltipZoomOut: string;
7 | tooltipAutoFit: string;
8 | nodeSequenceFlow: string;
9 | nodeStartEvent: string;
10 | nodeEndEvent: string;
11 | nodeExclusiveGateway: string;
12 | nodeApproverTask: string;
13 | nodeWebhookTask: string;
14 | [key: string]: string;
15 | };
16 | };
17 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/internal/ent/entc.go:
--------------------------------------------------------------------------------
1 | //go:build ignore
2 | // +build ignore
3 |
4 | package main
5 |
6 | // package ent
7 |
8 | import (
9 | "log"
10 |
11 | "entgo.io/ent/entc"
12 | "entgo.io/ent/entc/gen"
13 | "github.com/BeanWei/li/li-engine/contrib/lient"
14 | )
15 |
16 | func main() {
17 | err := entc.Generate("./schema",
18 | &gen.Config{},
19 | entc.Extensions(&lient.Extension{}),
20 | )
21 | if err != nil {
22 | log.Fatal("running ent codegen:", err)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/route-switch/hooks.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import get from "lodash/get";
3 | import { RouteContext, RouteSwitchContext } from "./context";
4 |
5 | export function useRouteComponent(name?: string) {
6 | if (!name) {
7 | return () => null;
8 | }
9 | const { components } = useContext(RouteSwitchContext);
10 | return get(components, name) || (() => null);
11 | }
12 |
13 | export function useRoute() {
14 | return useContext(RouteContext);
15 | }
16 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_chart.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import "github.com/BeanWei/li/li-engine/view/ui"
4 |
5 | func Chart(name string) *chartBuilder {
6 | return &chartBuilder{&formgridBuilder{&NodeBuilder{
7 | schema: &ui.Schema{
8 | Name: name,
9 | Type: ui.SchemaTypeVoid,
10 | XComponent: ui.ComponentChart,
11 | XComponentProps: make(map[string]interface{}),
12 | },
13 | },
14 | }}
15 | }
16 |
17 | type chartBuilder struct {
18 | *formgridBuilder
19 | }
20 |
--------------------------------------------------------------------------------
/li-app/internal/cmd/cmd_migrate.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/BeanWei/li/li-app/internal/data/ent"
7 | entmigrate "github.com/BeanWei/li/li-app/internal/data/ent/migrate"
8 | "github.com/gogf/gf/v2/os/gcmd"
9 | )
10 |
11 | func migrate(ctx context.Context, parser *gcmd.Parser) (err error) {
12 | return ent.LiClient().Schema.Create(ctx,
13 | entmigrate.WithForeignKeys(false),
14 | entmigrate.WithDropIndex(true),
15 | entmigrate.WithDropColumn(true),
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/hooks/useComponent.ts:
--------------------------------------------------------------------------------
1 | import { SchemaOptionsContext } from "@formily/react";
2 | import { get } from "lodash";
3 | import { useContext } from "react";
4 |
5 | export const useComponent = (component: any, defaults?: any) => {
6 | if (!component) {
7 | return defaults;
8 | }
9 | if (typeof component !== "string") {
10 | return component;
11 | }
12 | const { components } = useContext(SchemaOptionsContext);
13 | return get(components, component) || defaults;
14 | };
15 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/locale/zh-CN.ts:
--------------------------------------------------------------------------------
1 | import { Locale } from "./types";
2 |
3 | const zhCN: Locale = {
4 | LiFlow: {
5 | tooltipUndo: "上一步",
6 | tooltipRedo: "下一步",
7 | tooltipZoomIn: "放大",
8 | tooltipZoomOut: "缩小",
9 | tooltipAutoFit: "适应屏幕",
10 | nodeSequenceFlow: "连接线",
11 | nodeStartEvent: "开始节点",
12 | nodeEndEvent: "结束节点",
13 | nodeExclusiveGateway: "排他网关",
14 | nodeApproverTask: "审批节点",
15 | nodeWebhookTask: "钩子节点",
16 | },
17 | };
18 |
19 | export default zhCN;
20 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/entc.go:
--------------------------------------------------------------------------------
1 | //go:build ignore
2 | // +build ignore
3 |
4 | package main
5 |
6 | import (
7 | "log"
8 |
9 | "entgo.io/ent/entc"
10 | "entgo.io/ent/entc/gen"
11 | "github.com/BeanWei/li/li-engine/contrib/lient"
12 | )
13 |
14 | func main() {
15 | err := entc.Generate("./schema",
16 | &gen.Config{
17 | Features: []gen.Feature{
18 | gen.FeatureUpsert,
19 | },
20 | },
21 | entc.Extensions(&lient.Extension{}),
22 | )
23 | if err != nil {
24 | log.Fatal("running ent codegen:", err)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/__builtins__/loading.ts:
--------------------------------------------------------------------------------
1 | import { Message } from "@arco-design/web-react";
2 |
3 | export const loading = async (
4 | title: React.ReactNode = "Loading...",
5 | processor: () => Promise
6 | ) => {
7 | let hide: any = null;
8 | let loading = setTimeout(() => {
9 | hide = Message.loading({
10 | content: title,
11 | });
12 | }, 100);
13 | try {
14 | return await processor();
15 | } finally {
16 | hide?.();
17 | clearTimeout(loading);
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/li-app/internal/cmd/cmd_user.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/BeanWei/li/li-app/internal/data/ent"
7 | "github.com/gogf/gf/v2/os/gcmd"
8 | )
9 |
10 | func userCreate(ctx context.Context, parser *gcmd.Parser) (err error) {
11 | err = ent.LiClient().User.Create().
12 | SetEmail(parser.GetOpt("email").String()).
13 | SetPassword(parser.GetOpt("password").String()).
14 | SetNickname(parser.GetOpt("nickname").String()).
15 | SetIsAdmin(parser.GetOpt("isAdmin").Bool()).
16 | Exec(ctx)
17 | return
18 | }
19 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/view/blog.tag.go:
--------------------------------------------------------------------------------
1 | package view
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/data/ent"
5 | "github.com/BeanWei/li/li-engine/view"
6 | "github.com/BeanWei/li/li-engine/view/node"
7 | )
8 |
9 | type BlogTag struct {
10 | view.Schema
11 | }
12 |
13 | func (BlogTag) Nodes() []view.Node {
14 | return []view.Node{
15 | node.GridRow("row1").
16 | Gutter(16).
17 | Children(
18 | node.GridCol("col1").
19 | Span(24).
20 | Children(
21 | ent.ListTagView(),
22 | ),
23 | ),
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/view/blog.post.go:
--------------------------------------------------------------------------------
1 | package view
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/data/ent"
5 | "github.com/BeanWei/li/li-engine/view"
6 | "github.com/BeanWei/li/li-engine/view/node"
7 | )
8 |
9 | type BlogPost struct {
10 | view.Schema
11 | }
12 |
13 | func (BlogPost) Nodes() []view.Node {
14 | return []view.Node{
15 | node.GridRow("row1").
16 | Gutter(16).
17 | Children(
18 | node.GridCol("col1").
19 | Span(24).
20 | Children(
21 | ent.ListPostView(),
22 | ),
23 | ),
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/view/system.user.go:
--------------------------------------------------------------------------------
1 | package view
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/data/ent"
5 | "github.com/BeanWei/li/li-engine/view"
6 | "github.com/BeanWei/li/li-engine/view/node"
7 | )
8 |
9 | type SystemUser struct {
10 | view.Schema
11 | }
12 |
13 | func (SystemUser) Nodes() []view.Node {
14 | return []view.Node{
15 | node.GridRow("row1").
16 | Gutter(16).
17 | Children(
18 | node.GridCol("col1").
19 | Span(24).
20 | Children(
21 | ent.ListUserView(),
22 | ),
23 | ),
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/grid/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Grid as ArcoGrid, ColProps, RowProps } from "@arco-design/web-react";
3 |
4 | type ComposedGrid = React.FC<{}> & {
5 | Row?: React.FC;
6 | Col?: React.FC;
7 | };
8 |
9 | export const Grid: ComposedGrid = () => {
10 | return <>>;
11 | };
12 |
13 | Grid.Row = (props) => {
14 | return ;
15 | };
16 |
17 | Grid.Col = (props) => {
18 | return ;
19 | };
20 |
21 | export default Grid;
22 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/view/blog.comment.go:
--------------------------------------------------------------------------------
1 | package view
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/data/ent"
5 | "github.com/BeanWei/li/li-engine/view"
6 | "github.com/BeanWei/li/li-engine/view/node"
7 | )
8 |
9 | type BlogComment struct {
10 | view.Schema
11 | }
12 |
13 | func (BlogComment) Nodes() []view.Node {
14 | return []view.Node{
15 | node.GridRow("row1").
16 | Gutter(16).
17 | Children(
18 | node.GridCol("col1").
19 | Span(24).
20 | Children(
21 | ent.ListCommentView(),
22 | ),
23 | ),
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_email.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import "github.com/BeanWei/li/li-engine/view/ui"
4 |
5 | func Email(name string) *emailBuilder {
6 | return &emailBuilder{&textBuilder{&NodeBuilder{
7 | schema: &ui.Schema{
8 | Name: name,
9 | Type: ui.SchemaTypeString,
10 | XComponent: ui.ComponentInput,
11 | XComponentProps: make(map[string]interface{}),
12 | XDecorator: ui.DecoratorFormItem,
13 | XValidator: "email",
14 | },
15 | }}}
16 | }
17 |
18 | type emailBuilder struct {
19 | *textBuilder
20 | }
21 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/template/import.tmpl:
--------------------------------------------------------------------------------
1 | {{/* gotype: entgo.io/ent/entc/gen.Type */}}
2 |
3 | {{ define "import/additional/lient" }}
4 | "context"
5 | "reflect"
6 | "entgo.io/ent/dialect/sql/sqljson"
7 | "github.com/BeanWei/li/li-engine/ac"
8 | "github.com/BeanWei/li/li-engine/contrib/lient/sqlx"
9 | "github.com/BeanWei/li/li-engine/view"
10 | "github.com/BeanWei/li/li-engine/view/node"
11 | "github.com/BeanWei/li/li-engine/view/ui"
12 | "github.com/gogf/gf/v2/errors/gcode"
13 | "github.com/gogf/gf/v2/errors/gerror"
14 | "github.com/gogf/gf/v2/util/gconv"
15 | {{ end }}
--------------------------------------------------------------------------------
/li-web/apps/admin/src/assets/dark.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/hooks/useCompile.ts:
--------------------------------------------------------------------------------
1 | import { compile } from "@formily/json-schema/lib/compiler";
2 | import {
3 | SchemaExpressionScopeContext,
4 | SchemaOptionsContext,
5 | } from "@formily/react";
6 | import { useContext } from "react";
7 |
8 | export const useCompile = () => {
9 | const options = useContext(SchemaOptionsContext);
10 | const scope = useContext(SchemaExpressionScopeContext);
11 | return (source: any) => {
12 | if (!source) {
13 | return source;
14 | }
15 | return compile(source, { ...options.scope, ...scope });
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/li-web/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 | .pnp
6 | .pnp.js
7 |
8 | # testing
9 | coverage
10 |
11 | # next.js
12 | .next/
13 | out/
14 | build
15 |
16 | # misc
17 | .DS_Store
18 | *.pem
19 |
20 | # debug
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 | .pnpm-debug.log*
25 |
26 | # local env files
27 | .env.local
28 | .env.development.local
29 | .env.test.local
30 | .env.production.local
31 |
32 | # turbo
33 | .turbo
34 |
35 | # umi
36 | .umi
37 |
38 | # dev
39 | .example
40 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/__builtins__/icon.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import * as ICONS from "@arco-design/web-react/icon";
3 | import { IconProps } from "@arco-design/web-react/icon";
4 |
5 | const allicons = ICONS as Record;
6 |
7 | export const Icon: React.FC = (props) => {
8 | const { type, ...rest } = props;
9 | if (!type) {
10 | return null;
11 | }
12 | const Icon = allicons[type];
13 | if (!Icon) {
14 | return null;
15 | }
16 | return ;
17 | };
18 |
19 | export default Icon;
20 |
--------------------------------------------------------------------------------
/li-web/apps/admin/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 | Li Admin
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/components/Loading.tsx:
--------------------------------------------------------------------------------
1 | import { Spin } from "@arco-design/web-react";
2 |
3 | export const Loading: React.FC = () => {
4 | return (
5 |
12 |
22 |
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/upload/types.ts:
--------------------------------------------------------------------------------
1 | import { UploadProps } from "@arco-design/web-react";
2 | import React from "react";
3 |
4 | export type UploadAttachmentProps = Omit & {
5 | value?: string[];
6 | onChange?: (value?: (string | undefined)[]) => void;
7 | };
8 |
9 | export type UploadAvatarProps = Omit & {
10 | value?: string;
11 | onChange?: (value?: string) => void;
12 | };
13 |
14 | export type ComposedUpload = React.FC & {
15 | Attachment?: React.FC;
16 | Avatar?: React.FC;
17 | };
18 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/locale/en-US.ts:
--------------------------------------------------------------------------------
1 | import { Locale } from "./types";
2 |
3 | const enUS: Locale = {
4 | LiFlow: {
5 | tooltipUndo: "Undo",
6 | tooltipRedo: "Redo",
7 | tooltipZoomIn: "Zoom In",
8 | tooltipZoomOut: "Zoom Out",
9 | tooltipAutoFit: "Auto Fit",
10 | nodeSequenceFlow: "Sequence Flow",
11 | nodeStartEvent: "Start Event",
12 | nodeEndEvent: "End Event",
13 | nodeGateway: "Gateway",
14 | nodeExclusiveGateway: "Exclusive Gateway",
15 | nodeApproverTask: "Approver Task",
16 | nodeWebhookTask: "Webhook Task",
17 | },
18 | };
19 |
20 | export default enUS;
21 |
--------------------------------------------------------------------------------
/li-web/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "li-web",
3 | "version": "0.0.0",
4 | "private": true,
5 | "workspaces": [
6 | "apps/*",
7 | "packages/*"
8 | ],
9 | "scripts": {
10 | "build": "turbo run build",
11 | "dev": "turbo run dev --parallel",
12 | "lint": "turbo run lint",
13 | "format": "prettier -c --write \"**/*.{ts,tsx,md}\" --end-of-line auto"
14 | },
15 | "devDependencies": {
16 | "@arco-design/web-react": "^2.32.2",
17 | "prettier": "^2.6.2",
18 | "turbo": "^1.2.6"
19 | },
20 | "engines": {
21 | "npm": ">=7.0.0",
22 | "node": ">=14.0.0"
23 | },
24 | "packageManager": "pnpm@6.32.1"
25 | }
26 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/chart/utils.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 图表图片导出, 只支持 renderer = 'canvas'
3 | * @param chart chart 实例
4 | * @param name 图片名称,可选,默认名为 'download'
5 | */
6 | export function downloadImage(chart: any, name: string = "download") {
7 | if (!chart) return;
8 | const canvas = chart.getCanvas();
9 | canvas.get("timeline").stopAllAnimations();
10 | const dataURL = canvas.get("el").toDataURL({
11 | format: "png",
12 | quality: 1,
13 | });
14 | let a: HTMLAnchorElement | null = document.createElement("a");
15 | a.href = dataURL;
16 | a.download = `${name}-${new Date().toLocaleDateString()}.png`;
17 | a.click();
18 | }
19 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/hooks/useAttach.ts:
--------------------------------------------------------------------------------
1 | import { useRef, useEffect } from "react";
2 |
3 | interface IRecycleTarget {
4 | onMount: () => void;
5 | onUnmount: () => void;
6 | }
7 |
8 | export const useAttach = (target: T): T => {
9 | const oldTargetRef = useRef(null);
10 | useEffect(() => {
11 | if (oldTargetRef.current && target !== oldTargetRef.current) {
12 | oldTargetRef.current.onUnmount();
13 | }
14 | oldTargetRef.current = target;
15 | target.onMount();
16 | return () => {
17 | target.onUnmount();
18 | };
19 | }, [target]);
20 | return target;
21 | };
22 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/chart/Chart.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Card } from "@arco-design/web-react";
3 | import FormGrid, { IFormGridProps } from "../form-grid";
4 | import ChartAutoChart from "./Chart.AutoChart";
5 |
6 | export type ComposedChart = React.FC<
7 | React.PropsWithChildren
8 | > & {
9 | AutoChart?: React.FC;
10 | };
11 |
12 | export const Chart: ComposedChart = (props) => {
13 | return (
14 |
15 | {props.children}
16 |
17 | );
18 | };
19 |
20 | Chart.AutoChart = ChartAutoChart;
21 |
22 | export default Chart;
23 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/hooks/useFieldProps.ts:
--------------------------------------------------------------------------------
1 | import { useContext, useRef } from "react";
2 | import {
3 | Schema,
4 | SchemaExpressionScopeContext,
5 | SchemaOptionsContext,
6 | } from "@formily/react";
7 |
8 | export const useFieldProps = (schema: Schema) => {
9 | const options = useContext(SchemaOptionsContext);
10 | const scope = useContext(SchemaExpressionScopeContext);
11 | const scopeRef = useRef();
12 | scopeRef.current = scope;
13 | return schema.toFieldProps({
14 | ...options,
15 | get scope() {
16 | return {
17 | ...options.scope,
18 | ...scopeRef.current,
19 | };
20 | },
21 | }) as any;
22 | };
23 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_form.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func Form(name string) *formBuilder {
9 | return &formBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeObject,
13 | XComponent: ui.ComponentForm,
14 | },
15 | }}
16 | }
17 |
18 | type formBuilder struct {
19 | *NodeBuilder
20 | }
21 |
22 | func (b *formBuilder) AC(f ac.AC) *formBuilder {
23 | b.schema.AC = f
24 | return b
25 | }
26 |
27 | func (b *formBuilder) DecoratorCard() *formBuilder {
28 | b.schema.XDecorator = ui.DecoratorCardItem
29 | return b
30 | }
31 |
--------------------------------------------------------------------------------
/li-app/internal/cmd/cmd_run.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/BeanWei/li/li-app/internal/app/admin"
7 | "github.com/BeanWei/li/li-app/internal/middleware"
8 | "github.com/gogf/gf/v2/frame/g"
9 | "github.com/gogf/gf/v2/os/gcmd"
10 | "github.com/gogf/gf/v2/os/gsession"
11 | )
12 |
13 | func run(ctx context.Context, parser *gcmd.Parser) (err error) {
14 | s := g.Server()
15 | s.SetSessionStorage(gsession.NewStorageRedis(g.Redis()))
16 | s.Use(
17 | middleware.ErrorHandler,
18 | middleware.CORS,
19 | middleware.Ctx,
20 | // TODO: I18N
21 | // middleware.I18N,
22 | middleware.Authentication,
23 | )
24 | admin.Init()
25 | s.Run()
26 | return
27 | }
28 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/avatar/index.tsx:
--------------------------------------------------------------------------------
1 | import { Avatar as ArcoAvatar, AvatarProps } from "@arco-design/web-react";
2 | import React from "react";
3 |
4 | export const Avatar: React.FC<
5 | React.PropsWithChildren<{
6 | shape?: AvatarProps["shape"];
7 | size?: AvatarProps["size"];
8 | alt?: string;
9 | src?: string;
10 | }>
11 | > = (props) => {
12 | if (props.src) {
13 | return (
14 |
15 |
16 |
17 | );
18 | }
19 | return {props.children};
20 | };
21 |
22 | export default Avatar;
23 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/li-flow/nodes/index.ts:
--------------------------------------------------------------------------------
1 | import LogicFlow from "@logicflow/core";
2 | import EndEvent from "./EndEvent";
3 | import SequenceFlow from "./SequenceFlow";
4 | import StartEvent from "./StartEvent";
5 | import ApproverTask from "./ApproverTask";
6 | import ExclusiveGateway from "./ExclusiveGateway";
7 | import WebhookTask from "./WebhookTask";
8 | import { eletype } from "../config";
9 |
10 | export const registerNodes = (lf: LogicFlow) => {
11 | lf.register(StartEvent);
12 | lf.register(EndEvent);
13 | lf.register(ApproverTask);
14 | lf.register(WebhookTask);
15 | lf.register(SequenceFlow);
16 | lf.register(ExclusiveGateway);
17 | lf.setDefaultEdgeType(eletype.sequenceflow);
18 | };
19 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/select/shared.ts:
--------------------------------------------------------------------------------
1 | import { toArr } from "@formily/shared";
2 |
3 | export const getCurrentOptions = (values: any, dataSource: any) => {
4 | values = toArr(values).map((val) =>
5 | typeof val === "object" ? val.value : val
6 | );
7 | const findOptions = (options: any[]): any => {
8 | let current = [];
9 | for (const option of options) {
10 | if (values.includes(option.value)) {
11 | current.push(option);
12 | }
13 | const children = option.options;
14 | if (Array.isArray(children)) {
15 | current.push(...findOptions(children));
16 | }
17 | }
18 | return current;
19 | };
20 | return findOptions(dataSource);
21 | };
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, built with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
14 | *.DS_Store
15 | .idea/
16 | .vscode/
17 | *exvim*
18 | *vendor*
19 |
20 | # ent 仅保留schema文件目录和generate/entc文件
21 | **/ent/*
22 | !**/ent/schema
23 | !**/ent/generate.go
24 | !**/ent/entc.go
25 | !li-engine/contrib/liflow/ent/*
26 |
27 | # frontend
28 | node_modules/
29 | npm-debug.log
30 | yarn-error.log
31 | package-lock.json
32 |
33 | # backend
34 | vender/
35 | log/
36 | bin/
37 | cbuild
38 | config.yaml
39 | main
40 |
41 | # app
42 | li-app/tmp/
43 | li-app/*go.sum
44 | _PERSISTENT_/
--------------------------------------------------------------------------------
/li-engine/contrib/lient/sqlx/utils.go:
--------------------------------------------------------------------------------
1 | package sqlx
2 |
3 | import "strings"
4 |
5 | // escape escapes w with the default escape character ('/'),
6 | // to be used by the pattern matching functions below.
7 | // The second return value indicates if w was escaped or not.
8 | func escape(w string) (string, bool) {
9 | var n int
10 | for i := range w {
11 | if c := w[i]; c == '%' || c == '_' || c == '\\' {
12 | n++
13 | }
14 | }
15 | // No characters to escape.
16 | if n == 0 {
17 | return w, false
18 | }
19 | var b strings.Builder
20 | b.Grow(len(w) + n)
21 | for i := range w {
22 | if c := w[i]; c == '%' || c == '_' || c == '\\' {
23 | b.WriteByte('\\')
24 | }
25 | b.WriteByte(w[i])
26 | }
27 | return b.String(), true
28 | }
29 |
--------------------------------------------------------------------------------
/li-app/internal/middleware/err.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "github.com/gogf/gf/v2/errors/gcode"
5 | "github.com/gogf/gf/v2/errors/gerror"
6 | "github.com/gogf/gf/v2/net/ghttp"
7 | )
8 |
9 | // ErrorHandler 用来兜底的错误处理
10 | func ErrorHandler(r *ghttp.Request) {
11 | r.Middleware.Next()
12 | if err := r.GetError(); err != nil {
13 | r.Response.ClearBuffer()
14 | var (
15 | code = gerror.Code(err)
16 | msg string
17 | )
18 | if code == gcode.CodeNil {
19 | code = gcode.CodeInternalError
20 | msg = err.Error()
21 | } else {
22 | code = gcode.CodeInternalError
23 | msg = "Oops, 服务器居然开小差了, 请稍后再试吧"
24 | }
25 | r.Response.WriteJson(ghttp.DefaultHandlerResponse{
26 | Code: code.Code(),
27 | Message: msg,
28 | })
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/array-base/index.less:
--------------------------------------------------------------------------------
1 | @import '~@arco-design/web-react/lib/style/theme/default.less';
2 |
3 | @array-base-prefix-cls: ~'@{prefix}-formily-array-base';
4 |
5 | .@{array-base-prefix-cls}-remove {
6 | transition: all 0.25s ease-in-out;
7 | font-size: 16px;
8 | }
9 |
10 | .@{array-base-prefix-cls}-sort-handle {
11 | cursor: move;
12 | color: #888 !important;
13 | }
14 |
15 | .@{array-base-prefix-cls}-addition {
16 | transition: all 0.25s ease-in-out;
17 | }
18 |
19 | .@{array-base-prefix-cls}-move-down {
20 | transition: all 0.25s ease-in-out;
21 | font-size: 16px;
22 | margin-left: 6px;
23 | }
24 |
25 | .@{array-base-prefix-cls}-move-up {
26 | transition: all 0.25s ease-in-out;
27 | font-size: 16px;
28 | margin-left: 6px;
29 | }
30 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/list/context.ts:
--------------------------------------------------------------------------------
1 | import { createContext } from "react";
2 | import { TableProps } from "@arco-design/web-react";
3 | import { Result } from "pro-utils";
4 | import { ListProps } from "./types";
5 |
6 | export type ReloadData = {
7 | page?: number;
8 | limit?: number;
9 | query?: string;
10 | sorter?: Record;
11 | filter?: Record;
12 | };
13 |
14 | export type ListContextProps = {
15 | result?: Result;
16 | reload?: (values?: ReloadData) => void;
17 | tableProps?: TableProps & {
18 | onSearch?: (values: Record) => void;
19 | filter?: ListProps["filter"];
20 | };
21 | selectedKeys?: (string | number)[];
22 | };
23 |
24 | export const ListContext = createContext({});
25 |
--------------------------------------------------------------------------------
/li-web/apps/admin/mock/listUser.ts:
--------------------------------------------------------------------------------
1 | export default [
2 | { id: "1", nickname: "A", email: "a@li.com", money: 178343434.89 },
3 | {
4 | id: "2",
5 | nickname: "B",
6 | email: "b@li.com",
7 | likes: "LOL",
8 | friends: [
9 | { id: "1", nickname: "A", email: "a@li.com", money: 178343434.89 },
10 | {
11 | id: "3",
12 | nickname: "C",
13 | email: "c@li.com",
14 | avatar:
15 | "https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a8c8cdb109cb051163646151a4a5083b.png~tplv-uwbnlip3yd-webp.webp",
16 | },
17 | ],
18 | },
19 | {
20 | id: "3",
21 | nickname: "C",
22 | email: "c@li.com",
23 | avatar:
24 | "https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a8c8cdb109cb051163646151a4a5083b.png~tplv-uwbnlip3yd-webp.webp",
25 | },
26 | ];
27 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_actionformmodalcancel.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ActionFormModalCancel(name string) *actionformmodalcancelBuilder {
9 | return &actionformmodalcancelBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentActionFormModalCancel,
14 | },
15 | }}
16 | }
17 |
18 | type actionformmodalcancelBuilder struct {
19 | *NodeBuilder
20 | }
21 |
22 | func (b *actionformmodalcancelBuilder) AC(f ac.AC) *actionformmodalcancelBuilder {
23 | b.schema.AC = f
24 | return b
25 | }
26 |
27 | func (b *actionformmodalcancelBuilder) Title(title string) *actionformmodalcancelBuilder {
28 | b.SetTitle(title)
29 | return b
30 | }
31 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/locale/types.ts:
--------------------------------------------------------------------------------
1 | import { Locale as ArcoLocale } from "@arco-design/web-react/es/locale/interface";
2 |
3 | export type Locale = ArcoLocale & {
4 | Chart: {
5 | nodata: string;
6 | };
7 | ColorSelect: {
8 | red: string;
9 | orangered: string;
10 | orange: string;
11 | gold: string;
12 | lime: string;
13 | green: string;
14 | cyan: string;
15 | blue: string;
16 | arcobule: string;
17 | purple: string;
18 | pinkpurple: string;
19 | magenta: string;
20 | gray: string;
21 | };
22 | List: {
23 | query: string;
24 | reset: string;
25 | search: string;
26 | confirmDelete: string;
27 | };
28 | ListFilter: {
29 | yes: string;
30 | no: string;
31 | };
32 | RecordPicker: {
33 | drawerTitle: string;
34 | };
35 | };
36 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_actionformdrawercancel.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ActionFormDrawerCancel(name string) *actionformdrawercancelBuilder {
9 | return &actionformdrawercancelBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentActionFormDrawerCancel,
14 | },
15 | }}
16 | }
17 |
18 | type actionformdrawercancelBuilder struct {
19 | *NodeBuilder
20 | }
21 |
22 | func (b *actionformdrawercancelBuilder) AC(f ac.AC) *actionformdrawercancelBuilder {
23 | b.schema.AC = f
24 | return b
25 | }
26 |
27 | func (b *actionformdrawercancelBuilder) Title(title string) *actionformdrawercancelBuilder {
28 | b.SetTitle(title)
29 | return b
30 | }
31 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/locale/zh-CN.tsx:
--------------------------------------------------------------------------------
1 | import ArcoZhCN from "@arco-design/web-react/es/locale/zh-CN";
2 | import { Locale } from "./types";
3 |
4 | export const zhCN: Locale = {
5 | ...ArcoZhCN,
6 | Chart: {
7 | nodata: "暂无数据",
8 | },
9 | ColorSelect: {
10 | red: "浪漫红",
11 | orangered: "晚秋黄",
12 | orange: "活力橙",
13 | gold: "黄昏",
14 | lime: "新生绿",
15 | green: "仙野绿",
16 | cyan: "碧涛青",
17 | blue: "海蔚蓝",
18 | arcobule: "极致蓝",
19 | purple: "暗夜紫",
20 | pinkpurple: "青春紫",
21 | magenta: "品红",
22 | gray: "中性灰",
23 | },
24 | List: {
25 | query: "查询",
26 | reset: "重置",
27 | search: "搜索",
28 | confirmDelete: "你确定要删除吗?",
29 | },
30 | ListFilter: {
31 | yes: "是",
32 | no: "否",
33 | },
34 | RecordPicker: {
35 | drawerTitle: "请选择",
36 | },
37 | };
38 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/executor/exclusive_gateway.go:
--------------------------------------------------------------------------------
1 | package executor
2 |
3 | import "github.com/BeanWei/li/li-engine/contrib/liflow"
4 |
5 | type ExclusiveGatewayExecutor struct {
6 | ElementExecutor
7 | }
8 |
9 | func (e *ExclusiveGatewayExecutor) Execute(ctx *liflow.FlowCtx) error {
10 | // TODO: 2022/05/01 Support hook
11 | ctx.CurrentNodeInstance.FlowInstanceDataID = ctx.InstanceDataID
12 | ctx.CurrentNodeInstance.Status = liflow.FlowNodeInstanceStatusCompleted
13 | ctx.NodeInstanceList = append(ctx.NodeInstanceList, *ctx.CurrentNodeInstance)
14 | return nil
15 | }
16 |
17 | func (e *ExclusiveGatewayExecutor) GetExecuteExecutor(ctx *liflow.FlowCtx) liflow.Executor {
18 | nextNode := ctx.CalculateNextNode(ctx.CurrentNodeModel, ctx.InstanceDataMap)
19 | ctx.CurrentNodeModel = nextNode
20 | return liflow.GetElementExecutor(nextNode.Type)
21 | }
22 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_dropdownmenuitem.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func DropdownMenuItem(name string) *dropdownmenuitemBuilder {
9 | return &dropdownmenuitemBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentDropdownMenuItem,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type dropdownmenuitemBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *dropdownmenuitemBuilder) AC(f ac.AC) *dropdownmenuitemBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *dropdownmenuitemBuilder) Title(title string) *dropdownmenuitemBuilder {
29 | b.SetTitle(title)
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arrayitemsindex.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ArrayItemsIndex(name string) *arrayitemsindexBuilder {
9 | return &arrayitemsindexBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentArrayItemsIndex,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type arrayitemsindexBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *arrayitemsindexBuilder) AC(f ac.AC) *arrayitemsindexBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *arrayitemsindexBuilder) Title(title string) *arrayitemsindexBuilder {
29 | b.schema.XComponentProps["title"] = title
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arraytableindex.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ArrayTableIndex(name string) *arraytableindexBuilder {
9 | return &arraytableindexBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentArrayTableIndex,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type arraytableindexBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *arraytableindexBuilder) AC(f ac.AC) *arraytableindexBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *arraytableindexBuilder) Title(title string) *arraytableindexBuilder {
29 | b.schema.XComponentProps["title"] = title
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/schema-components/theme-switch/index.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { Button, ButtonProps } from "@arco-design/web-react";
3 | import { IconMoonFill, IconSunFill } from "@arco-design/web-react/icon";
4 | import { observer } from "@formily/react";
5 | import { GlobalContext } from "../../../context";
6 |
7 | export const ThemeSwitch: React.FC = observer((props) => {
8 | const { theme, setTheme } = useContext(GlobalContext);
9 |
10 | return (
11 | : }
19 | onClick={() => setTheme?.(theme === "light" ? "dark" : "light")}
20 | />
21 | );
22 | });
23 |
24 | export default ThemeSwitch;
25 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arrayitemsremove.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ArrayItemRemove(name string) *arrayitemsremoveBuilder {
9 | return &arrayitemsremoveBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentArrayItemsRemove,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type arrayitemsremoveBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *arrayitemsremoveBuilder) AC(f ac.AC) *arrayitemsremoveBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *arrayitemsremoveBuilder) Title(title string) *arrayitemsremoveBuilder {
29 | b.schema.XComponentProps["title"] = title
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/application/index.tsx:
--------------------------------------------------------------------------------
1 | import { Suspense } from "react";
2 | import { Loading } from "../components";
3 |
4 | const Blank = ({ children }: any) => children || null;
5 |
6 | export const compose = (...components: any[]) => {
7 | const Root = [...components, Blank].reduce((parent, child) => {
8 | const [Parent, parentProps] = Array.isArray(parent) ? parent : [parent];
9 | const [Child, childProps] = Array.isArray(child) ? child : [child];
10 | return ({ children }: any) => (
11 |
12 | {children}
13 |
14 | );
15 | });
16 | return (LastChild?: any) => (props?: any) => {
17 | return (
18 | }>
19 | {LastChild && }
20 |
21 | );
22 | };
23 | };
24 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arrayitemsmoveup.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ArrayItemsMoveUp(name string) *arrayitemsmoveupBuilder {
9 | return &arrayitemsmoveupBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentArrayItemsMoveUp,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type arrayitemsmoveupBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *arrayitemsmoveupBuilder) AC(f ac.AC) *arrayitemsmoveupBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *arrayitemsmoveupBuilder) Title(title string) *arrayitemsmoveupBuilder {
29 | b.schema.XComponentProps["title"] = title
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arraytablemoveup.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ArrayTableMoveUp(name string) *arraytablemoveupBuilder {
9 | return &arraytablemoveupBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentArrayTableMoveUp,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type arraytablemoveupBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *arraytablemoveupBuilder) AC(f ac.AC) *arraytablemoveupBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *arraytablemoveupBuilder) Title(title string) *arraytablemoveupBuilder {
29 | b.schema.XComponentProps["title"] = title
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arraytableremove.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ArrayTableRemove(name string) *arraytableremoveBuilder {
9 | return &arraytableremoveBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentArrayTableRemove,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type arraytableremoveBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *arraytableremoveBuilder) AC(f ac.AC) *arraytableremoveBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *arraytableremoveBuilder) Title(title string) *arraytableremoveBuilder {
29 | b.schema.XComponentProps["title"] = title
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-app/internal/cmd/cmd.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | _ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
5 |
6 | _ "github.com/BeanWei/li/li-app/internal/data/hook"
7 | "github.com/gogf/gf/v2/os/gcmd"
8 | )
9 |
10 | var Li = &gcmd.Command{
11 | Name: "li",
12 | Usage: "li-app cli",
13 | }
14 |
15 | func init() {
16 | Li.AddCommand(
17 | &gcmd.Command{
18 | Name: "run",
19 | Usage: "run app",
20 | Func: run,
21 | },
22 | &gcmd.Command{
23 | Name: "migrate",
24 | Usage: "migrate schemas",
25 | Func: migrate,
26 | },
27 | &gcmd.Command{
28 | Name: "user-create",
29 | Usage: "create user",
30 | Func: userCreate,
31 | Arguments: []gcmd.Argument{
32 | {Name: "email", Short: "u"},
33 | {Name: "password", Short: "p"},
34 | {Name: "nickname", Short: "n"},
35 | {Name: "isAdmin", Short: "a"},
36 | },
37 | },
38 | )
39 | }
40 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_dropdownmenusubmenu.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func DropdownMenuSubMenu(name string) *dropdownmenusubmenuBuilder {
9 | return &dropdownmenusubmenuBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentDropdownMenuSubMenu,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type dropdownmenusubmenuBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *dropdownmenusubmenuBuilder) AC(f ac.AC) *dropdownmenusubmenuBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *dropdownmenusubmenuBuilder) Title(title string) *dropdownmenusubmenuBuilder {
29 | b.SetTitle(title)
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/view/app.sign.go:
--------------------------------------------------------------------------------
1 | package view
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/app/admin/consts"
5 | "github.com/BeanWei/li/li-app/internal/app/admin/controller"
6 | "github.com/BeanWei/li/li-engine/view"
7 | "github.com/BeanWei/li/li-engine/view/node"
8 | )
9 |
10 | func SignFormNode() view.Node {
11 | return node.Form("signform").
12 | Children(
13 | node.Email("email").
14 | Placeholder("邮箱").
15 | SetRequired(true),
16 | node.Password("password").
17 | Placeholder("密码").
18 | SetRequired(true),
19 | node.Submit("submit").
20 | ButtonLong(true).
21 | ButtonType("primary").
22 | ButtonStyle(map[string]interface{}{
23 | "width": "100%",
24 | }).
25 | ForSubmit(controller.OperationUserSignIn, controller.UserSignIn).
26 | ForSubmitSuccessTo(consts.AppEntry).
27 | SetXContent("登录"),
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/view/dashboard.workplace.go:
--------------------------------------------------------------------------------
1 | package view
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/view"
5 | "github.com/BeanWei/li/li-engine/view/node"
6 | )
7 |
8 | type DashboardWorkplace struct {
9 | view.Schema
10 | }
11 |
12 | func (DashboardWorkplace) Nodes() []view.Node {
13 | return []view.Node{
14 | node.GridRow("row1").
15 | Gutter(16).
16 | Children(
17 | node.GridCol("col1").
18 | Span(8).
19 | SetXContent("Col-1"),
20 | node.GridCol("col2").
21 | Span(8).
22 | SetXContent("Col-2"),
23 | node.GridCol("col3").
24 | Span(8).
25 | SetXContent("Col-3"),
26 | ),
27 | node.GridRow("row2").
28 | Gutter(16).
29 | Children(
30 | node.GridCol("col4").
31 | Span(16).
32 | SetXContent("Col-4"),
33 | node.GridCol("col5").
34 | Span(8).
35 | SetXContent("Col-5"),
36 | ),
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arrayitemsmovedown.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ArrayItemsMoveDown(name string) *arrayitemsmovedownBuilder {
9 | return &arrayitemsmovedownBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentArrayItemsMoveDown,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type arrayitemsmovedownBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *arrayitemsmovedownBuilder) AC(f ac.AC) *arrayitemsmovedownBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *arrayitemsmovedownBuilder) Title(title string) *arrayitemsmovedownBuilder {
29 | b.schema.XComponentProps["title"] = title
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arraytablemovedown.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ArrayTableMoveDown(name string) *arraytablemovedownBuilder {
9 | return &arraytablemovedownBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentArrayTableMoveDown,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type arraytablemovedownBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *arraytablemovedownBuilder) AC(f ac.AC) *arraytablemovedownBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *arraytablemovedownBuilder) Title(title string) *arraytablemovedownBuilder {
29 | b.schema.XComponentProps["title"] = title
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/types.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Form } from "@formily/core";
3 | import {
4 | IRecursionFieldProps,
5 | ISchemaFieldProps,
6 | SchemaReactComponents,
7 | } from "@formily/react";
8 |
9 | export interface ISchemaComponentContext {
10 | scope?: any;
11 | components?: SchemaReactComponents;
12 | refresh?: () => void;
13 | reset?: () => void;
14 | SchemaField?: React.FC;
15 | }
16 |
17 | export interface ISchemaComponentProvider {
18 | form?: Form;
19 | scope?: any;
20 | components?: SchemaReactComponents;
21 | }
22 |
23 | export interface IRecursionComponentProps extends IRecursionFieldProps {
24 | scope?: any;
25 | components?: SchemaReactComponents;
26 | }
27 |
28 | export interface ISchemaComponentOptionsProps {
29 | scope?: any;
30 | components?: SchemaReactComponents;
31 | inherit?: boolean;
32 | }
33 |
--------------------------------------------------------------------------------
/li-web/packages/pro-utils/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pro-utils",
3 | "version": "0.0.0",
4 | "main": "./src/index.ts",
5 | "license": "MIT",
6 | "sideEffects": [
7 | "dist/*",
8 | "esm/*.js",
9 | "lib/*.js",
10 | "src/*.ts",
11 | "*.less",
12 | "**/*/style.js"
13 | ],
14 | "devDependencies": {
15 | "@types/lodash": "^4.14.182",
16 | "@types/react": "^18.0.8",
17 | "config": "workspace:*",
18 | "tsconfig": "workspace:*",
19 | "typescript": "^4.6.4"
20 | },
21 | "peerDependencies": {
22 | "@arco-design/web-react": "^2.30.0",
23 | "@types/react-dom": "^18.0.3",
24 | "react-dom": "^18.1.0"
25 | },
26 | "dependencies": {
27 | "ahooks": "^3.3.10",
28 | "axios": "^0.27.2",
29 | "lodash": "^4.17.21",
30 | "nanoid": "^3.3.4",
31 | "react": "^18.1.0"
32 | },
33 | "publishConfig": {
34 | "access": "public"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/sqlx/sqlx.go:
--------------------------------------------------------------------------------
1 | package sqlx
2 |
3 | import (
4 | "strings"
5 |
6 | "entgo.io/ent/dialect"
7 | "entgo.io/ent/dialect/sql"
8 | )
9 |
10 | func ContainsFoldAny(col, substr string) *sql.Predicate {
11 | p := sql.P()
12 | return p.Append(func(b *sql.Builder) {
13 | w, escaped := escape(substr)
14 | switch b.Dialect() {
15 | case dialect.MySQL:
16 | b.WriteString("CONVERT(" + col + " using 'utf8mb4_general_ci') LIKE ")
17 | b.Arg("%" + strings.ToLower(w) + "%")
18 | case dialect.Postgres:
19 | b.WriteString(col + "::text ILIKE ")
20 | b.Arg("%" + strings.ToLower(w) + "%")
21 | default: // SQLite.
22 | var f sql.Func
23 | f.SetDialect(b.Dialect())
24 | f.Lower(col)
25 | b.WriteString(f.String()).WriteString(" LIKE ")
26 | b.Arg("%" + strings.ToLower(w) + "%")
27 | if escaped {
28 | p.WriteString(" ESCAPE ").Arg("\\")
29 | }
30 | }
31 | })
32 | }
33 |
--------------------------------------------------------------------------------
/li-web/apps/admin/config/proxy.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | dev: {
3 | "/api": {
4 | target: "http://localhost:8299/api/",
5 | changeOrigin: true,
6 | rewrite: (path) => path.replace(/^\/api/, ""),
7 | },
8 | "/upload": {
9 | target: "http://localhost:8299/upload/",
10 | changeOrigin: true,
11 | rewrite: (path) => path.replace(/^\/upload/, ""),
12 | },
13 | "/locales": {
14 | target: "http://localhost:8299/locales/",
15 | changeOrigin: true,
16 | rewrite: (path) => path.replace(/^\/locales/, ""),
17 | },
18 | },
19 | test: {
20 | "/api/": {
21 | target: "http://localhost:8299",
22 | changeOrigin: true,
23 | rewrite: { "^/api": "" },
24 | },
25 | },
26 | pre: {
27 | "/api/": {
28 | target: "your pre url",
29 | changeOrigin: true,
30 | rewrite: { "^/api": "" },
31 | },
32 | },
33 | };
34 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arrayitemssorthandle.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ArrayItemsSortHandle(name string) *arrayitemssorthandleBuilder {
9 | return &arrayitemssorthandleBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentArrayItemsSortHandle,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type arrayitemssorthandleBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *arrayitemssorthandleBuilder) AC(f ac.AC) *arrayitemssorthandleBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *arrayitemssorthandleBuilder) Title(title string) *arrayitemssorthandleBuilder {
29 | b.schema.XComponentProps["title"] = title
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arraytablesorthandle.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ArrayTableSortHandle(name string) *arraytablesorthandleBuilder {
9 | return &arraytablesorthandleBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentArrayTableSortHandle,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type arraytablesorthandleBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *arraytablesorthandleBuilder) AC(f ac.AC) *arraytablesorthandleBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *arraytablesorthandleBuilder) Title(title string) *arraytablesorthandleBuilder {
29 | b.schema.XComponentProps["title"] = title
30 | return b
31 | }
32 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/space/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | Divider,
4 | Space as ArcoSpace,
5 | SpaceProps,
6 | } from "@arco-design/web-react";
7 | import { RecursionField, useFieldSchema } from "@formily/react";
8 | import { useFormLayout } from "../form-layout";
9 |
10 | export const Space: React.FC = (props) => {
11 | const fieldSchema = useFieldSchema();
12 | const layout = useFormLayout();
13 | let { split } = props;
14 | if (split === "divider") {
15 | split = ;
16 | }
17 | return (
18 |
19 | {fieldSchema.mapProperties((schema, key) => {
20 | return ;
21 | })}
22 |
23 | );
24 | };
25 |
26 | export default Space;
27 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/locale/en-US.tsx:
--------------------------------------------------------------------------------
1 | import ArcoEnUS from "@arco-design/web-react/es/locale/en-US";
2 | import { Locale } from "./types";
3 |
4 | export const enUS: Locale = {
5 | ...ArcoEnUS,
6 | Chart: {
7 | nodata: "No Data",
8 | },
9 | ColorSelect: {
10 | red: "Red",
11 | orangered: "Orangered",
12 | orange: "Orange",
13 | gold: "Gold",
14 | lime: "Lime",
15 | green: "Green",
16 | cyan: "Cyan",
17 | blue: "Blue",
18 | arcobule: "Arco Blue",
19 | purple: "Purple",
20 | pinkpurple: "Pink Purple",
21 | magenta: "Magenta",
22 | gray: "Gray",
23 | },
24 | List: {
25 | query: "Query",
26 | reset: "Reset",
27 | search: "Search",
28 | confirmDelete: "Are you sure you want to delete?",
29 | },
30 | ListFilter: {
31 | yes: "Yes",
32 | no: "No",
33 | },
34 | RecordPicker: {
35 | drawerTitle: "Please select",
36 | },
37 | };
38 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_tabstabpane.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func TabsTabPane(name string) *tabstabpaneBuilder {
9 | return &tabstabpaneBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentTabsTabPane,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type tabstabpaneBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *tabstabpaneBuilder) AC(f ac.AC) *tabstabpaneBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *tabstabpaneBuilder) Title(title string) *tabstabpaneBuilder {
29 | b.SetTitle(title)
30 | return b
31 | }
32 |
33 | func (b *tabsBuilder) Icon(icon string) *tabsBuilder {
34 | b.schema.XComponentProps["icon"] = icon
35 | return b
36 | }
37 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/predicate/predicate.go:
--------------------------------------------------------------------------------
1 | // Code generated by entc, DO NOT EDIT.
2 |
3 | package predicate
4 |
5 | import (
6 | "entgo.io/ent/dialect/sql"
7 | )
8 |
9 | // FlowDefinition is the predicate function for flowdefinition builders.
10 | type FlowDefinition func(*sql.Selector)
11 |
12 | // FlowDeployment is the predicate function for flowdeployment builders.
13 | type FlowDeployment func(*sql.Selector)
14 |
15 | // FlowInstance is the predicate function for flowinstance builders.
16 | type FlowInstance func(*sql.Selector)
17 |
18 | // FlowInstanceData is the predicate function for flowinstancedata builders.
19 | type FlowInstanceData func(*sql.Selector)
20 |
21 | // FlowNodeInstance is the predicate function for flownodeinstance builders.
22 | type FlowNodeInstance func(*sql.Selector)
23 |
24 | // FlowNodeInstanceLog is the predicate function for flownodeinstancelog builders.
25 | type FlowNodeInstanceLog func(*sql.Selector)
26 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/style/global.less:
--------------------------------------------------------------------------------
1 | @import 'nprogress/nprogress.css';
2 |
3 | html,
4 | body {
5 | width: 100%;
6 | height: 100%;
7 | margin: 0;
8 | padding: 0;
9 | font-size: 14px;
10 | background-color: var(--color-bg-1);
11 | }
12 |
13 | body[arco-theme='dark'] {
14 | .chart-wrapper {
15 | .bizcharts-tooltip {
16 | background: linear-gradient(
17 | 304.17deg,
18 | rgba(90, 92, 95, 0.6) -6.04%,
19 | rgba(87, 87, 87, 0.6) 85.2%
20 | ) !important;
21 | backdrop-filter: blur(10px);
22 | border-radius: 6px;
23 | box-shadow: none !important;
24 | }
25 | }
26 | }
27 |
28 | ::-webkit-scrollbar {
29 | width: 6px;
30 | background-color: transparent;
31 | }
32 |
33 | ::-webkit-scrollbar-thumb {
34 | border-radius: 6px;
35 | box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
36 | }
37 |
38 | ::-webkit-scrollbar-track {
39 | box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
40 | }
41 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_listaction.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | "github.com/gogf/gf/v2/container/gmap"
7 | )
8 |
9 | func ListAction(name string) *listactionBuilder {
10 | return &listactionBuilder{&NodeBuilder{
11 | schema: &ui.Schema{
12 | Name: name,
13 | Type: ui.SchemaTypeVoid,
14 | XComponent: ui.ComponentListAction,
15 | Properties: gmap.NewListMap(),
16 | },
17 | }}
18 | }
19 |
20 | type listactionBuilder struct {
21 | *NodeBuilder
22 | }
23 |
24 | func (b *listactionBuilder) AC(f ac.AC) *listactionBuilder {
25 | b.schema.AC = f
26 | return b
27 | }
28 |
29 | func (b *listactionBuilder) Title(title string) *listactionBuilder {
30 | b.SetTitle(title)
31 | return b
32 | }
33 |
34 | func (b *listactionBuilder) Description(description string) *listactionBuilder {
35 | b.SetDescription(description)
36 | return b
37 | }
38 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pro-components",
3 | "version": "0.0.0",
4 | "main": "./src/index.ts",
5 | "license": "MIT",
6 | "sideEffects": [
7 | "dist/*",
8 | "esm/*.js",
9 | "lib/*.js",
10 | "src/*.ts",
11 | "*.less",
12 | "**/*/style.js"
13 | ],
14 | "scripts": {
15 | "start": "dumi dev",
16 | "lint": "eslint *.tsx"
17 | },
18 | "devDependencies": {
19 | "config": "workspace:*",
20 | "dumi": "^1.1.40",
21 | "tsconfig": "workspace:*",
22 | "typescript": "^4.6.4"
23 | },
24 | "peerDependencies": {
25 | "@arco-design/web-react": "^2.30.0",
26 | "@types/react": "^18.0.8",
27 | "@types/react-dom": "^18.0.3",
28 | "react": "^18.1.0",
29 | "react-dom": "^18.1.0"
30 | },
31 | "dependencies": {
32 | "@logicflow/core": "^1.1.14",
33 | "pro-utils": "workspace:*"
34 | },
35 | "publishConfig": {
36 | "access": "public"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/liflow.go:
--------------------------------------------------------------------------------
1 | package liflow
2 |
3 | import "github.com/BeanWei/li/li-engine/contrib/liflow/ent/schema"
4 |
5 | type (
6 | Executor interface {
7 | Validate(eleMap map[string]*schema.FlowElement, ele *schema.FlowElement) error
8 | Execute(ctx *FlowCtx) error
9 | Commit(ctx *FlowCtx) error
10 | Rollback(ctx *FlowCtx) error
11 | IsCompleted(ctx *FlowCtx) bool
12 | GetExecuteExecutor(ctx *FlowCtx) Executor
13 | GetRollbackExecutor(ctx *FlowCtx) (Executor, error)
14 | }
15 | )
16 |
17 | type (
18 | RegisterExecutorInput struct {
19 | ElementType string
20 | ElementExecutor Executor
21 | }
22 | )
23 |
24 | var (
25 | executorMap = make(map[string]Executor)
26 | )
27 |
28 | func RegisterExecutor(eles ...*RegisterExecutorInput) {
29 | for _, ele := range eles {
30 | executorMap[ele.ElementType] = ele.ElementExecutor
31 | }
32 | }
33 |
34 | func GetElementExecutor(name string) Executor {
35 | return executorMap[name]
36 | }
37 |
--------------------------------------------------------------------------------
/li-engine/controller/internal/reflection/reflection.go:
--------------------------------------------------------------------------------
1 | package reflection
2 |
3 | import "reflect"
4 |
5 | func ValueToInterface(v reflect.Value) (value interface{}, ok bool) {
6 | if v.IsValid() && v.CanInterface() {
7 | return v.Interface(), true
8 | }
9 | switch v.Kind() {
10 | case reflect.Bool:
11 | return v.Bool(), true
12 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
13 | return v.Int(), true
14 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
15 | return v.Uint(), true
16 | case reflect.Float32, reflect.Float64:
17 | return v.Float(), true
18 | case reflect.Complex64, reflect.Complex128:
19 | return v.Complex(), true
20 | case reflect.String:
21 | return v.String(), true
22 | case reflect.Ptr:
23 | return ValueToInterface(v.Elem())
24 | case reflect.Interface:
25 | return ValueToInterface(v.Elem())
26 | default:
27 | return nil, false
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/template.go:
--------------------------------------------------------------------------------
1 | package lient
2 |
3 | import (
4 | "embed"
5 | "strings"
6 | "text/template"
7 |
8 | "entgo.io/ent/entc/gen"
9 | "github.com/gogf/gf/v2/text/gstr"
10 | "github.com/gogf/gf/v2/util/gconv"
11 | "github.com/hexops/valast"
12 | )
13 |
14 | var (
15 | //go:embed template
16 | templateDir embed.FS
17 | FuncMap = template.FuncMap{
18 | "valast": valast.String,
19 | "title": title,
20 | "contains": contains,
21 | "listfield": listfield,
22 | "joinx": gstr.JoinAny,
23 | }
24 | Templates = gen.MustParse(gen.NewTemplate("lient").Funcs(FuncMap).ParseFS(templateDir, "template/*tmpl"))
25 | )
26 |
27 | func title(s string) string {
28 | return strings.Title(gstr.Join(gstr.SplitAndTrim(gstr.CaseSnake(s), "_"), " "))
29 | }
30 |
31 | func contains(s1 interface{}, s2 string) bool {
32 | return gstr.Contains(gconv.String(s1), s2)
33 | }
34 |
35 | func listfield(fields ...*gen.Field) []*gen.Field {
36 | return fields
37 | }
38 |
--------------------------------------------------------------------------------
/li-web/packages/tsconfig/base.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "Default",
4 | "compilerOptions": {
5 | "lib": [
6 | "dom",
7 | "dom.iterable",
8 | "esnext"
9 | ],
10 | "composite": false,
11 | "declaration": true,
12 | "declarationMap": true,
13 | "esModuleInterop": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "inlineSources": false,
16 | "isolatedModules": true,
17 | "moduleResolution": "node",
18 | "noUnusedLocals": false,
19 | "noUnusedParameters": false,
20 | "preserveWatchOutput": true,
21 | "skipLibCheck": true,
22 | "strict": true,
23 | "target": "es5",
24 | "allowJs": true,
25 | "allowSyntheticDefaultImports": true,
26 | "noFallthroughCasesInSwitch": true,
27 | "module": "esnext",
28 | "resolveJsonModule": true,
29 | "noEmit": true,
30 | "jsx": "react-jsx"
31 | },
32 | "exclude": ["node_modules"]
33 | }
34 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/processor/processor.go:
--------------------------------------------------------------------------------
1 | package processor
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/contrib/liflow"
5 | "github.com/BeanWei/li/li-engine/contrib/liflow/executor"
6 | )
7 |
8 | func init() {
9 | liflow.RegisterExecutor(
10 | &liflow.RegisterExecutorInput{
11 | ElementType: "StartEvent",
12 | ElementExecutor: new(executor.StartEventExecutor),
13 | },
14 | &liflow.RegisterExecutorInput{
15 | ElementType: "EndEvent",
16 | ElementExecutor: new(executor.EndEventExecutor),
17 | },
18 | &liflow.RegisterExecutorInput{
19 | ElementType: "SequenceFlow",
20 | ElementExecutor: new(executor.SequenceFlowExecutor),
21 | },
22 | &liflow.RegisterExecutorInput{
23 | ElementType: "UserTask",
24 | ElementExecutor: new(executor.UserTaskExecutor),
25 | },
26 | &liflow.RegisterExecutorInput{
27 | ElementType: "ExclusiveGateway",
28 | ElementExecutor: new(executor.ExclusiveGatewayExecutor),
29 | },
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_dropdownmenuurl.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func DropdownMenuURL(name string) *dropdownmenuurlBuilder {
9 | return &dropdownmenuurlBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentDropdownMenuSubMenu,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type dropdownmenuurlBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *dropdownmenuurlBuilder) AC(f ac.AC) *dropdownmenuurlBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *dropdownmenuurlBuilder) Title(title string) *dropdownmenuurlBuilder {
29 | b.SetTitle(title)
30 | return b
31 | }
32 |
33 | func (b *dropdownmenuurlBuilder) Href(href string) *dropdownmenuurlBuilder {
34 | b.schema.XComponentProps["href"] = href
35 | return b
36 | }
37 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/record-provider/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { createContext, useContext } from "react";
2 |
3 | export const RecordContext = createContext({});
4 | export const RecordIndexContext = createContext(null);
5 |
6 | export const RecordProvider: React.FC<
7 | React.PropsWithChildren<{ record: any }>
8 | > = (props) => {
9 | const { record, children } = props;
10 | return (
11 | {children}
12 | );
13 | };
14 |
15 | export const RecordIndexProvider: React.FC<
16 | React.PropsWithChildren<{ index: any }>
17 | > = (props) => {
18 | const { index, children } = props;
19 | return (
20 |
21 | {children}
22 |
23 | );
24 | };
25 |
26 | export function useRecord() {
27 | return useContext(RecordContext) as D;
28 | }
29 |
30 | export function useRecordIndex() {
31 | return useContext(RecordIndexContext);
32 | }
33 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/executor/start_event.go:
--------------------------------------------------------------------------------
1 | package executor
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/contrib/liflow"
5 | "github.com/BeanWei/li/li-engine/contrib/liflow/ent/schema"
6 | "github.com/gogf/gf/v2/errors/gerror"
7 | )
8 |
9 | type StartEventExecutor struct {
10 | ElementExecutor
11 | }
12 |
13 | func (e *StartEventExecutor) Validate(eleMap map[string]*schema.FlowElement, ele *schema.FlowElement) error {
14 | if len(ele.Incoming) > 0 {
15 | return gerror.NewCode(liflow.ErrCodeElementTooMuchIncoming)
16 | }
17 | return nil
18 | }
19 |
20 | func (e *StartEventExecutor) Execute(ctx *liflow.FlowCtx) error {
21 | ctx.CurrentNodeInstance.Status = liflow.FlowNodeInstanceStatusCompleted
22 | ctx.NodeInstanceList = append(ctx.NodeInstanceList, *ctx.CurrentNodeInstance)
23 | return nil
24 | }
25 |
26 | func (e *StartEventExecutor) Rollback(ctx *liflow.FlowCtx) error {
27 | ctx.CurrentNodeInstance = ctx.SuspendNodeInstance
28 | ctx.NodeInstanceList = nil
29 | return nil
30 | }
31 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_listcard.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | "github.com/gogf/gf/v2/container/gmap"
7 | )
8 |
9 | func ListCard(name string) *listcardBuilder {
10 | return &listcardBuilder{&NodeBuilder{
11 | schema: &ui.Schema{
12 | Name: name,
13 | Type: ui.SchemaTypeVoid,
14 | XComponent: ui.ComponentListCard,
15 | XComponentProps: make(map[string]interface{}),
16 | Properties: gmap.NewListMap(),
17 | },
18 | }}
19 | }
20 |
21 | type listcardBuilder struct {
22 | *NodeBuilder
23 | }
24 |
25 | func (b *listcardBuilder) AC(f ac.AC) *listcardBuilder {
26 | b.schema.AC = f
27 | return b
28 | }
29 |
30 | func (b *listcardBuilder) Title(title string) *listcardBuilder {
31 | b.SetTitle(title)
32 | return b
33 | }
34 |
35 | func (b *listcardBuilder) Description(description string) *listcardBuilder {
36 | b.SetDescription(description)
37 | return b
38 | }
39 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/core/RecordProvider.tsx:
--------------------------------------------------------------------------------
1 | import React, { createContext, useContext } from "react";
2 |
3 | export const RecordContext = createContext({});
4 | export const RecordIndexContext = createContext(null);
5 |
6 | export const RecordProvider: React.FC<
7 | React.PropsWithChildren<{ record: any }>
8 | > = (props) => {
9 | const { record, children } = props;
10 | return (
11 | {children}
12 | );
13 | };
14 |
15 | export const RecordIndexProvider: React.FC<
16 | React.PropsWithChildren<{ index: any }>
17 | > = (props) => {
18 | const { index, children } = props;
19 | return (
20 |
21 | {children}
22 |
23 | );
24 | };
25 |
26 | export function useRecord() {
27 | return useContext(RecordContext) as D;
28 | }
29 |
30 | export function useRecordIndex() {
31 | return useContext(RecordIndexContext);
32 | }
33 |
--------------------------------------------------------------------------------
/li-app/internal/shared/context.go:
--------------------------------------------------------------------------------
1 | package shared
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/gogf/gf/v2/net/ghttp"
7 | )
8 |
9 | // 上下文管理服务
10 | var Ctx = new(ctxShared)
11 |
12 | type ctxShared struct{}
13 |
14 | // CtxSrvKey 上下文变量存储键名
15 | const ContextKey = "CtxSvcKey"
16 |
17 | // Context 请求上下文结构
18 | type Context struct {
19 | Session *ghttp.Session // session
20 | User *CtxUser // 上下文用户信息
21 | }
22 |
23 | // Init 初始化上下文对象指针到上下文对象中,以便后续的请求流程中可以修改。
24 | func (s *ctxShared) Init(r *ghttp.Request, customCtx *Context) {
25 | r.SetCtxVar(ContextKey, customCtx)
26 | }
27 |
28 | // Get 获得上下文变量
29 | func (s *ctxShared) Get(ctx context.Context) *Context {
30 | value := ctx.Value(ContextKey)
31 | if value == nil {
32 | return &Context{}
33 | }
34 | if localCtx, ok := value.(*Context); ok {
35 | return localCtx
36 | }
37 | return &Context{}
38 | }
39 |
40 | // SetUser 设定上下文用户信息
41 | func (s *ctxShared) SetUser(ctx context.Context, ctxUser *CtxUser) {
42 | s.Get(ctx).User = ctxUser
43 | }
44 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/mixin/id_mixin.go:
--------------------------------------------------------------------------------
1 | package mixin
2 |
3 | import (
4 | "entgo.io/ent"
5 | "entgo.io/ent/schema/field"
6 | "entgo.io/ent/schema/mixin"
7 | "github.com/BeanWei/li/li-engine/contrib/lient"
8 | )
9 |
10 | type ID struct {
11 | mixin.Schema
12 | }
13 |
14 | func (ID) Fields() []ent.Field {
15 | return []ent.Field{
16 | field.Int64("id").
17 | Unique().
18 | Immutable().
19 | DefaultFunc(func() int64 {
20 | return lient.NewID()
21 | }).
22 | Annotations(lient.Annotation{
23 | DisableCreate: true,
24 | }),
25 | }
26 | }
27 |
28 | type XID struct {
29 | mixin.Schema
30 | }
31 |
32 | func (XID) Fields() []ent.Field {
33 | return []ent.Field{
34 | field.String("id").
35 | NotEmpty().
36 | Unique().
37 | Immutable().
38 | DefaultFunc(func() string {
39 | return lient.NewXid()
40 | }).
41 | Annotations(lient.Annotation{
42 | DisableCreate: true,
43 | }),
44 | }
45 | }
46 |
47 | var _ ent.Mixin = (*ID)(nil)
48 | var _ ent.Mixin = (*XID)(nil)
49 |
--------------------------------------------------------------------------------
/li-app/config/config.dev.yaml:
--------------------------------------------------------------------------------
1 | # HTTP Server.
2 | server:
3 | address: ":8199"
4 | serverRoot: "resource/public"
5 | serverAgent: "li"
6 | sessionIdName: "x-api-sid"
7 |
8 | # Global logging.
9 | logger:
10 | level: "all"
11 | stdout: true
12 |
13 | # Database.
14 | database:
15 | logger:
16 | level: "all"
17 | stdout: true
18 | default:
19 | link: "postgres://root:1234567890@127.0.0.1:5432/li-app?sslmode=disable"
20 | type: "pgsql"
21 | debug: true
22 |
23 | # Redis.
24 | redis:
25 | cache:
26 | address: 127.0.0.1:6379
27 | db: 0
28 | pass: 123456
29 | idleTimeout: 600
30 | default:
31 | address: 127.0.0.1:6379
32 | db: 0
33 | pass: 123456
34 | idleTimeout: 600
35 |
36 | # OSS.
37 | file:
38 | default:
39 | adapter: "local"
40 | local:
41 | dir: "./tmp/upload"
42 | aws: # 兼容 minio
43 | accessKeyID: ""
44 | secretAccessKey: ""
45 | endpoint: "" # for minio
46 | region: ""
47 | disableSSL: true
48 | forcePathStyle: true
49 |
--------------------------------------------------------------------------------
/li-app/internal/data/ent/schema/tag.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | import (
4 | "entgo.io/ent"
5 | "entgo.io/ent/schema/edge"
6 | "entgo.io/ent/schema/field"
7 | "github.com/BeanWei/li/li-engine/contrib/lient"
8 | "github.com/BeanWei/li/li-engine/contrib/lient/mixin"
9 | "github.com/BeanWei/li/li-engine/view/node"
10 | )
11 |
12 | type Tag struct {
13 | ent.Schema
14 | }
15 |
16 | func (Tag) Mixin() []ent.Mixin {
17 | return []ent.Mixin{
18 | mixin.XID{},
19 | mixin.Time{},
20 | }
21 | }
22 |
23 | func (Tag) Fields() []ent.Field {
24 | return []ent.Field{
25 | field.String("label").
26 | NotEmpty().
27 | Annotations(
28 | lient.Annotation{
29 | ViewSchema: node.Text("label").Title("标签").SetRequired(true).Schema(),
30 | ColumnProps: &lient.ColumnProps{
31 | Filterable: true,
32 | },
33 | Queryable: true,
34 | },
35 | ),
36 | }
37 | }
38 |
39 | func (Tag) Edges() []ent.Edge {
40 | return []ent.Edge{
41 | edge.From("posts", Post.Type).
42 | Ref("tags"),
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/li-app/internal/middleware/auth.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/app/admin/controller"
5 | "github.com/BeanWei/li/li-app/internal/shared"
6 | engine "github.com/BeanWei/li/li-engine"
7 | "github.com/gogf/gf/v2/errors/gcode"
8 | "github.com/gogf/gf/v2/net/ghttp"
9 | )
10 |
11 | // Authentication 登录验证
12 | func Authentication(r *ghttp.Request) {
13 | if r.URL.Path == "/api/liql" {
14 | operation := r.GetForm("operation").String()
15 | if operation == controller.OperationUserSignIn ||
16 | operation == engine.OperationGetAppConfig ||
17 | operation == engine.OperationGetSignView {
18 | r.Middleware.Next()
19 | } else {
20 | ctxUser := shared.Ctx.Get(r.Context()).User
21 | if ctxUser == nil {
22 | r.Response.WriteJson(ghttp.DefaultHandlerResponse{
23 | Code: gcode.CodeNotAuthorized.Code(),
24 | Message: "请登录",
25 | })
26 | } else {
27 | r.Middleware.Next()
28 | }
29 | }
30 | } else {
31 | r.Middleware.Next()
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_checkbox.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func Checkbox(name string) *checkboxBuilder {
9 | return &checkboxBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeBool,
13 | XComponent: ui.ComponentCheckbox,
14 | XDecorator: ui.DecoratorFormItem,
15 | },
16 | }}
17 | }
18 |
19 | type checkboxBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *checkboxBuilder) AC(f ac.AC) *checkboxBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *checkboxBuilder) Title(title string) *checkboxBuilder {
29 | b.SetTitle(title)
30 | return b
31 | }
32 |
33 | func (b *checkboxBuilder) Description(description string) *checkboxBuilder {
34 | b.SetDescription(description)
35 | return b
36 | }
37 |
38 | func (b *checkboxBuilder) Default(value interface{}) *checkboxBuilder {
39 | b.schema.Default = value
40 | return b
41 | }
42 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/internal/ent/schema/tag.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | import (
4 | "entgo.io/ent"
5 | "entgo.io/ent/schema/edge"
6 | "entgo.io/ent/schema/field"
7 | "github.com/BeanWei/li/li-engine/contrib/lient"
8 | "github.com/BeanWei/li/li-engine/contrib/lient/mixin"
9 | "github.com/BeanWei/li/li-engine/view/node"
10 | )
11 |
12 | type Tag struct {
13 | ent.Schema
14 | }
15 |
16 | func (Tag) Mixin() []ent.Mixin {
17 | return []ent.Mixin{
18 | mixin.XID{},
19 | mixin.Time{},
20 | }
21 | }
22 |
23 | func (Tag) Fields() []ent.Field {
24 | return []ent.Field{
25 | field.String("label").
26 | NotEmpty().
27 | Annotations(
28 | lient.Annotation{
29 | ViewSchema: node.Text("label").Title("标签").SetRequired(true).Schema(),
30 | ColumnProps: &lient.ColumnProps{
31 | Filterable: true,
32 | },
33 | Queryable: true,
34 | },
35 | ),
36 | }
37 | }
38 |
39 | func (Tag) Edges() []ent.Edge {
40 | return []ent.Edge{
41 | edge.From("posts", Post.Type).
42 | Ref("tags"),
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/context.go:
--------------------------------------------------------------------------------
1 | // Code generated by entc, DO NOT EDIT.
2 |
3 | package ent
4 |
5 | import (
6 | "context"
7 | )
8 |
9 | type clientCtxKey struct{}
10 |
11 | // FromContext returns a Client stored inside a context, or nil if there isn't one.
12 | func FromContext(ctx context.Context) *Client {
13 | c, _ := ctx.Value(clientCtxKey{}).(*Client)
14 | return c
15 | }
16 |
17 | // NewContext returns a new context with the given Client attached.
18 | func NewContext(parent context.Context, c *Client) context.Context {
19 | return context.WithValue(parent, clientCtxKey{}, c)
20 | }
21 |
22 | type txCtxKey struct{}
23 |
24 | // TxFromContext returns a Tx stored inside a context, or nil if there isn't one.
25 | func TxFromContext(ctx context.Context) *Tx {
26 | tx, _ := ctx.Value(txCtxKey{}).(*Tx)
27 | return tx
28 | }
29 |
30 | // NewTxContext returns a new context with the given Tx attached.
31 | func NewTxContext(parent context.Context, tx *Tx) context.Context {
32 | return context.WithValue(parent, txCtxKey{}, tx)
33 | }
34 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/async-data-provider/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { createContext, useContext } from "react";
2 | import { useRequest } from "pro-utils";
3 |
4 | export const AsyncDataContext = createContext({});
5 |
6 | export interface AsyncDataProviderProps {
7 | value?: any;
8 | request?: any;
9 | uid?: string;
10 | onSuccess?: (data: any, params: any) => void;
11 | }
12 |
13 | export const AsyncDataProvider: React.FC<
14 | React.PropsWithChildren
15 | > = (props) => {
16 | const { value, request, children, ...others } = props;
17 | if (value) {
18 | return (
19 |
20 | {children}
21 |
22 | );
23 | }
24 | const result = useRequest(request, { ...others });
25 | return (
26 |
27 | {children}
28 |
29 | );
30 | };
31 |
32 | export const useAsyncData = () => {
33 | return useContext(AsyncDataContext);
34 | };
35 |
--------------------------------------------------------------------------------
/li-app/internal/middleware/ctx.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/data"
5 | "github.com/BeanWei/li/li-app/internal/shared"
6 | "github.com/gogf/gf/v2/container/garray"
7 | "github.com/gogf/gf/v2/errors/gerror"
8 | "github.com/gogf/gf/v2/net/ghttp"
9 | )
10 |
11 | // Ctx 自定义上下文变量
12 | func Ctx(r *ghttp.Request) {
13 | customCtx := &shared.Context{
14 | Session: r.Session,
15 | }
16 | shared.Ctx.Init(r, customCtx)
17 | uid := shared.Session.GetUserID(r.Context())
18 | if uid != "" {
19 | usr, err := data.User.GetUser(r.Context(), uid)
20 | if err != nil {
21 | r.Response.WriteJson(ghttp.DefaultHandlerResponse{
22 | Code: gerror.Code(err).Code(),
23 | Message: err.Error(),
24 | })
25 | } else {
26 | if usr != nil {
27 | customCtx.User = &shared.CtxUser{
28 | ID: usr.ID,
29 | IsAdmin: usr.IsAdmin,
30 | Roles: garray.NewStrArrayFrom(usr.Roles),
31 | }
32 | }
33 | r.Middleware.Next()
34 | }
35 | } else {
36 | r.Middleware.Next()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/li-flow/nodes/SequenceFlow.ts:
--------------------------------------------------------------------------------
1 | import { PolylineEdge, PolylineEdgeModel } from "@logicflow/core";
2 | import { eletype } from "../config";
3 |
4 | class SequenceFlowModel extends PolylineEdgeModel {
5 | static extendKey = "SequenceFlowModel";
6 | getEdgeStyle() {
7 | const style = super.getEdgeStyle();
8 | // svg属性
9 | style.strokeWidth = 1;
10 | style.stroke = "#ababac";
11 | return style;
12 | }
13 | /**
14 | * 重写此方法,使保存数据是能带上锚点数据。
15 | */
16 | // getData() {
17 | // const data = super.getData();
18 | // data.sourceAnchorId = this.sourceAnchorId;
19 | // data.targetAnchorId = this.targetAnchorId;
20 | // return data;
21 | // }
22 | }
23 |
24 | class SequenceFlowView extends PolylineEdge {
25 | static extendKey = "SequenceFlowEdge";
26 | }
27 |
28 | const SequenceFlow = {
29 | type: eletype.sequenceflow,
30 | view: SequenceFlowView,
31 | model: SequenceFlowModel,
32 | };
33 |
34 | export { SequenceFlowView, SequenceFlowModel };
35 | export default SequenceFlow;
36 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_colorselect.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ColorSelect(name string) *colorselectBuilder {
9 | return &colorselectBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeString,
13 | XComponent: ui.ComponentColorSelect,
14 | XDecorator: ui.DecoratorFormItem,
15 | },
16 | }}
17 | }
18 |
19 | type colorselectBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *colorselectBuilder) AC(f ac.AC) *colorselectBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *colorselectBuilder) Title(title string) *colorselectBuilder {
29 | b.SetTitle(title)
30 | return b
31 | }
32 |
33 | func (b *colorselectBuilder) Description(description string) *colorselectBuilder {
34 | b.SetDescription(description)
35 | return b
36 | }
37 |
38 | func (b *colorselectBuilder) Default(value interface{}) *colorselectBuilder {
39 | b.schema.Default = value
40 | return b
41 | }
42 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/driver/helper.go:
--------------------------------------------------------------------------------
1 | package driver
2 |
3 | import (
4 | gosql "database/sql"
5 |
6 | "entgo.io/ent/dialect"
7 | "entgo.io/ent/dialect/sql"
8 | "github.com/gogf/gf/v2/errors/gerror"
9 | "github.com/gogf/gf/v2/frame/g"
10 | )
11 |
12 | func getDriver(master bool, name ...string) (drv *sql.Driver, err error) {
13 | var sqlDB *gosql.DB
14 | if master {
15 | sqlDB, err = g.DB(name...).Master()
16 | } else {
17 | sqlDB, err = g.DB(name...).Slave()
18 | }
19 | if err != nil {
20 | return nil, err
21 | }
22 | if sqlDB == nil {
23 | return nil, gerror.New("failed to connect master/slave db")
24 | }
25 |
26 | driver := g.DB(name...).GetConfig().Type
27 | if driver == "pgsql" {
28 | driver = dialect.Postgres
29 | }
30 |
31 | drv = sql.OpenDB(driver, sqlDB)
32 | return
33 | }
34 |
35 | // Master 主数据库驱动
36 | func Master(name ...string) (drv *sql.Driver, err error) {
37 | return getDriver(true, name...)
38 | }
39 |
40 | // Slave 从数据库驱动
41 | func Slave(name ...string) (drv *sql.Driver, err error) {
42 | return getDriver(false, name...)
43 | }
44 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_divider.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func Divider(name string) *dividerBuilder {
9 | return ÷rBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentDivider,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type dividerBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *dividerBuilder) AC(f ac.AC) *dividerBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *dividerBuilder) Type(typ string) *dividerBuilder {
29 | b.schema.XComponentProps["type"] = typ
30 | return b
31 | }
32 |
33 | func (b *dividerBuilder) Orientation(orientation string) *dividerBuilder {
34 | b.schema.XComponentProps["orientation"] = orientation
35 | return b
36 | }
37 |
38 | func (b *dividerBuilder) Style(style map[string]interface{}) *dividerBuilder {
39 | b.schema.XComponentProps["style"] = style
40 | return b
41 | }
42 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/time-picker/index.tsx:
--------------------------------------------------------------------------------
1 | import { connect, mapReadPretty } from "@formily/react";
2 | import { TimePicker as ArcoTimePicker } from "@arco-design/web-react";
3 | import {
4 | TimePickerProps as ArcoTimePickerProps,
5 | TimeRangePickerProps,
6 | } from "@arco-design/web-react";
7 | import { isArr } from "@formily/shared";
8 |
9 | type ComposedTimePicker = React.FC & {
10 | RangePicker?: React.FC;
11 | };
12 |
13 | const ReadPretty: React.FC = (props: any) => {
14 | const getLabels = () => {
15 | return isArr(props.value) ? props.value.join("~") : props.value;
16 | };
17 | return (
18 |
19 | {getLabels()}
20 |
21 | );
22 | };
23 |
24 | export const TimePicker: ComposedTimePicker = connect(
25 | ArcoTimePicker,
26 | mapReadPretty(ReadPretty)
27 | );
28 |
29 | TimePicker.RangePicker = connect(
30 | ArcoTimePicker.RangePicker,
31 | mapReadPretty(ReadPretty)
32 | );
33 |
34 | export default TimePicker;
35 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/executor/end_event.go:
--------------------------------------------------------------------------------
1 | package executor
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/contrib/liflow"
5 | "github.com/BeanWei/li/li-engine/contrib/liflow/ent/schema"
6 | "github.com/gogf/gf/v2/errors/gerror"
7 | )
8 |
9 | type EndEventExecutor struct {
10 | ElementExecutor
11 | }
12 |
13 | func (e *EndEventExecutor) Validate(eleMap map[string]*schema.FlowElement, ele *schema.FlowElement) error {
14 | if len(ele.Outgoing) > 0 {
15 | return gerror.NewCode(liflow.ErrCodeElementTooMuchOutgoing)
16 | }
17 | return nil
18 | }
19 |
20 | func (e *EndEventExecutor) Execute(ctx *liflow.FlowCtx) error {
21 | ctx.CurrentNodeInstance.Status = liflow.FlowNodeInstanceStatusCompleted
22 | ctx.NodeInstanceList = append(ctx.NodeInstanceList, *ctx.CurrentNodeInstance)
23 | return nil
24 | }
25 |
26 | func (e *EndEventExecutor) Rollback(ctx *liflow.FlowCtx) error {
27 | ctx.CurrentNodeInstance = ctx.SuspendNodeInstance
28 | ctx.NodeInstanceList = nil
29 | return nil
30 | }
31 |
32 | func (e *EndEventExecutor) GetExecuteExecutor(ctx *liflow.FlowCtx) liflow.Executor {
33 | return nil
34 | }
35 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/db.go:
--------------------------------------------------------------------------------
1 | // Code generated by entc, DO NOT EDIT.
2 |
3 | package ent
4 |
5 | import (
6 | "context"
7 | "sync"
8 |
9 | "github.com/BeanWei/li/li-engine/contrib/lient/driver"
10 | "github.com/gogf/gf/v2/frame/g"
11 | "github.com/gogf/gf/v2/os/gctx"
12 | "github.com/gogf/gf/v2/util/gmode"
13 | )
14 |
15 | var (
16 | dbclient *Client
17 | dbclientOnce sync.Once
18 | )
19 |
20 | func DB() *Client {
21 | dbclientOnce.Do(func() {
22 | drv, err := driver.NewDriver()
23 | if err != nil {
24 | g.Log().Fatalf(gctx.New(), "[LiEnt Client] - failed init: %+v", err)
25 | }
26 |
27 | if gmode.IsDevelop() {
28 | dbclient = NewClient(Driver(drv)).Debug()
29 | } else {
30 | dbclient = NewClient(Driver(drv))
31 | }
32 |
33 | dbclient.Use(func(next Mutator) Mutator {
34 | return MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
35 | v, err := next.Mutate(ctx, m)
36 | if err != nil {
37 | g.DB().GetLogger().Error(ctx, err.Error())
38 | return nil, err
39 | }
40 | return v, nil
41 | })
42 | })
43 | })
44 | return dbclient
45 | }
46 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_gridcol.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | "github.com/gogf/gf/v2/container/gmap"
7 | )
8 |
9 | func GridCol(name string) *gridcolBuilder {
10 | return &gridcolBuilder{&NodeBuilder{
11 | schema: &ui.Schema{
12 | Name: name,
13 | Type: ui.SchemaTypeVoid,
14 | XComponent: ui.ComponentGridCol,
15 | XComponentProps: make(map[string]interface{}),
16 | Properties: gmap.NewListMap(),
17 | },
18 | }}
19 | }
20 |
21 | type gridcolBuilder struct {
22 | *NodeBuilder
23 | }
24 |
25 | func (b *gridcolBuilder) AC(f ac.AC) *gridcolBuilder {
26 | b.schema.AC = f
27 | return b
28 | }
29 |
30 | // https://arco.design/react/components/grid#api
31 |
32 | // Span 栅格占位格数
33 | func (b *gridcolBuilder) Span(span int) *gridcolBuilder {
34 | b.schema.XComponentProps["span"] = span
35 | return b
36 | }
37 |
38 | // Offset 栅格左侧的间隔格数,间隔内不可以有栅格
39 | func (b *gridcolBuilder) Offset(offset int) *gridcolBuilder {
40 | b.schema.XComponentProps["offset"] = offset
41 | return b
42 | }
43 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/enthook.go:
--------------------------------------------------------------------------------
1 | package liflow
2 |
3 | import (
4 | "context"
5 | "fmt"
6 |
7 | "github.com/BeanWei/li/li-engine/contrib/liflow/ent"
8 | "github.com/BeanWei/li/li-engine/contrib/liflow/ent/hook"
9 | )
10 |
11 | func init() {
12 | ent.DB().FlowDeployment.Use(
13 | hook.On(
14 | func(next ent.Mutator) ent.Mutator {
15 | return hook.FlowDeploymentFunc(func(ctx context.Context, m *ent.FlowDeploymentMutation) (ent.Value, error) {
16 | if flowModel, exists := m.Model(); exists {
17 | flowElementMap := flowModel.ElementMap()
18 | for _, ele := range flowModel {
19 | if ele == nil {
20 | return nil, fmt.Errorf("flow element cannot be empty")
21 | }
22 | if executor := executorMap[ele.Type]; executor != nil {
23 | if err := executor.Validate(flowElementMap, ele); err != nil {
24 | return nil, err
25 | }
26 | } else {
27 | return nil, fmt.Errorf("flow element type %s not register executor", ele.Type)
28 | }
29 | }
30 | }
31 | return next.Mutate(ctx, m)
32 | })
33 | },
34 | ent.OpCreate|ent.OpUpdateOne,
35 | ),
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/template/db.tmpl:
--------------------------------------------------------------------------------
1 | {{/* gotype: entgo.io/ent/entc/gen.Type */}}
2 |
3 | {{ define "db" }}
4 | {{ template "header" $ }}
5 | import (
6 | "context"
7 | "sync"
8 |
9 | "github.com/BeanWei/li/li-engine/contrib/lient/driver"
10 | "github.com/gogf/gf/v2/frame/g"
11 | "github.com/gogf/gf/v2/os/gctx"
12 | "github.com/gogf/gf/v2/util/gmode"
13 | )
14 |
15 | var (
16 | dbclient *Client
17 | dbclientOnce sync.Once
18 | )
19 |
20 | func DB() *Client {
21 | dbclientOnce.Do(func() {
22 | drv, err := driver.NewDriver()
23 | if err != nil {
24 | g.Log().Fatalf(gctx.New(), "[LiEnt Client] - failed init: %+v", err)
25 | }
26 |
27 | if gmode.IsDevelop() {
28 | dbclient = NewClient(Driver(drv)).Debug()
29 | } else {
30 | dbclient = NewClient(Driver(drv))
31 | }
32 |
33 | dbclient.Use(func(next Mutator) Mutator {
34 | return MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
35 | v, err := next.Mutate(ctx, m)
36 | if err != nil {
37 | g.DB().GetLogger().Error(ctx, err.Error())
38 | return nil, err
39 | }
40 | return v, nil
41 | })
42 | })
43 | })
44 | return dbclient
45 | }
46 | {{ end }}
--------------------------------------------------------------------------------
/li-engine/controller/file_preview.go:
--------------------------------------------------------------------------------
1 | package controller
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/contrib/lifile"
5 | "github.com/BeanWei/li/li-engine/service"
6 | "github.com/gogf/gf/v2/errors/gcode"
7 | "github.com/gogf/gf/v2/errors/gerror"
8 | "github.com/gogf/gf/v2/net/ghttp"
9 | )
10 |
11 | type FilePreviewReq struct {
12 | BucketName string `json:"bucket_name" p:"bucket_name" v:"required"`
13 | FileName string `json:"file_name" p:"file_name" v:"required"`
14 | }
15 |
16 | func FilePreviw(r *ghttp.Request) {
17 | var req *FilePreviewReq
18 | if err := r.Parse(&req); err != nil {
19 | code := gerror.Code(err)
20 | r.Response.WriteJson(ghttp.DefaultHandlerResponse{
21 | Code: code.Code(),
22 | Message: err.Error(),
23 | })
24 | return
25 | }
26 | client, err := service.NewFileClient(r.Context())
27 | if err != nil {
28 | r.Response.WriteJson(ghttp.DefaultHandlerResponse{
29 | Code: gcode.CodeInternalError.Code(),
30 | Message: gcode.CodeInternalError.Message(),
31 | })
32 | return
33 | }
34 | client.ServeFile(r, &lifile.ProxyInput{
35 | BucketName: req.BucketName,
36 | FileName: req.FileName,
37 | })
38 | }
39 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_listactionsearch.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func ListActionSearch(name string) *listactionsearchBuilder {
9 | return &listactionsearchBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentListActionSearch,
14 | },
15 | }}
16 | }
17 |
18 | type listactionsearchBuilder struct {
19 | *NodeBuilder
20 | }
21 |
22 | func (b *listactionsearchBuilder) AC(f ac.AC) *listactionsearchBuilder {
23 | b.schema.AC = f
24 | return b
25 | }
26 |
27 | func (b *listactionsearchBuilder) Style(style map[string]interface{}) *listactionsearchBuilder {
28 | b.schema.XComponentProps["style"] = style
29 | return b
30 | }
31 |
32 | func (b *listactionsearchBuilder) Placeholder(placeholder string) *listactionsearchBuilder {
33 | b.schema.XComponentProps["placeholder"] = placeholder
34 | return b
35 | }
36 |
37 | func (b *listactionsearchBuilder) Position(position string) *listactionsearchBuilder {
38 | b.schema.XComponentProps["position"] = position
39 | return b
40 | }
41 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/action/types.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { ButtonProps } from "@arco-design/web-react";
3 | import { IFormLayoutProps } from "../form-layout";
4 | import { IModalProps } from "../form-modal";
5 | import { IDrawerProps } from "../form-drawer";
6 |
7 | export type ComposedAction = React.FC & {
8 | FormDrawer?: React.FC;
9 | FormModal?: React.FC;
10 | };
11 |
12 | export type ActionFormDrawerProps = ButtonProps & {
13 | initialValues?: Record;
14 | forInit?: string;
15 | forInitVariables?: Record;
16 | forSubmitSuccess?: (payload: any) => void;
17 | isMenuItem?: boolean;
18 | actionText?: string | React.ReactNode;
19 | drawerProps?: IDrawerProps;
20 | layoutProps?: IFormLayoutProps;
21 | };
22 |
23 | export type ActionFormModalProps = ButtonProps & {
24 | initialValues?: Record;
25 | forInit?: string;
26 | forInitVariables?: Record;
27 | forSubmitSuccess?: (payload: any) => void;
28 | isMenuItem?: boolean;
29 | actionText?: string | React.ReactNode;
30 | modalProps?: IModalProps;
31 | layoutProps?: IFormLayoutProps;
32 | };
33 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/core/SchemaComponentOptions.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | SchemaExpressionScopeContext,
3 | SchemaOptionsContext,
4 | } from "@formily/react";
5 | import { FormPath } from "@formily/shared";
6 | import React, { useContext } from "react";
7 | import { ISchemaComponentOptionsProps } from "../types";
8 |
9 | export const SchemaComponentOptions: React.FC<
10 | React.PropsWithChildren
11 | > = (props) => {
12 | let options = useContext(SchemaOptionsContext);
13 | const expressionScope = useContext(SchemaExpressionScopeContext);
14 | const scope = { ...options?.scope, ...expressionScope, ...props.scope };
15 |
16 | return (
17 |
27 |
28 | {props.children}
29 |
30 |
31 | );
32 | };
33 |
--------------------------------------------------------------------------------
/li-engine/contrib/lifile/lifile.go:
--------------------------------------------------------------------------------
1 | package lifile
2 |
3 | import (
4 | "context"
5 | "mime/multipart"
6 | "strconv"
7 | "strings"
8 |
9 | "github.com/gogf/gf/v2/net/ghttp"
10 | "github.com/gogf/gf/v2/os/gfile"
11 | "github.com/gogf/gf/v2/os/gtime"
12 | "github.com/gogf/gf/v2/util/grand"
13 | )
14 |
15 | // Storage 存储接口
16 | type Storage interface {
17 | PutObject(ctx context.Context, input *PutObjectInput) (out *PutObjectOutput, err error)
18 | DeleteObject(ctx context.Context, input *DeleteObjectInput) (err error)
19 | // TODO: 文件服务实现 图片裁剪 + office 预览
20 | ServeFile(r *ghttp.Request, input *ProxyInput)
21 | }
22 |
23 | type (
24 | PutObjectInput struct {
25 | File *multipart.FileHeader
26 | BucketName string
27 | FileSize int64
28 | ContentType string
29 | }
30 | PutObjectOutput struct {
31 | FileName string
32 | FileUrl string
33 | }
34 | DeleteObjectInput struct {
35 | BucketName string
36 | FileName string
37 | }
38 | ProxyInput struct {
39 | BucketName string
40 | FileName string
41 | }
42 | )
43 |
44 | func (i *PutObjectInput) filename() string {
45 | return strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36)+grand.S(6)) + gfile.Ext(i.File.Filename)
46 | }
47 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/schema/flow_instance_data.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | import (
4 | "entgo.io/ent"
5 | "entgo.io/ent/schema/field"
6 | "entgo.io/ent/schema/index"
7 | "github.com/BeanWei/li/li-engine/contrib/lient/mixin"
8 | )
9 |
10 | type FlowInstanceData struct {
11 | ent.Schema
12 | }
13 |
14 | func (FlowInstanceData) Mixin() []ent.Mixin {
15 | return []ent.Mixin{
16 | mixin.XID{},
17 | mixin.Time{},
18 | }
19 | }
20 |
21 | func (FlowInstanceData) Fields() []ent.Field {
22 | return []ent.Field{
23 | field.String("flow_instance_id").
24 | NotEmpty().
25 | Comment("流程执行实例ID"),
26 | field.String("flow_node_instance_id").
27 | Default("").
28 | Optional().
29 | Comment("节点执行实例ID"),
30 | field.String("node_key").
31 | Default("").
32 | Optional().
33 | Comment("节点唯一标示"),
34 | field.JSON("data", map[string]interface{}{}).
35 | Default(map[string]string{}).
36 | Optional().
37 | Comment("数据列表json"),
38 | field.Int8("type").
39 | Default(0).
40 | Comment("操作类型(1.实例初始化 2.系统执行 3.系统主动获取 4.上游更新 5.任务提交 6.任务撤回)"),
41 | }
42 | }
43 |
44 | func (FlowInstanceData) Indexes() []ent.Index {
45 | return []ent.Index{
46 | index.Fields("flow_instance_id"),
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/route-switch/RouteSwitch.tsx:
--------------------------------------------------------------------------------
1 | import { Navigate, Route, Routes } from "react-router-dom";
2 | import { RouteContext } from "./context";
3 | import { useRouteComponent } from "./hooks";
4 | import { RouteSwitchProps } from "./types";
5 |
6 | export function RouteSwitch(props: RouteSwitchProps) {
7 | const { routes = [] } = props;
8 | if (!routes.length) {
9 | return null;
10 | }
11 | return (
12 |
13 | {routes.map((route, index) => {
14 | return (
15 |
22 | ) : (
23 |
24 |
25 |
26 | )
27 | }
28 | />
29 | );
30 | })}
31 |
32 | );
33 | }
34 |
35 | function ComponentRenderer(props: { component: string }) {
36 | const Component = useRouteComponent(props.component);
37 | return ;
38 | }
39 |
--------------------------------------------------------------------------------
/li-app/internal/data/user.go:
--------------------------------------------------------------------------------
1 | package data
2 |
3 | import (
4 | "context"
5 | "crypto/sha256"
6 | "fmt"
7 |
8 | "github.com/BeanWei/li/li-app/internal/data/ent"
9 | "github.com/gogf/gf/v2/errors/gcode"
10 | "github.com/gogf/gf/v2/errors/gerror"
11 | "github.com/gogf/gf/v2/os/gcache"
12 | "golang.org/x/crypto/pbkdf2"
13 | )
14 |
15 | var User = new(usersvc)
16 |
17 | type usersvc struct{}
18 |
19 | func (usersvc) HashPassword(pwd, salt string) string {
20 | passwd := pbkdf2.Key([]byte(pwd), []byte(salt), 10000, 50, sha256.New)
21 | return fmt.Sprintf("%x", passwd)
22 | }
23 |
24 | func (usersvc) GetUser(ctx context.Context, uid string) (usr *ent.User, err error) {
25 | val, err := gcache.GetOrSetFunc(ctx, uid, func(ctx context.Context) (interface{}, error) {
26 | return ent.LiClient().User.Get(ctx, uid)
27 | }, 0)
28 | if err != nil {
29 | if ent.IsNotFound(err) {
30 | return nil, nil
31 | }
32 | return nil, gerror.WrapCode(gcode.CodeDbOperationError, err)
33 | }
34 | if err = val.Struct(&usr); err != nil {
35 | return nil, err
36 | }
37 | return
38 | }
39 |
40 | func (usersvc) RemoveUserCache(ctx context.Context, uids ...interface{}) (err error) {
41 | _, err = gcache.Remove(ctx, uids...)
42 | return
43 | }
44 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/input-number/index.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | InputNumber as ArcoInputNumber,
3 | InputNumberProps,
4 | } from "@arco-design/web-react";
5 | import { connect, mapReadPretty } from "@formily/react";
6 | import { isValid } from "@formily/shared";
7 | import { useTranslation } from "react-i18next";
8 | import { toFixed } from "./utils/MiniDecimal";
9 | import { getNumberPrecision } from "./utils/numberUtil";
10 |
11 | export const InputNumber = connect(
12 | (props: InputNumberProps) => {
13 | const { t } = useTranslation();
14 | return (
15 |
18 | );
19 | },
20 | mapReadPretty((props) => {
21 | const { step, value, addonBefore, addonAfter } = props;
22 | if (!isValid(props.value)) {
23 | return -
;
24 | }
25 | const precision = Math.max(
26 | getNumberPrecision(String(value)),
27 | getNumberPrecision(step)
28 | );
29 | return (
30 |
31 | {addonBefore}
32 | {toFixed(String(value), ".", precision)}
33 | {addonAfter}
34 |
35 | );
36 | })
37 | );
38 |
39 | export default InputNumber;
40 |
--------------------------------------------------------------------------------
/li-engine/controller/file_upload.go:
--------------------------------------------------------------------------------
1 | package controller
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/BeanWei/li/li-engine/contrib/lifile"
7 | "github.com/BeanWei/li/li-engine/service"
8 | "github.com/gogf/gf/v2/errors/gcode"
9 | "github.com/gogf/gf/v2/errors/gerror"
10 | "github.com/gogf/gf/v2/net/ghttp"
11 | "github.com/gogf/gf/v2/os/gtime"
12 | )
13 |
14 | type FileUploadRes struct {
15 | Name string `json:"name"`
16 | URL string `json:"url"`
17 | }
18 |
19 | // FileUpload 单文件上传
20 | func FileUpload(ctx context.Context) (res *FileUploadRes, err error) {
21 | client, err := service.NewFileClient(ctx)
22 | if err != nil {
23 | return nil, err
24 | }
25 |
26 | f := ghttp.RequestFromCtx(ctx).GetUploadFile("file")
27 | if f == nil {
28 | err = gerror.NewCode(
29 | gcode.CodeMissingParameter,
30 | "file is empty, maybe you retrieve it from invalid field name or form enctype",
31 | )
32 | return
33 | }
34 |
35 | output, err := client.PutObject(ctx, &lifile.PutObjectInput{
36 | File: f.FileHeader,
37 | BucketName: gtime.Now().Format("Ym"),
38 | })
39 | if err != nil {
40 | return nil, err
41 | }
42 | res = &FileUploadRes{
43 | Name: output.FileName,
44 | URL: "/upload" + output.FileUrl,
45 | }
46 | return
47 | }
48 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/chart/index.less:
--------------------------------------------------------------------------------
1 | @import '~@arco-design/web-react/lib/style/theme/default.less';
2 |
3 | @authchart-cls: ~'@{prefix}-autochart';
4 |
5 | .@{authchart-cls}-container {
6 | position: relative;
7 | min-height: 400px;
8 |
9 | .@{authchart-cls}-canvas-layer {
10 | height: 100%;
11 | width: 100%;
12 | position: absolute;
13 | top: 0px;
14 | left: 0px;
15 | pointer-events: auto;
16 | box-sizing: border-box;
17 | display: flex;
18 | flex-direction: column;
19 |
20 | .canvas-content {
21 | flex: 1 1 0%;
22 | position: relative;
23 | }
24 |
25 | .feedback-layer {
26 | height: 100%;
27 | width: 100%;
28 | position: absolute;
29 | top: 0px;
30 | left: 0px;
31 | box-sizing: border-box;
32 | }
33 | }
34 |
35 | .@{authchart-cls}-nodata-layer {
36 | height: 100%;
37 | width: 100%;
38 | position: absolute;
39 | top: 0px;
40 | left: 0px;
41 | // pointer-events: none;
42 | box-sizing: border-box;
43 | }
44 |
45 | .@{authchart-cls}-nodata-content {
46 | color: #aaa;
47 | text-align: center;
48 | position: relative;
49 | top: 50%;
50 | transform: translateY(-50%);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./action";
2 | export * from "./array-base";
3 | export * from "./array-items";
4 | export * from "./array-table";
5 | export * from "./avatar";
6 | export * from "./card-item";
7 | export * from "./cascader";
8 | export * from "./chart";
9 | export * from "./checkbox";
10 | export * from "./color-select";
11 | export * from "./date-picker";
12 | export * from "./divider";
13 | export * from "./dropdown-menu";
14 | export * from "./flow-editor";
15 | export * from "./form";
16 | export * from "./form-button-group";
17 | export * from "./form-drawer";
18 | export * from "./form-grid";
19 | export * from "./form-item";
20 | export * from "./form-layout";
21 | export * from "./form-modal";
22 | export * from "./grid";
23 | export * from "./input";
24 | export * from "./input-number";
25 | export * from "./list";
26 | export * from "./menu";
27 | export * from "./money";
28 | export * from "./password";
29 | export * from "./radio";
30 | export * from "./record-select";
31 | export * from "./reset";
32 | export * from "./select";
33 | export * from "./space";
34 | export * from "./submit";
35 | export * from "./switch";
36 | export * from "./tabs";
37 | export * from "./time-picker";
38 | export * from "./upload";
39 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_percent.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func Percent(name string) *percentBuilder {
9 | return &percentBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeNumber,
13 | XComponent: ui.ComponentInputNumber,
14 | XComponentProps: map[string]interface{}{
15 | "suffix": "%",
16 | "precision": 2,
17 | "step": 1,
18 | },
19 | XDecorator: ui.DecoratorFormItem,
20 | },
21 | }}
22 | }
23 |
24 | type percentBuilder struct {
25 | *NodeBuilder
26 | }
27 |
28 | func (b *percentBuilder) AC(f ac.AC) *percentBuilder {
29 | b.schema.AC = f
30 | return b
31 | }
32 |
33 | func (b *percentBuilder) Title(title string) *percentBuilder {
34 | b.SetTitle(title)
35 | return b
36 | }
37 |
38 | func (b *percentBuilder) Description(description string) *percentBuilder {
39 | b.SetDescription(description)
40 | return b
41 | }
42 |
43 | func (b *percentBuilder) Default(value interface{}) *percentBuilder {
44 | b.schema.Default = value
45 | return b
46 | }
47 |
48 | func (b *percentBuilder) Step(step int) *percentBuilder {
49 | b.schema.XComponentProps["step"] = step
50 | return b
51 | }
52 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_gridrow.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | "github.com/gogf/gf/v2/container/gmap"
7 | )
8 |
9 | func GridRow(name string) *gridrowBuilder {
10 | return &gridrowBuilder{&NodeBuilder{
11 | schema: &ui.Schema{
12 | Name: name,
13 | Type: ui.SchemaTypeVoid,
14 | XComponent: ui.ComponentGridRow,
15 | XComponentProps: make(map[string]interface{}),
16 | Properties: gmap.NewListMap(),
17 | },
18 | }}
19 | }
20 |
21 | type gridrowBuilder struct {
22 | *NodeBuilder
23 | }
24 |
25 | func (b *gridrowBuilder) AC(f ac.AC) *gridrowBuilder {
26 | b.schema.AC = f
27 | return b
28 | }
29 |
30 | // https://arco.design/react/components/grid#api
31 |
32 | // Gutter 栅格间隔
33 | func (b *gridrowBuilder) Gutter(gutter int) *gridrowBuilder {
34 | b.schema.XComponentProps["gutter"] = gutter
35 | return b
36 | }
37 |
38 | // Align 竖直对齐方式
39 | func (b *gridrowBuilder) Align(align string) *gridrowBuilder {
40 | b.schema.XComponentProps["align"] = align
41 | return b
42 | }
43 |
44 | // Justify 水平对齐方式
45 | func (b *gridrowBuilder) Justify(justify string) *gridrowBuilder {
46 | b.schema.XComponentProps["justify"] = justify
47 | return b
48 | }
49 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/schema/flow_node_instance_log.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | import (
4 | "entgo.io/ent"
5 | "entgo.io/ent/schema/field"
6 | "entgo.io/ent/schema/index"
7 | "github.com/BeanWei/li/li-engine/contrib/lient/mixin"
8 | )
9 |
10 | type FlowNodeInstanceLog struct {
11 | ent.Schema
12 | }
13 |
14 | func (FlowNodeInstanceLog) Mixin() []ent.Mixin {
15 | return []ent.Mixin{
16 | mixin.XID{},
17 | mixin.Time{},
18 | }
19 | }
20 |
21 | func (FlowNodeInstanceLog) Fields() []ent.Field {
22 | return []ent.Field{
23 | field.String("flow_instance_id").
24 | NotEmpty().
25 | Comment("流程执行实例ID"),
26 | field.String("flow_node_instance_id").
27 | NotEmpty().
28 | Comment("节点执行实例ID"),
29 | field.String("flow_instance_data_id").
30 | Default("").
31 | Optional().
32 | Comment("实例数据ID"),
33 | field.String("node_key").
34 | NotEmpty().
35 | Comment("节点唯一标示"),
36 | field.Int8("type").
37 | Default(0).
38 | Comment("操作类型(1.系统执行 2.任务提交 3.任务撤销)"),
39 | field.Int8("status").
40 | Default(0).
41 | Comment("'状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)"),
42 | }
43 | }
44 |
45 | func (FlowNodeInstanceLog) Indexes() []ent.Index {
46 | return []ent.Index{
47 | index.Fields("flow_instance_id"),
48 | index.Fields("flow_node_instance_id"),
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_actionformmodalsubmit.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/controller"
6 | "github.com/BeanWei/li/li-engine/view/ui"
7 | )
8 |
9 | func ActionFormModalSubmit(name string) *actionformmodalsubmitBuilder {
10 | return &actionformmodalsubmitBuilder{&NodeBuilder{
11 | schema: &ui.Schema{
12 | Name: name,
13 | Type: ui.SchemaTypeVoid,
14 | XComponent: ui.ComponentActionFormModalSubmit,
15 | XComponentProps: make(map[string]interface{}),
16 | HandlerNames: make([]string, 0),
17 | },
18 | }}
19 | }
20 |
21 | type actionformmodalsubmitBuilder struct {
22 | *NodeBuilder
23 | }
24 |
25 | func (b *actionformmodalsubmitBuilder) AC(f ac.AC) *actionformmodalsubmitBuilder {
26 | b.schema.AC = f
27 | return b
28 | }
29 |
30 | func (b *actionformmodalsubmitBuilder) Title(title string) *actionformmodalsubmitBuilder {
31 | b.SetTitle(title)
32 | return b
33 | }
34 |
35 | func (b *actionformmodalsubmitBuilder) ForSubmit(operation string, handler interface{}) *actionformmodalsubmitBuilder {
36 | b.schema.XComponentProps["forSubmit"] = operation
37 | b.schema.HandlerNames = append(b.schema.HandlerNames, operation)
38 | controller.Bind(operation, handler)
39 | return b
40 | }
41 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/schema/flow_instance.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | import (
4 | "entgo.io/ent"
5 | "entgo.io/ent/schema/edge"
6 | "entgo.io/ent/schema/field"
7 | "entgo.io/ent/schema/index"
8 | "github.com/BeanWei/li/li-engine/contrib/lient/mixin"
9 | )
10 |
11 | type FlowInstance struct {
12 | ent.Schema
13 | }
14 |
15 | func (FlowInstance) Mixin() []ent.Mixin {
16 | return []ent.Mixin{
17 | mixin.XID{},
18 | mixin.Time{},
19 | }
20 | }
21 |
22 | func (FlowInstance) Fields() []ent.Field {
23 | return []ent.Field{
24 | field.String("flow_deployment_id").
25 | NotEmpty().
26 | Comment("部署的流程ID"),
27 | field.String("ref_id").
28 | NotEmpty().
29 | Comment("引用/调用方ID"),
30 | field.Int8("status").
31 | Default(0).
32 | Comment("流程状态(1.执行完成 2.执行中 3.执行终止(强制终止))"),
33 | }
34 | }
35 |
36 | func (FlowInstance) Edges() []ent.Edge {
37 | return []ent.Edge{
38 | edge.From("flow_deployment", FlowDeployment.Type).
39 | Ref("flow_instances").
40 | Field("flow_deployment_id").
41 | Unique().
42 | Required(),
43 | edge.To("flow_node_instances", FlowNodeInstance.Type),
44 | }
45 | }
46 |
47 | func (FlowInstance) Indexes() []ent.Index {
48 | return []ent.Index{
49 | index.Fields("flow_deployment_id"),
50 | index.Fields("ref_id"),
51 | index.Fields("status"),
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_avatar.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func Avatar(name string) *avatarBuilder {
9 | return &avatarBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeVoid,
13 | XComponent: ui.ComponentAvatar,
14 | XComponentProps: make(map[string]interface{}),
15 | },
16 | }}
17 | }
18 |
19 | type avatarBuilder struct {
20 | *NodeBuilder
21 | }
22 |
23 | func (b *avatarBuilder) AC(f ac.AC) *avatarBuilder {
24 | b.schema.AC = f
25 | return b
26 | }
27 |
28 | func (b *avatarBuilder) Shape(shape string) *avatarBuilder {
29 | b.schema.XComponentProps["shape"] = shape
30 | return b
31 | }
32 |
33 | func (b *avatarBuilder) Size(size int) *avatarBuilder {
34 | b.schema.XComponentProps["size"] = size
35 | return b
36 | }
37 |
38 | func (b *avatarBuilder) Alt(alt string) *avatarBuilder {
39 | b.schema.XComponentProps["alt"] = alt
40 | return b
41 | }
42 |
43 | func (b *avatarBuilder) Src(src string) *avatarBuilder {
44 | b.schema.XComponentProps["src"] = src
45 | return b
46 | }
47 |
48 | func (b *avatarBuilder) Style(style map[string]interface{}) *avatarBuilder {
49 | b.schema.XComponentProps["style"] = style
50 | return b
51 | }
52 |
--------------------------------------------------------------------------------
/li-engine/service/file.go:
--------------------------------------------------------------------------------
1 | package service
2 |
3 | import (
4 | "context"
5 | "sync"
6 |
7 | "github.com/BeanWei/li/li-engine/contrib/lifile"
8 | "github.com/gogf/gf/v2/frame/g"
9 | )
10 |
11 | var (
12 | fileclent lifile.Storage
13 | fileclentOnce sync.Once
14 | )
15 |
16 | func NewFileClient(ctx context.Context) (lifile.Storage, error) {
17 | var err error
18 | fileclentOnce.Do(func() {
19 | adapter := g.Cfg().MustGet(ctx, "file.default.adapter").String()
20 | switch adapter {
21 | case "aws":
22 | fileclent, err = lifile.NewStorageAwsClient(&lifile.AwsClientOption{
23 | AccessKeyID: g.Cfg().MustGet(ctx, "file.aws.accessKeyID").String(),
24 | SecretAccessKey: g.Cfg().MustGet(ctx, "file.aws.secretAccessKey").String(),
25 | Endpoint: g.Cfg().MustGet(ctx, "file.aws.endpoint").String(),
26 | Region: g.Cfg().MustGet(ctx, "file.aws.region").String(),
27 | DisableSSL: g.Cfg().MustGet(ctx, "file.aws.disableSSL").Bool(),
28 | ForcePathStyle: g.Cfg().MustGet(ctx, "file.aws.forcePathStyle").Bool(),
29 | })
30 | default:
31 | fileclent, err = lifile.NewStorageLocalClient(&lifile.LocalClientOption{
32 | Dir: g.Cfg().MustGet(ctx, "file.local.dir").String(),
33 | })
34 | }
35 | })
36 | if err != nil {
37 | return nil, err
38 | }
39 | return fileclent, nil
40 | }
41 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_actionformdrawersubmit.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/controller"
6 | "github.com/BeanWei/li/li-engine/view/ui"
7 | )
8 |
9 | func ActionFormDrawerSubmit(name string) *actionformdrawersubmitBuilder {
10 | return &actionformdrawersubmitBuilder{
11 | &NodeBuilder{
12 | schema: &ui.Schema{
13 | Name: name,
14 | Type: ui.SchemaTypeVoid,
15 | XComponent: ui.ComponentActionFormDrawerSubmit,
16 | XComponentProps: make(map[string]interface{}),
17 | HandlerNames: make([]string, 0),
18 | },
19 | },
20 | }
21 | }
22 |
23 | type actionformdrawersubmitBuilder struct {
24 | *NodeBuilder
25 | }
26 |
27 | func (b *actionformdrawersubmitBuilder) AC(f ac.AC) *actionformdrawersubmitBuilder {
28 | b.schema.AC = f
29 | return b
30 | }
31 |
32 | func (b *actionformdrawersubmitBuilder) Title(title string) *actionformdrawersubmitBuilder {
33 | b.SetTitle(title)
34 | return b
35 | }
36 |
37 | func (b *actionformdrawersubmitBuilder) ForSubmit(operation string, handler interface{}) *actionformdrawersubmitBuilder {
38 | b.schema.XComponentProps["forSubmit"] = operation
39 | b.schema.HandlerNames = append(b.schema.HandlerNames, operation)
40 | controller.Bind(operation, handler)
41 | return b
42 | }
43 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/__builtins__/hooks/useCollapseGrid.ts:
--------------------------------------------------------------------------------
1 | import { useMemo } from "react";
2 | import FormGrid from "../../form-grid";
3 |
4 | export const useCollapseGrid = (maxRows: number) => {
5 | const grid = useMemo(
6 | () =>
7 | FormGrid.createFormGrid({
8 | maxColumns: 4,
9 | maxWidth: 240,
10 | maxRows: maxRows,
11 | shouldVisible: (node, grid) => {
12 | if (node.index === grid.childSize - 1) return true;
13 | if (grid.maxRows === Infinity) return true;
14 | return (node.shadowRow || 0) < maxRows + 1;
15 | },
16 | }),
17 | []
18 | );
19 | const expanded = grid.maxRows === Infinity;
20 | const realRows = grid.shadowRows;
21 | const computeRows = grid.fullnessLastColumn
22 | ? grid.shadowRows - 1
23 | : grid.shadowRows;
24 |
25 | const toggle = () => {
26 | if (grid.maxRows === Infinity) {
27 | grid.maxRows = maxRows;
28 | } else {
29 | grid.maxRows = Infinity;
30 | }
31 | };
32 | const takeType = () => {
33 | if (realRows < maxRows + 1) return "incomplete-wrap";
34 | if (computeRows > maxRows) return "collapsible";
35 | return "complete-wrap";
36 | };
37 | return {
38 | grid,
39 | expanded,
40 | toggle,
41 | type: takeType(),
42 | };
43 | };
44 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/controller/user.go:
--------------------------------------------------------------------------------
1 | package controller
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/BeanWei/li/li-app/internal/app/admin/dto"
7 | "github.com/BeanWei/li/li-app/internal/data"
8 | "github.com/BeanWei/li/li-app/internal/data/ent"
9 | "github.com/BeanWei/li/li-app/internal/data/ent/user"
10 | "github.com/BeanWei/li/li-app/internal/shared"
11 | "github.com/gogf/gf/v2/errors/gcode"
12 | "github.com/gogf/gf/v2/errors/gerror"
13 | )
14 |
15 | const (
16 | OperationUserSignIn = "userSignIn"
17 | OperationUserProfile = "userProfile"
18 | )
19 |
20 | // UserSignIn 用户登录
21 | func UserSignIn(ctx context.Context, req *dto.UserSignInReq) (res *dto.UserSignInRes, err error) {
22 | usr, err := ent.LiClient().User.
23 | Query().
24 | Where(user.EmailEQ(req.Email)).
25 | Only(ctx)
26 | if err != nil {
27 | if ent.IsNotFound(err) {
28 | return nil, gerror.NewCode(gcode.CodeNotFound, "账号不存在")
29 | }
30 | return nil, gerror.Wrapf(err, "查询用户 %s 错误", req.Email)
31 | }
32 | res = &dto.UserSignInRes{
33 | ID: usr.ID,
34 | }
35 | res.Sid, err = shared.Session.SetUser(ctx, usr.ID)
36 | return
37 | }
38 |
39 | // UserProfile 当前用户信息
40 | func UserProfile(ctx context.Context) (res *ent.User, err error) {
41 | ctxUser := shared.Ctx.Get(ctx).User
42 | res, err = data.User.GetUser(ctx, ctxUser.ID)
43 | return
44 | }
45 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/schema-components/lang-switch/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useContext } from "react";
2 | import { observer } from "@formily/react";
3 | import { IconLanguage } from "@arco-design/web-react/icon";
4 | import { Button, Select, TriggerProps } from "@arco-design/web-react";
5 | import { GlobalContext } from "../../../context";
6 |
7 | export const LangSwitch: React.FC<{
8 | triggerElementStyle?: React.CSSProperties;
9 | triggerProps?: TriggerProps;
10 | }> = observer((props) => {
11 | const { lang, setLang } = useContext(GlobalContext);
12 |
13 | return (
14 | }
24 | />
25 | }
26 | options={[
27 | { label: "中文", value: "zh-CN" },
28 | { label: "English", value: "en-US" },
29 | ]}
30 | value={lang}
31 | triggerProps={{
32 | ...props.triggerProps,
33 | autoAlignPopupWidth: false,
34 | autoAlignPopupMinWidth: true,
35 | }}
36 | trigger="hover"
37 | onChange={(value) => {
38 | setLang?.(value);
39 | }}
40 | />
41 | );
42 | });
43 |
44 | export default LangSwitch;
45 |
--------------------------------------------------------------------------------
/li-engine/contrib/lient/mixin/time_mixin.go:
--------------------------------------------------------------------------------
1 | package mixin
2 |
3 | import (
4 | "time"
5 |
6 | "entgo.io/ent"
7 | "entgo.io/ent/schema/field"
8 | "entgo.io/ent/schema/index"
9 | "entgo.io/ent/schema/mixin"
10 | "github.com/BeanWei/li/li-engine/contrib/lient"
11 | )
12 |
13 | type Time struct {
14 | mixin.Schema
15 | }
16 |
17 | func (Time) Fields() []ent.Field {
18 | return []ent.Field{
19 | field.Int64("created_at").
20 | Immutable().
21 | DefaultFunc(func() int64 {
22 | return time.Now().Unix()
23 | }).
24 | Annotations(lient.Annotation{
25 | DisableCreate: true,
26 | DisableUpdate: true,
27 | }),
28 | field.Int64("updated_at").
29 | DefaultFunc(func() int64 {
30 | return time.Now().Unix()
31 | }).
32 | UpdateDefault(func() int64 {
33 | return time.Now().Unix()
34 | }).
35 | Annotations(lient.Annotation{
36 | DisableCreate: true,
37 | DisableUpdate: true,
38 | }),
39 | field.Int64("deleted_at").
40 | Optional().
41 | Default(0).
42 | StructTag(`json:"-"`).
43 | Annotations(lient.Annotation{
44 | DisableCreate: true,
45 | DisableRead: true,
46 | DisableUpdate: true,
47 | }),
48 | }
49 | }
50 |
51 | func (Time) Indexes() []ent.Index {
52 | return []ent.Index{
53 | index.Fields("created_at"),
54 | index.Fields("deleted_at"),
55 | }
56 | }
57 |
58 | var _ ent.Mixin = (*Time)(nil)
59 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/radio/index.tsx:
--------------------------------------------------------------------------------
1 | import { connect, mapProps, mapReadPretty, useField } from "@formily/react";
2 | import { Radio as ArcoRadio, Tag } from "@arco-design/web-react";
3 | import type { RadioProps, RadioGroupProps } from "@arco-design/web-react";
4 | import { isValid } from "@formily/shared";
5 |
6 | type ComposedRadio = React.FC & {
7 | Group?: React.FC;
8 | __ARCO_RADIO?: boolean;
9 | };
10 |
11 | export const Radio: ComposedRadio = connect(
12 | ArcoRadio,
13 | mapProps({
14 | value: "checked",
15 | onInput: "onChange",
16 | })
17 | );
18 |
19 | Radio.__ARCO_RADIO = true;
20 |
21 | Radio.Group = connect(
22 | ArcoRadio.Group,
23 | mapProps({
24 | dataSource: "options",
25 | }),
26 | mapReadPretty((props) => {
27 | const { value } = props;
28 | if (!isValid(value)) {
29 | return -
;
30 | }
31 | const field = useField();
32 | const dataSource = field.dataSource || [];
33 |
34 | return (
35 |
36 | {dataSource
37 | .filter((option: any) => option.value === value)
38 | .map((option: any, key: any) => (
39 |
40 | {option.label}
41 |
42 | ))}
43 |
44 | );
45 | })
46 | );
47 |
48 | export default Radio;
49 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/schema/flow_deployment.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | import (
4 | "entgo.io/ent"
5 | "entgo.io/ent/schema/edge"
6 | "entgo.io/ent/schema/field"
7 | "entgo.io/ent/schema/index"
8 | "github.com/BeanWei/li/li-engine/contrib/lient/mixin"
9 | )
10 |
11 | type FlowDeployment struct {
12 | ent.Schema
13 | }
14 |
15 | func (FlowDeployment) Mixin() []ent.Mixin {
16 | return []ent.Mixin{
17 | mixin.XID{},
18 | mixin.Time{},
19 | }
20 | }
21 |
22 | func (FlowDeployment) Fields() []ent.Field {
23 | return []ent.Field{
24 | field.String("flow_definition_id").
25 | NotEmpty().
26 | Comment("流程定义ID"),
27 | field.String("name").
28 | NotEmpty().
29 | Comment("流程名称"),
30 | field.Int8("status").
31 | Default(0).
32 | Comment("状态(1.已部署 2.已下线)"),
33 | field.JSON("model", FlowModel{}).
34 | Comment("流程模型"),
35 | field.String("remark").
36 | Default("").
37 | Optional().
38 | Comment("备注"),
39 | }
40 | }
41 |
42 | func (FlowDeployment) Edges() []ent.Edge {
43 | return []ent.Edge{
44 | edge.From("flow_definition", FlowDefinition.Type).
45 | Ref("flow_deployments").
46 | Field("flow_definition_id").
47 | Unique().
48 | Required(),
49 | edge.To("flow_instances", FlowInstance.Type),
50 | }
51 | }
52 |
53 | func (FlowDeployment) Indexes() []ent.Index {
54 | return []ent.Index{
55 | index.Fields("flow_definition_id"),
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/array-table/index.less:
--------------------------------------------------------------------------------
1 | @import '~@arco-design/web-react/lib/style/theme/default.less';
2 |
3 | @array-table-prefix-cls: ~'@{prefix}-formily-array-table';
4 | @error-color: #ff4d4f;
5 |
6 | .@{array-table-prefix-cls} {
7 | .@{array-table-prefix-cls}-pagination {
8 | display: flex;
9 | justify-content: center;
10 |
11 | .@{array-table-prefix-cls}-status-select.has-error {
12 | .@{prefix}-select-selector {
13 | border-color: @error-color !important;
14 | }
15 | }
16 | }
17 |
18 | .@{prefix}-table {
19 | td {
20 | visibility: visible;
21 |
22 | .@{prefix}-form-item:not(.@{prefix}-form-item-feedback-layout-popover) {
23 | margin-bottom: 0 !important;
24 |
25 | .@{prefix}-form-item-help {
26 | position: absolute;
27 | font-size: 12px;
28 | top: 100%;
29 | background: #fff;
30 | width: 100%;
31 | margin-top: 3px;
32 | padding: 3px;
33 | z-index: 1;
34 | border-radius: 3px;
35 | box-shadow: 0 0 10px #eee;
36 | animation: none;
37 | transform: translateY(0);
38 | opacity: 1;
39 | }
40 | }
41 | }
42 | }
43 |
44 | .@{array-table-prefix-cls}-sort-helper {
45 | background: #fff;
46 | border: 1px solid #eee;
47 | z-index: 10;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/i18n/index.ts:
--------------------------------------------------------------------------------
1 | import i18next from "i18next";
2 | import { initReactI18next } from "react-i18next";
3 | import HttpApi from "i18next-http-backend";
4 |
5 | const getLocalStorage = (): string | undefined => {
6 | try {
7 | return JSON.parse(localStorage.getItem("li-lang") || '""');
8 | } catch {
9 | return;
10 | }
11 | };
12 |
13 | export const i18n = i18next.createInstance();
14 |
15 | i18n
16 | .use(HttpApi)
17 | .use(initReactI18next)
18 | .init({
19 | debug: false,
20 | lng: getLocalStorage() || navigator.language,
21 | supportedLngs: ["en-US", "zh-CN"],
22 | preload: ["en-US", "zh-CN"],
23 | backend: {
24 | loadPath: "/locales/{{lng}}.json",
25 | },
26 | // lient 默认的文案
27 | resources: {
28 | "en-US": {
29 | translation: {
30 | addNew: "Add New",
31 | bulkDelete: "Bulk Delete",
32 | confirmDelete: "Are you sure you want to delete it?",
33 | columnAction: "Actions",
34 | viewDrawerTitle: "View",
35 | editDrawerTitle: "Edit",
36 | },
37 | },
38 | "zh-CN": {
39 | translation: {
40 | addNew: "新建",
41 | bulkDelete: "删除",
42 | confirmDelete: "你确定要删除吗?",
43 | columnAction: "操作",
44 | viewDrawerTitle: "查看",
45 | editDrawerTitle: "编辑",
46 | },
47 | },
48 | },
49 | });
50 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/reset/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Button, ButtonProps } from "@arco-design/web-react";
3 | import { IFieldResetOptions, IFormFeedback } from "@formily/core";
4 | import { useFieldSchema, useParentForm } from "@formily/react";
5 | import { useTranslation } from "react-i18next";
6 |
7 | export interface IResetProps extends IFieldResetOptions, ButtonProps {
8 | onClick?: (e: Event) => any;
9 | onResetValidateSuccess?: (payload: any) => void;
10 | onResetValidateFailed?: (feedbacks: IFormFeedback[]) => void;
11 | }
12 |
13 | export const Reset: React.FC = ({
14 | forceClear,
15 | validate,
16 | onResetValidateSuccess,
17 | onResetValidateFailed,
18 | ...props
19 | }) => {
20 | const form = useParentForm();
21 | const fieldSchema = useFieldSchema();
22 | const { t } = useTranslation();
23 | return (
24 |
41 | );
42 | };
43 |
44 | export default Reset;
45 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/core/SchemaFormField.tsx:
--------------------------------------------------------------------------------
1 | import { useMemo } from "react";
2 | import { createForm, onFieldValueChange } from "@formily/core";
3 | import { FormProvider, Schema, Stringify } from "@formily/react";
4 | import { UiSchemaComponentProvider } from "./UiSchemaComponentProvider";
5 | import { SchemaComponent } from "./SchemaComponent";
6 |
7 | export const SchemaFormField: React.FC<{
8 | name: string;
9 | schema: Stringify;
10 | value?: any;
11 | onChange?: (value: any) => void;
12 | }> = (props) => {
13 | const form = useMemo(
14 | () =>
15 | createForm({
16 | initialValues: {
17 | [props.name]: props.value,
18 | },
19 | effects() {
20 | onFieldValueChange(props.name, (field) => {
21 | props.onChange?.(field.value);
22 | });
23 | },
24 | }),
25 | []
26 | );
27 | const schema = new Schema({
28 | type: "object",
29 | properties: {
30 | [props.name]: props.schema,
31 | },
32 | });
33 | schema.reduceProperties((b, s) => {
34 | s["x-decorator"] = undefined;
35 | s["x-decorator-props"] = undefined;
36 | s["x-read-pretty"] = false;
37 | });
38 |
39 | return (
40 |
41 |
42 |
43 |
44 |
45 | );
46 | };
47 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/processor/terminate_process.go:
--------------------------------------------------------------------------------
1 | package processor
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/BeanWei/li/li-engine/contrib/liflow"
7 | "github.com/BeanWei/li/li-engine/contrib/liflow/ent"
8 | "github.com/gogf/gf/v2/errors/gerror"
9 | )
10 |
11 | type (
12 | terminateProcessInput struct {
13 | FlowInstanceID string
14 | }
15 | terminateProcessOutput struct {
16 | FlowInstanceID string `json:"flow_instance_id"`
17 | FlowInstanceStatus int8 `json:"flow_instance_status"`
18 | }
19 | )
20 |
21 | // TerminateProcess 终止流程
22 | // 强制终止流程实例,如果当前流程实例状态是已完成,引擎什么也不做,否则引擎会将状态置为已终止
23 | // 注意,一旦流程已完成或者已终止,引擎将不再允许提交和回滚
24 | func TerminateProcess(ctx context.Context, input *terminateProcessInput) (*terminateProcessOutput, error) {
25 | flowInstance, err := ent.DB().FlowInstance.Get(ctx, input.FlowInstanceID)
26 | if err != nil {
27 | return nil, gerror.WrapCode(liflow.ErrCodeGetFlowInstanceFailed, err)
28 | }
29 | output := new(terminateProcessOutput)
30 | if flowInstance.Status == liflow.FlowInstanceStatusCompleted {
31 | output.FlowInstanceStatus = liflow.FlowInstanceStatusCompleted
32 | } else {
33 | err = flowInstance.Update().SetStatus(liflow.FlowInstanceStatusTerminated).Exec(ctx)
34 | if err != nil {
35 | return nil, gerror.WrapCode(liflow.ErrCodeSaveFlowInstanceFailed, err)
36 | }
37 | output.FlowInstanceStatus = liflow.FlowInstanceStatusTerminated
38 | }
39 | return output, nil
40 | }
41 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_arrayitems.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view"
6 | "github.com/BeanWei/li/li-engine/view/ui"
7 | "github.com/gogf/gf/v2/container/gmap"
8 | )
9 |
10 | func ArrayItems(name string) *arrayitemsBuilder {
11 | return &arrayitemsBuilder{&NodeBuilder{
12 | schema: &ui.Schema{
13 | Name: name,
14 | Type: ui.SchemaTypeArray,
15 | XComponent: ui.ComponentArrayItems,
16 | XComponentProps: make(map[string]interface{}),
17 | XDecorator: ui.DecoratorFormItem,
18 | Properties: gmap.NewListMap(),
19 | },
20 | }}
21 | }
22 |
23 | type arrayitemsBuilder struct {
24 | *NodeBuilder
25 | }
26 |
27 | func (b *arrayitemsBuilder) AC(f ac.AC) *arrayitemsBuilder {
28 | b.schema.AC = f
29 | return b
30 | }
31 |
32 | // Rows 一维数组
33 | func (b *arrayitemsBuilder) Rows(elements ...view.Node) *arrayitemsBuilder {
34 | if b.schema.Items == nil {
35 | b.schema.Items = &ui.Schema{
36 | Type: ui.SchemaTypeVoid,
37 | XComponent: ui.ComponentSpace,
38 | Properties: gmap.NewListMap(),
39 | }
40 | }
41 | for _, element := range elements {
42 | es := element.Schema()
43 | b.schema.Items.Properties.Set(es.Name, es)
44 | }
45 | return b
46 | }
47 |
48 | // Columns 对象数组
49 | func (b *arrayitemsBuilder) Columns(elements ...view.Node) *arrayitemsBuilder {
50 | b.Items(elements...)
51 | return b
52 | }
53 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_rate.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func Rate(name string) *rateBuilder {
9 | return &rateBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeNumber,
13 | XComponent: ui.ComponentRate,
14 | XComponentProps: make(map[string]interface{}),
15 | XDecorator: ui.DecoratorFormItem,
16 | },
17 | }}
18 | }
19 |
20 | type rateBuilder struct {
21 | *NodeBuilder
22 | }
23 |
24 | func (b *rateBuilder) AC(f ac.AC) *rateBuilder {
25 | b.schema.AC = f
26 | return b
27 | }
28 |
29 | func (b *rateBuilder) Title(title string) *rateBuilder {
30 | b.SetTitle(title)
31 | return b
32 | }
33 |
34 | func (b *rateBuilder) Description(description string) *rateBuilder {
35 | b.SetDescription(description)
36 | return b
37 | }
38 |
39 | func (b *rateBuilder) Default(value interface{}) *rateBuilder {
40 | b.schema.Default = value
41 | return b
42 | }
43 |
44 | func (b *rateBuilder) Count(count int) *rateBuilder {
45 | b.schema.XComponentProps["count"] = count
46 | return b
47 | }
48 |
49 | func (b *rateBuilder) AllowHalf(allowHalf bool) *rateBuilder {
50 | b.schema.XComponentProps["allowHalf"] = allowHalf
51 | return b
52 | }
53 |
54 | func (b *rateBuilder) Grading(grading bool) *rateBuilder {
55 | b.schema.XComponentProps["grading"] = grading
56 | return b
57 | }
58 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/li-flow/components/NodePanel/index.tsx:
--------------------------------------------------------------------------------
1 | import LogicFlow from "@logicflow/core";
2 | import useLocale from "../../../locale";
3 | import { node } from "../../config";
4 |
5 | const NodePanel: React.FC<{ lf: LogicFlow }> = (props) => {
6 | const local = useLocale();
7 | const nodes = Object.values(node);
8 |
9 | return (
10 |
14 | {nodes.map((item, key) => {
15 | return (
16 |
24 |

{
32 | props.lf.dnd.startDrag({
33 | type: item.type,
34 | });
35 | }}
36 | />
37 |
{local.LiFlow[item.label]}
38 |
39 | );
40 | })}
41 |
42 | );
43 | };
44 |
45 | export default NodePanel;
46 |
--------------------------------------------------------------------------------
/li-web/apps/admin/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import svgrPlugin from "@arco-plugins/vite-plugin-svgr";
4 | import vitePluginForArco from "@arco-plugins/vite-react";
5 | import { viteMockServe } from "vite-plugin-mock";
6 | import proxy from "./config/proxy";
7 |
8 | const { REACT_APP_ENV = "" } = process.env;
9 |
10 | // https://vitejs.dev/config/
11 | export default defineConfig({
12 | resolve: {
13 | alias: [
14 | { find: "@", replacement: "/src" },
15 | { find: /^~/, replacement: "" }, // https://github.com/vitejs/vite/issues/2185
16 | ],
17 | },
18 | server: {
19 | proxy: proxy[REACT_APP_ENV],
20 | },
21 | plugins: [
22 | react(),
23 | svgrPlugin({
24 | svgrOptions: {},
25 | }),
26 | vitePluginForArco({
27 | theme: "@arco-themes/react-arco-pro",
28 | modifyVars: {
29 | "arcoblue-6": "#165DFF",
30 | },
31 | }),
32 | viteMockServe({
33 | mockPath: "./mock",
34 | localEnabled: !!!REACT_APP_ENV,
35 | }),
36 | ],
37 | css: {
38 | preprocessorOptions: {
39 | less: {
40 | javascriptEnabled: true,
41 | },
42 | },
43 | },
44 | build: {
45 | rollupOptions: {
46 | output: {
47 | manualChunks(id) {
48 | if (id.includes('node_modules')) {
49 | return 'vendor';
50 | };
51 | },
52 | },
53 | },
54 | },
55 | });
56 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/tabs/index.tsx:
--------------------------------------------------------------------------------
1 | import { Fragment } from "react";
2 | import { TabsProps, Tabs as ArcoTabs } from "@arco-design/web-react";
3 | import { RecursionField, useFieldSchema } from "@formily/react";
4 | import { useTranslation } from "react-i18next";
5 | import { Icon } from "../__builtins__";
6 |
7 | type ComposedTabs = React.FC & {
8 | TabPane?: React.FC;
9 | };
10 |
11 | export const Tabs: ComposedTabs = (props) => {
12 | const fieldSchema = useFieldSchema();
13 | const { t } = useTranslation();
14 | return (
15 |
16 | {fieldSchema.mapProperties((schema, key) => {
17 | return (
18 |
23 |
27 | {t(schema.title)}
28 |
29 | ) : (
30 | t(schema.title)
31 | )
32 | }
33 | >
34 |
35 |
36 | );
37 | })}
38 |
39 | );
40 | };
41 |
42 | Tabs.TabPane = () => {
43 | return ;
44 | };
45 |
46 | export default Tabs;
47 |
--------------------------------------------------------------------------------
/li-app/internal/data/hook/user.go:
--------------------------------------------------------------------------------
1 | package hook
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/BeanWei/li/li-app/internal/data"
7 | "github.com/BeanWei/li/li-app/internal/data/ent"
8 | "github.com/BeanWei/li/li-app/internal/data/ent/hook"
9 | "github.com/BeanWei/li/li-app/internal/data/ent/user"
10 | "github.com/gogf/gf/v2/util/grand"
11 | )
12 |
13 | func init() {
14 | ent.LiClient().User.Use(
15 | // 生成盐值和加密密码
16 | hook.If(
17 | func(next ent.Mutator) ent.Mutator {
18 | return hook.UserFunc(func(ctx context.Context, m *ent.UserMutation) (ent.Value, error) {
19 | password, _ := m.Password()
20 | salt := grand.S(10)
21 | m.SetSalt(salt)
22 | m.SetPassword(data.User.HashPassword(password, salt))
23 | return next.Mutate(ctx, m)
24 | })
25 | },
26 | hook.And(
27 | hook.HasOp(ent.OpCreate),
28 | hook.HasFields(user.FieldPassword),
29 | ),
30 | ),
31 | // 移除缓存中的用户信息
32 | hook.On(
33 | func(next ent.Mutator) ent.Mutator {
34 | return hook.UserFunc(func(ctx context.Context, m *ent.UserMutation) (ent.Value, error) {
35 | val, err := next.Mutate(ctx, m)
36 | if err != nil {
37 | return val, err
38 | }
39 | var ids []interface{}
40 | if id, ok := m.ID(); ok {
41 | ids = append(ids, id)
42 | }
43 | data.User.RemoveUserCache(ctx, ids...)
44 | return val, err
45 | })
46 | },
47 | ent.OpUpdate|ent.OpUpdateOne|ent.OpDelete|ent.OpDeleteOne,
48 | ),
49 | )
50 | }
51 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_money.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func Money(name string) *moneyBuilder {
9 | return &moneyBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeString,
13 | XComponent: ui.ComponentMoney,
14 | XComponentProps: make(map[string]interface{}),
15 | XDecorator: ui.DecoratorFormItem,
16 | },
17 | }}
18 | }
19 |
20 | type moneyBuilder struct {
21 | *NodeBuilder
22 | }
23 |
24 | func (b *moneyBuilder) AC(f ac.AC) *moneyBuilder {
25 | b.schema.AC = f
26 | return b
27 | }
28 |
29 | func (b *moneyBuilder) Title(title string) *moneyBuilder {
30 | b.SetTitle(title)
31 | return b
32 | }
33 |
34 | func (b *moneyBuilder) Description(description string) *moneyBuilder {
35 | b.SetDescription(description)
36 | return b
37 | }
38 |
39 | func (b *moneyBuilder) Default(value interface{}) *moneyBuilder {
40 | b.schema.Default = value
41 | return b
42 | }
43 |
44 | func (b *moneyBuilder) Step(step int) *moneyBuilder {
45 | b.schema.XComponentProps["step"] = step
46 | return b
47 | }
48 |
49 | func (b *moneyBuilder) Precision(precision int) *moneyBuilder {
50 | b.schema.XComponentProps["precision"] = precision
51 | return b
52 | }
53 |
54 | func (b *moneyBuilder) Currency(currency string) *moneyBuilder {
55 | b.schema.XComponentProps["currency"] = currency
56 | return b
57 | }
58 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_password.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func Password(name string) *passwordBuilder {
9 | return &passwordBuilder{&textBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeString,
13 | XComponent: ui.ComponentPassword,
14 | XComponentProps: make(map[string]interface{}),
15 | XDecorator: ui.DecoratorFormItem,
16 | },
17 | }}}
18 | }
19 |
20 | type passwordBuilder struct {
21 | *textBuilder
22 | }
23 |
24 | func (b *passwordBuilder) AC(f ac.AC) *passwordBuilder {
25 | b.schema.AC = f
26 | return b
27 | }
28 |
29 | func (b *passwordBuilder) Title(title string) *passwordBuilder {
30 | b.SetTitle(title)
31 | return b
32 | }
33 |
34 | func (b *passwordBuilder) Description(description string) *passwordBuilder {
35 | b.SetDescription(description)
36 | return b
37 | }
38 |
39 | func (b *passwordBuilder) Default(value interface{}) *passwordBuilder {
40 | b.schema.Default = value
41 | return b
42 | }
43 |
44 | func (b *passwordBuilder) VisibilityToggle(visibilityToggle bool) *passwordBuilder {
45 | b.schema.XComponentProps["visibilityToggle"] = visibilityToggle
46 | return b
47 | }
48 |
49 | func (b *passwordBuilder) DefaultVisibility(defaultVisibility bool) *passwordBuilder {
50 | b.schema.XComponentProps["defaultVisibility"] = defaultVisibility
51 | return b
52 | }
53 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/document-title/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { createContext, useContext, useEffect, useState } from "react";
2 | import { Helmet } from "react-helmet";
3 |
4 | interface DocumentTitleContextProps {
5 | title?: any;
6 | setTitle?: (title?: any) => void;
7 | }
8 |
9 | export const DocumentTitleContext = createContext({
10 | title: null,
11 | setTitle() {},
12 | });
13 |
14 | export const DocumentTitleProvider: React.FC<
15 | React.PropsWithChildren<{
16 | addonBefore?: string;
17 | addonAfter?: string;
18 | }>
19 | > = (props) => {
20 | const { addonBefore, addonAfter } = props;
21 | const [title, setTitle] = useState("");
22 | const documentTitle = title
23 | ? `${addonBefore ? `${addonBefore} | ` : ""}${title || ""}${
24 | addonAfter ? ` | ${addonAfter}` : ""
25 | }`
26 | : "Li Admin";
27 | return (
28 |
34 |
35 | {documentTitle}
36 |
37 | {props.children}
38 |
39 | );
40 | };
41 |
42 | export const useDocumentTitle = () => {
43 | return useContext(DocumentTitleContext);
44 | };
45 |
46 | export const useCurrentDocumentTitle = (title: string) => {
47 | const { setTitle } = useDocumentTitle();
48 | useEffect(() => {
49 | setTitle?.(title);
50 | }, []);
51 | };
52 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/schema/flow_definition.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | import (
4 | "entgo.io/ent"
5 | "entgo.io/ent/schema/edge"
6 | "entgo.io/ent/schema/field"
7 | "github.com/BeanWei/li/li-engine/contrib/lient/mixin"
8 | )
9 |
10 | type (
11 | FlowDefinition struct {
12 | ent.Schema
13 | }
14 | FlowModel []*FlowElement
15 | FlowElement struct {
16 | Name string
17 | Key string
18 | Type string
19 | FlowType FlowElementFlowType
20 | Outgoing []string
21 | Incoming []string
22 | Properties map[string]interface{}
23 | }
24 | FlowElementFlowType string
25 | )
26 |
27 | func (fm *FlowModel) ElementMap() map[string]*FlowElement {
28 | femap := make(map[string]*FlowElement)
29 | for _, fe := range *fm {
30 | femap[fe.Key] = fe
31 | }
32 | return femap
33 | }
34 |
35 | func (FlowDefinition) Mixin() []ent.Mixin {
36 | return []ent.Mixin{
37 | mixin.XID{},
38 | mixin.Time{},
39 | }
40 | }
41 |
42 | func (FlowDefinition) Fields() []ent.Field {
43 | return []ent.Field{
44 | field.String("name").
45 | NotEmpty().
46 | Comment("流程名称"),
47 | field.Int8("status").
48 | Default(0).
49 | Comment("状态(1.初始态 1.编辑中 2.已上线)"),
50 | field.JSON("model", FlowModel{}).
51 | Comment("流程模型"),
52 | field.String("remark").
53 | Default("").
54 | Optional().
55 | Comment("备注"),
56 | }
57 | }
58 |
59 | func (FlowDefinition) Edges() []ent.Edge {
60 | return []ent.Edge{
61 | edge.To("flow_deployments", FlowDeployment.Type),
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/admin.go:
--------------------------------------------------------------------------------
1 | package admin
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/app/admin/consts"
5 | "github.com/BeanWei/li/li-app/internal/app/admin/controller"
6 | "github.com/BeanWei/li/li-app/internal/app/admin/view"
7 | engine "github.com/BeanWei/li/li-engine"
8 | )
9 |
10 | func Init() {
11 | engine.NewApp(&engine.App{
12 | Title: "Li Admin",
13 | Copyright: "Powered by ❤️璃❤️",
14 | Entry: consts.AppEntry,
15 | Menus: []*engine.AppMenu{
16 | {
17 | Title: "仪表盘",
18 | Icon: "IconDashboard",
19 | Children: []*engine.AppMenu{
20 | {
21 | Title: "工作台",
22 | Page: new(view.DashboardWorkplace),
23 | IsHome: true,
24 | },
25 | },
26 | },
27 | {
28 | Title: "系统管理",
29 | Icon: "IconSettings",
30 | Children: []*engine.AppMenu{
31 | {
32 | Title: "用户管理",
33 | Page: new(view.SystemUser),
34 | },
35 | },
36 | },
37 | {
38 | Title: "博客应用",
39 | Icon: "IconEdit",
40 | Children: []*engine.AppMenu{
41 | {
42 | Title: "文章管理",
43 | Page: new(view.BlogPost),
44 | },
45 | {
46 | Title: "标签管理",
47 | Page: new(view.BlogTag),
48 | },
49 | {
50 | Title: "评论管理",
51 | Page: new(view.BlogComment),
52 | },
53 | },
54 | },
55 | },
56 | NavItems: view.NavItems(),
57 | Binding: &engine.AppBinding{
58 | GetCurrentUserController: controller.UserProfile,
59 | SignForm: view.SignFormNode(),
60 | },
61 | })
62 | }
63 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_uploadavatar.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func UploadAvatar(name string) *uploadavatarBuilder {
9 | return &uploadavatarBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeString,
13 | XComponent: ui.ComponentUploadAvatar,
14 | XComponentProps: map[string]interface{}{
15 | "action": "/api/liql",
16 | "data": map[string]string{
17 | "operation": "@uploadFile",
18 | },
19 | },
20 | XDecorator: ui.DecoratorFormItem,
21 | },
22 | }}
23 | }
24 |
25 | type uploadavatarBuilder struct {
26 | *NodeBuilder
27 | }
28 |
29 | func (b *uploadavatarBuilder) AC(f ac.AC) *uploadavatarBuilder {
30 | b.schema.AC = f
31 | return b
32 | }
33 |
34 | func (b *uploadavatarBuilder) Title(title string) *uploadavatarBuilder {
35 | b.SetTitle(title)
36 | return b
37 | }
38 |
39 | func (b *uploadavatarBuilder) Description(description string) *uploadavatarBuilder {
40 | b.SetDescription(description)
41 | return b
42 | }
43 |
44 | func (b *uploadavatarBuilder) Default(value interface{}) *uploadavatarBuilder {
45 | b.schema.Default = value
46 | return b
47 | }
48 |
49 | func (b *uploadavatarBuilder) Accept(accept string) *uploadavatarBuilder {
50 | b.schema.XComponentProps["accept"] = accept
51 | return b
52 | }
53 |
54 | func (b *uploadavatarBuilder) Tip(tip string) *uploadavatarBuilder {
55 | b.schema.XComponentProps["tip"] = tip
56 | return b
57 | }
58 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/schema/flow_node_instance.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | import (
4 | "entgo.io/ent"
5 | "entgo.io/ent/schema/edge"
6 | "entgo.io/ent/schema/field"
7 | "entgo.io/ent/schema/index"
8 | "github.com/BeanWei/li/li-engine/contrib/lient/mixin"
9 | )
10 |
11 | type FlowNodeInstance struct {
12 | ent.Schema
13 | }
14 |
15 | func (FlowNodeInstance) Mixin() []ent.Mixin {
16 | return []ent.Mixin{
17 | mixin.XID{},
18 | mixin.Time{},
19 | }
20 | }
21 |
22 | func (FlowNodeInstance) Fields() []ent.Field {
23 | return []ent.Field{
24 | field.String("flow_instance_id").
25 | NotEmpty().
26 | Comment("流程执行实例ID"),
27 | field.String("source_flow_node_instance_id").
28 | Default("").
29 | Optional().
30 | Comment("上一个节点执行实例ID"),
31 | field.String("flow_instance_data_id").
32 | Default("").
33 | Optional().
34 | Comment("实例数据ID"),
35 | field.String("node_key").
36 | NotEmpty().
37 | Comment("节点唯一标示"),
38 | field.String("source_node_key").
39 | Default("").
40 | Optional().
41 | Comment("上一节点唯一标示"),
42 | field.Int8("status").
43 | Default(0).
44 | Comment("状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)"),
45 | }
46 | }
47 |
48 | func (FlowNodeInstance) Edges() []ent.Edge {
49 | return []ent.Edge{
50 | edge.From("flow_instance", FlowInstance.Type).
51 | Ref("flow_node_instances").
52 | Field("flow_instance_id").
53 | Unique().
54 | Required(),
55 | }
56 | }
57 |
58 | func (FlowNodeInstance) Indexes() []ent.Index {
59 | return []ent.Index{
60 | index.Fields("flow_instance_id"),
61 | index.Fields("status"),
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/li-web/packages/pro-components/src/li-flow/nodes/ExclusiveGateway.ts:
--------------------------------------------------------------------------------
1 | import { h, PolygonNode, PolygonNodeModel } from "@logicflow/core";
2 | import { eletype, node } from "../config";
3 |
4 | class ExclusiveGatewayModel extends PolygonNodeModel {
5 | static extendKey = "ExclusiveGatewayModel";
6 | constructor(data: any, graphModel: any) {
7 | if (!data.text) {
8 | data.text = "";
9 | }
10 | if (typeof data.text === "string") {
11 | data.text = {
12 | value: data.text,
13 | x: data.x,
14 | y: data.y + 40,
15 | };
16 | }
17 | super(data, graphModel);
18 | this.points = [
19 | [25, 0],
20 | [50, 25],
21 | [25, 50],
22 | [0, 25],
23 | ];
24 | }
25 | }
26 |
27 | class ExclusiveGatewayView extends PolygonNode {
28 | static extendKey = "ExclusiveGatewayNode";
29 | getShape(): any {
30 | const { model } = this.props;
31 | const style = model.getNodeStyle();
32 | return h("g", {}, [
33 | h("image", {
34 | ...style,
35 | x: model.x - (1 / 2) * model.width,
36 | y: model.y - (1 / 2) * model.height,
37 | width: model.width,
38 | height: model.height,
39 | // 根据宽高缩放
40 | preserveAspectRatio: "none meet",
41 | href: node.exclusivegateway.imgsrc,
42 | }),
43 | ]);
44 | }
45 | }
46 |
47 | const ExclusiveGateway = {
48 | type: eletype.exclusivegateway,
49 | view: ExclusiveGatewayView,
50 | model: ExclusiveGatewayModel,
51 | };
52 |
53 | export { ExclusiveGatewayView, ExclusiveGatewayModel };
54 | export default ExclusiveGateway;
55 |
--------------------------------------------------------------------------------
/li-app/internal/app/admin/view/app.nav.go:
--------------------------------------------------------------------------------
1 | package view
2 |
3 | import (
4 | "github.com/BeanWei/li/li-app/internal/data/ent/user"
5 | "github.com/BeanWei/li/li-engine/view"
6 | "github.com/BeanWei/li/li-engine/view/com"
7 | "github.com/BeanWei/li/li-engine/view/node"
8 | )
9 |
10 | func NavItems() []view.Node {
11 | return []view.Node{
12 | com.LangSwitch("navLangSwitch"),
13 | com.ThemeSwitch("navThemeSwitch"),
14 | node.DropdownMenu("navUser").
15 | TriggerPopupStyle(map[string]interface{}{
16 | "marginRight": "28px",
17 | }).
18 | Droplist(
19 | node.DropdownMenuItem("updateProfile").
20 | Children(
21 | node.ActionFormDrawer("action").
22 | Title("用户设置").
23 | IsMenuItem(true).
24 | InitialValues(map[string]interface{}{
25 | "nickname": `{{global.currentUser.nickname}}`,
26 | }).
27 | Body(
28 | user.NodeNickname(),
29 | ).
30 | Footer(
31 | node.ActionFormDrawerCancel("cancel"),
32 | node.ActionFormDrawerSubmit("submit"),
33 | ),
34 | ),
35 | node.DropdownMenuItem("updatePassword").Title("修改密码"),
36 | node.Divider("divider").
37 | Style(map[string]interface{}{
38 | "margin": "4px 0",
39 | }),
40 | node.DropdownMenuItem("signOut").Title("退出登录"),
41 | ).
42 | Children(
43 | node.Avatar("currentUser").
44 | Size(32).
45 | Src(`{{global.currentUser.avatar}}`).
46 | Style(map[string]interface{}{
47 | "cursor": "pointer",
48 | }).
49 | SetXContent(`{{global.currentUser.nickname?.[0] || "Li"}}`),
50 | ),
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "schema-components",
3 | "version": "0.0.0",
4 | "main": "./src/index.ts",
5 | "license": "MIT",
6 | "sideEffects": [
7 | "dist/*",
8 | "esm/*.js",
9 | "lib/*.js",
10 | "src/*.ts",
11 | "*.less",
12 | "**/*/style.js"
13 | ],
14 | "scripts": {
15 | "start": "dumi dev",
16 | "lint": "eslint *.tsx"
17 | },
18 | "devDependencies": {
19 | "@types/lodash": "^4.14.182",
20 | "config": "workspace:*",
21 | "dumi": "^1.1.40",
22 | "tsconfig": "workspace:*",
23 | "typescript": "^4.6.4"
24 | },
25 | "peerDependencies": {
26 | "@arco-design/web-react": "^2.30.0",
27 | "@types/react": "^18.0.8",
28 | "@types/react-dom": "^18.0.3",
29 | "react": "^18.1.0",
30 | "react-dom": "^18.1.0"
31 | },
32 | "dependencies": {
33 | "@antv/antv-spec": "^0.1.0-alpha.18",
34 | "@antv/chart-advisor": "^2.1.0-alpha.0",
35 | "@antv/g2plot": "^2.4.16",
36 | "@antv/g6": "^4.6.4",
37 | "@formily/core": "2.1.0",
38 | "@formily/grid": "2.1.0",
39 | "@formily/json-schema": "2.1.0",
40 | "@formily/react": "2.1.0",
41 | "@formily/reactive": "2.1.0",
42 | "@formily/reactive-react": "2.1.0",
43 | "@formily/shared": "2.1.0",
44 | "classnames": "^2.3.1",
45 | "lodash": "^4.17.21",
46 | "pro-components": "workspace:*",
47 | "pro-utils": "workspace:*",
48 | "react-i18next": "^11.16.7",
49 | "react-router-dom": "^6.3.0",
50 | "react-sortable-hoc": "^2.0.0",
51 | "react-sticky-box": "^1.0.2"
52 | },
53 | "publishConfig": {
54 | "access": "public"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/config.go:
--------------------------------------------------------------------------------
1 | // Code generated by entc, DO NOT EDIT.
2 |
3 | package ent
4 |
5 | import (
6 | "entgo.io/ent"
7 | "entgo.io/ent/dialect"
8 | )
9 |
10 | // Option function to configure the client.
11 | type Option func(*config)
12 |
13 | // Config is the configuration for the client and its builder.
14 | type config struct {
15 | // driver used for executing database requests.
16 | driver dialect.Driver
17 | // debug enable a debug logging.
18 | debug bool
19 | // log used for logging on debug mode.
20 | log func(...interface{})
21 | // hooks to execute on mutations.
22 | hooks *hooks
23 | }
24 |
25 | // hooks per client, for fast access.
26 | type hooks struct {
27 | FlowDefinition []ent.Hook
28 | FlowDeployment []ent.Hook
29 | FlowInstance []ent.Hook
30 | FlowInstanceData []ent.Hook
31 | FlowNodeInstance []ent.Hook
32 | FlowNodeInstanceLog []ent.Hook
33 | }
34 |
35 | // Options applies the options on the config object.
36 | func (c *config) options(opts ...Option) {
37 | for _, opt := range opts {
38 | opt(c)
39 | }
40 | if c.debug {
41 | c.driver = dialect.Debug(c.driver, c.log)
42 | }
43 | }
44 |
45 | // Debug enables debug logging on the ent.Driver.
46 | func Debug() Option {
47 | return func(c *config) {
48 | c.debug = true
49 | }
50 | }
51 |
52 | // Log sets the logging function for debug mode.
53 | func Log(fn func(...interface{})) Option {
54 | return func(c *config) {
55 | c.log = fn
56 | }
57 | }
58 |
59 | // Driver configures the client driver.
60 | func Driver(driver dialect.Driver) Option {
61 | return func(c *config) {
62 | c.driver = driver
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_dropdownmenu.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view"
6 | "github.com/BeanWei/li/li-engine/view/ui"
7 | )
8 |
9 | func DropdownMenu(name string) *dropdownmenuBuilder {
10 | return &dropdownmenuBuilder{&NodeBuilder{
11 | schema: &ui.Schema{
12 | Name: name,
13 | Type: ui.SchemaTypeVoid,
14 | XComponent: ui.ComponentDropdownMenu,
15 | XComponentProps: map[string]interface{}{
16 | "triggerProps": map[string]interface{}{
17 | "popupStyle": make(map[string]interface{}),
18 | },
19 | },
20 | },
21 | }}
22 | }
23 |
24 | type dropdownmenuBuilder struct {
25 | *NodeBuilder
26 | }
27 |
28 | func (b *dropdownmenuBuilder) AC(f ac.AC) *dropdownmenuBuilder {
29 | b.schema.AC = f
30 | return b
31 | }
32 |
33 | func (b *dropdownmenuBuilder) Droplist(elements ...view.Node) *dropdownmenuBuilder {
34 | b.Items(elements...)
35 | return b
36 | }
37 |
38 | func (b *dropdownmenuBuilder) Position(position string) *dropdownmenuBuilder {
39 | b.schema.XComponentProps["position"] = position
40 | return b
41 | }
42 |
43 | func (b *dropdownmenuBuilder) Trigger(trigger string) *dropdownmenuBuilder {
44 | b.schema.XComponentProps["trigger"] = trigger
45 | return b
46 | }
47 |
48 | func (b *dropdownmenuBuilder) TriggerPopupStyle(style map[string]interface{}) *dropdownmenuBuilder {
49 | triggerProps, ok := b.schema.XComponentProps["triggerProps"].(map[string]interface{})
50 | if !ok {
51 | return b
52 | }
53 | triggerProps["popupStyle"] = style
54 | b.schema.XComponentProps["triggerProps"] = triggerProps
55 | return b
56 | }
57 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_space.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | "github.com/gogf/gf/v2/container/gmap"
7 | )
8 |
9 | func Space(name string) *spaceBuilder {
10 | return &spaceBuilder{&NodeBuilder{
11 | schema: &ui.Schema{
12 | Name: name,
13 | Type: ui.SchemaTypeVoid,
14 | XComponent: ui.ComponentSpace,
15 | XComponentProps: make(map[string]interface{}),
16 | Properties: gmap.NewListMap(),
17 | },
18 | }}
19 | }
20 |
21 | type spaceBuilder struct {
22 | *NodeBuilder
23 | }
24 |
25 | func (b *spaceBuilder) AC(f ac.AC) *spaceBuilder {
26 | b.schema.AC = f
27 | return b
28 | }
29 |
30 | func (b *spaceBuilder) Title(title string) *spaceBuilder {
31 | b.SetTitle(title)
32 | return b
33 | }
34 |
35 | func (b *spaceBuilder) Description(description string) *spaceBuilder {
36 | b.SetDescription(description)
37 | return b
38 | }
39 |
40 | func (b *spaceBuilder) Align(align string) *spaceBuilder {
41 | b.schema.XComponentProps["align"] = align
42 | return b
43 | }
44 |
45 | func (b *spaceBuilder) Direction(direction string) *spaceBuilder {
46 | b.schema.XComponentProps["direction"] = direction
47 | return b
48 | }
49 |
50 | func (b *spaceBuilder) Size(size int) *spaceBuilder {
51 | b.schema.XComponentProps["size"] = size
52 | return b
53 | }
54 |
55 | func (b *spaceBuilder) Wrap(wrap bool) *spaceBuilder {
56 | b.schema.XComponentProps["wrap"] = wrap
57 | return b
58 | }
59 |
60 | func (b *spaceBuilder) SplitByDivider() *spaceBuilder {
61 | b.schema.XComponentProps["split"] = "divider"
62 | return b
63 | }
64 |
--------------------------------------------------------------------------------
/li-engine/contrib/liflow/ent/schema/flow_instance_comment.go:
--------------------------------------------------------------------------------
1 | package schema
2 |
3 | // import (
4 | // "entgo.io/ent"
5 | // "entgo.io/ent/schema/field"
6 | // "entgo.io/ent/schema/index"
7 | // "github.com/BeanWei/li/li-engine/contrib/lient/mixin"
8 | // )
9 |
10 | // type FlowInstanceComment struct {
11 | // ent.Schema
12 | // }
13 |
14 | // func (FlowInstanceComment) Mixin() []ent.Mixin {
15 | // return []ent.Mixin{
16 | // mixin.XID{},
17 | // }
18 | // }
19 |
20 | // func (FlowInstanceComment) Fields() []ent.Field {
21 | // return []ent.Field{
22 | // field.String("flow_instance_id").
23 | // NotEmpty().
24 | // Comment("流程实例ID"),
25 | // field.String("flow_node_instance_id").
26 | // NotEmpty().
27 | // Comment("节点实例ID"),
28 | // field.Int8("type").
29 | // Default(0).
30 | // Comment("类型(1:事件 2:意见)"),
31 | // field.Int8("action").
32 | // Default(0).
33 | // Comment("操作(1:通过 2:拒绝 3:驳回)"),
34 | // field.String("user_id").
35 | // Default("").
36 | // Optional().
37 | // Comment("审批人"),
38 | // field.Int64("start_at").
39 | // Optional().
40 | // Comment("开始时间"),
41 | // field.Int64("end_at").
42 | // Optional().
43 | // Comment("结束时间"),
44 | // field.String("content").
45 | // Default("").
46 | // Optional().
47 | // Comment("审批信息"),
48 | // field.Strings("attachments").
49 | // Default([]string{}).
50 | // Optional().
51 | // Comment("审批附件"),
52 | // }
53 | // }
54 |
55 | // func (FlowInstanceComment) Indexes() []ent.Index {
56 | // return []ent.Index{
57 | // index.Fields("flow_instance_id"),
58 | // index.Fields("flow_node_instance_id"),
59 | // }
60 | // }
61 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
❤️ LI ❤️
3 |
4 | a next-generation low-code & fullstack app to create web services | 下一代 低代码&全栈类&为web服务 的应用开发框架(当前专注场景在后台系统)
5 |
6 | ---
7 |
8 | ## 🚀 简介
9 | Li 是一个低代码 **全栈类** 的应用开发框架。她使用 **Go** 代码描述前端页面的 **Schema** , 基于图ORM框架 **ent** 的代码生成能力,只需要定义好数据表模型,在模型上添加上视图的注解,就能帮你自动生成完整的增删改查的 `Controller` & `View` & `AC<权限控制器>`,让你专注于业务开发。
10 |
11 | 代码生成并不是 Li 的核心能力,Li 专注于快速构建视图,处理复杂的 数据权限,操作权限,字段权限。
12 |
13 | ## 🌈 特性
14 | + **易于上手**:会基础的 Go 即可
15 | + **例子完整**:li-app 目录为真实的实战例子
16 | + **功能强大**:快速构建应用,灵活性高,能够处理复杂权限,加上代码生成加快业务开发
17 | + **大量组件**:支持后台管理系统的常见组件
18 | + **权限管理**:Li 具备完备的权限控制,能够同时控制视图的接口请求
19 | + **前端零代码**:前端页面按照开发者自定义的schema自动构建,无需处理前端代码
20 |
21 | ## 🧐 为什么要做 Li ?
22 | * 1: 通用的应用构建存在大量的重复劳动
23 | * 2: 基础的代码生成无法完美的服务于前端
24 | * 3: 权限处理繁琐
25 |
26 | 为了解决上面这些问题,**Li** 诞生了,她很年幼却很强大,而且目标很远大。
27 |
28 | ## 📟 技术体系
29 | **后端:**
30 | Golang, GoFrame, Ent ...
31 |
32 | **前端:**
33 | React, TypeScript, Formily, Arco-Design ...
34 |
35 | ## ⌨️ 快速开始
36 | https://github.com/BeanWei/li-quickstart
37 |
38 | ## 🏗️ 本地开发 (示例仓库:https://github.com/BeanWei/li-example)
39 | * 1: cd li-web & pnpm
40 | * 2: cd li-web/apps/admin & pnpm dev
41 | * 3: cd li-app, 配置 config.yaml, make generate & make migrate
42 | * 4: 创建管理员账号:go run li.go user-create -u=你的邮箱 -p=你的密码 -n=Admin -a=true
43 | * 5: 浏览器打开 localhost:3000
44 | * 6: Just for fun~~~
45 |
46 | ## ⛰ 演示截图
47 |
48 |
49 |  |
50 |  |
51 |
52 |
53 |
54 | ---
55 |
56 |
57 | 作者 Bean.Wei / vx: zlnwcq
58 |
59 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/core/SchemaComponent.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | IRecursionFieldProps,
3 | ISchemaFieldProps,
4 | RecursionField,
5 | Schema,
6 | } from "@formily/react";
7 | import { useMemo } from "react";
8 | import { SchemaComponentOptions } from "./SchemaComponentOptions";
9 |
10 | function toSchema(schema?: any) {
11 | if (!schema) return new Schema({});
12 | if (Schema.isSchemaInstance(schema)) {
13 | return schema;
14 | }
15 | if (schema.name) {
16 | return new Schema({
17 | type: "object",
18 | properties: {
19 | [schema.name]: schema,
20 | },
21 | });
22 | }
23 | return new Schema(schema);
24 | }
25 |
26 | const useMemoizedSchema = (schema: any) => {
27 | return useMemo(() => toSchema(schema), []);
28 | };
29 |
30 | const RecursionSchemaComponent = (props: ISchemaFieldProps) => {
31 | const { components, scope, schema, ...others } = props;
32 | return (
33 |
34 |
35 |
36 | );
37 | };
38 |
39 | const MemoizedSchemaComponent = (props: ISchemaFieldProps) => {
40 | const { schema, ...others } = props;
41 | const s = useMemoizedSchema(schema);
42 | return ;
43 | };
44 |
45 | export const SchemaComponent = (
46 | props: (ISchemaFieldProps | IRecursionFieldProps) & { memoized?: boolean }
47 | ) => {
48 | const { memoized, ...others } = props;
49 | if (memoized) {
50 | return ;
51 | }
52 | return ;
53 | };
54 |
--------------------------------------------------------------------------------
/li-web/apps/admin/src/modules/sign-page/index.tsx:
--------------------------------------------------------------------------------
1 | import Logo from "@/assets/logo.svg";
2 | import { Layout } from "@arco-design/web-react";
3 | import { useRequest } from "pro-utils";
4 | import { SchemaComponent } from "schema-components";
5 | import { Loading } from "../components";
6 | import { LangSwitch } from "../schema-components";
7 | import styles from "./index.module.less";
8 |
9 | export const SignPage: React.FC = (props) => {
10 | const { data = {}, loading } = useRequest("@getSignView");
11 |
12 | if (loading) {
13 | return ;
14 | }
15 |
16 | const {
17 | title = "Li Admin",
18 | description,
19 | copyright = "Li Admin",
20 | logo,
21 | body = {},
22 | } = data;
23 |
24 | return (
25 |
26 |
27 |
33 |
34 |
35 |
36 |
37 |
38 | {logo ?
: }
39 |
40 |
{title}
41 |
42 | {description ? (
43 |
{description}
44 | ) : null}
45 |
46 |
47 |
48 |
{copyright}
49 |
50 | );
51 | };
52 |
53 | export default SignPage;
54 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/date-picker/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { DatePicker as ArcoDatePicker } from "@arco-design/web-react";
3 | import type { DatePickerProps, RangePickerProps } from "@arco-design/web-react";
4 | import { connect, mapReadPretty } from "@formily/react";
5 | import { isArr } from "@formily/shared";
6 | import cls from "classnames";
7 | import { usePrefixCls } from "../__builtins__";
8 |
9 | type ComposedDatePicker = React.FC & {
10 | RangePicker?: React.FC;
11 | };
12 |
13 | const ReadPretty: React.FC = (props: any) => {
14 | if (!props.value) {
15 | return -
;
16 | }
17 | const prefixCls = usePrefixCls("description-date-picker", props);
18 | const getLabels = () => {
19 | return isArr(props.value) ? props.value.join("~") : props.value;
20 | };
21 | return {getLabels()}
;
22 | };
23 |
24 | const BaseDatePicker: React.FC = (props) => {
25 | const { mode, ...rest } = props;
26 | switch (mode) {
27 | case "date":
28 | return ;
29 | case "week":
30 | return ;
31 | case "month":
32 | return ;
33 | case "year":
34 | return ;
35 | case "quarter":
36 | return ;
37 | default:
38 | return ;
39 | }
40 | };
41 |
42 | export const DatePicker: ComposedDatePicker = connect(
43 | BaseDatePicker,
44 | mapReadPretty(ReadPretty)
45 | );
46 |
47 | export default DatePicker;
48 |
--------------------------------------------------------------------------------
/li-web/packages/schema-components/src/components/array-items/index.less:
--------------------------------------------------------------------------------
1 | @import '~@arco-design/web-react/lib/style/theme/default.less';
2 |
3 | @array-items-prefix-cls: ~'@{prefix}-formily-array-items';
4 | @border-color-split: #303030;
5 |
6 | .@{array-items-prefix-cls}-item-inner {
7 | visibility: visible;
8 | }
9 |
10 | // fix https://github.com/alibaba/formily/issues/2891
11 | .@{array-items-prefix-cls}-item {
12 | z-index: 100000;
13 | }
14 |
15 | .@{array-items-prefix-cls}-card {
16 | display: flex;
17 | border: 1px solid @border-color-split;
18 | margin-bottom: 10px;
19 | padding: 3px 6px;
20 | justify-content: space-between;
21 |
22 | .@{prefix}-formily-item:not(.@{prefix}-formily-item-feedback-layout-popover) {
23 | margin-bottom: 0 !important;
24 |
25 | .@{prefix}-formily-item-help {
26 | position: absolute;
27 | font-size: 12px;
28 | top: 100%;
29 | width: 100%;
30 | margin-top: 3px;
31 | padding: 3px;
32 | z-index: 1;
33 | border-radius: 3px;
34 | box-shadow: 0 0 10px @border-color-split;
35 | }
36 | }
37 | }
38 |
39 | .@{array-items-prefix-cls}-divide {
40 | display: flex;
41 | border-bottom: 1px solid @border-color-split;
42 | padding: 10px 0;
43 | justify-content: space-between;
44 |
45 | .@{prefix}-formily-item:not(.@{prefix}-formily-item-feedback-layout-popover) {
46 | margin-bottom: 0 !important;
47 |
48 | .@{prefix}-formily-item-help {
49 | position: absolute;
50 | font-size: 12px;
51 | top: 100%;
52 | width: 100%;
53 | margin-top: 3px;
54 | padding: 3px;
55 | z-index: 1;
56 | border-radius: 3px;
57 | box-shadow: 0 0 10px @border-color-split;
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/li-engine/view/node/node_checkboxgroup.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "github.com/BeanWei/li/li-engine/ac"
5 | "github.com/BeanWei/li/li-engine/view/ui"
6 | )
7 |
8 | func CheckboxGroup(name string) *checkboxgroupBuilder {
9 | return &checkboxgroupBuilder{&NodeBuilder{
10 | schema: &ui.Schema{
11 | Name: name,
12 | Type: ui.SchemaTypeArray,
13 | XComponent: ui.ComponentCheckboxGroup,
14 | XComponentProps: make(map[string]interface{}),
15 | XDecorator: ui.DecoratorFormItem,
16 | Enum: make([]map[string]interface{}, 0),
17 | },
18 | }}
19 | }
20 |
21 | type checkboxgroupBuilder struct {
22 | *NodeBuilder
23 | }
24 |
25 | func (b *checkboxgroupBuilder) AC(f ac.AC) *checkboxgroupBuilder {
26 | b.schema.AC = f
27 | return b
28 | }
29 |
30 | func (b *checkboxgroupBuilder) Title(title string) *checkboxgroupBuilder {
31 | b.SetTitle(title)
32 | return b
33 | }
34 |
35 | func (b *checkboxgroupBuilder) Description(description string) *checkboxgroupBuilder {
36 | b.SetDescription(description)
37 | return b
38 | }
39 |
40 | func (b *checkboxgroupBuilder) Default(value interface{}) *checkboxgroupBuilder {
41 | b.schema.Default = value
42 | return b
43 | }
44 |
45 | func (b *checkboxgroupBuilder) Option(value interface{}, label ...string) *checkboxgroupBuilder {
46 | var label_ interface{}
47 | if len(label) > 0 {
48 | label_ = label[0]
49 | } else {
50 | label_ = value
51 | }
52 | b.schema.Enum = append(b.schema.Enum, map[string]interface{}{
53 | "label": label_,
54 | "value": value,
55 | })
56 | return b
57 | }
58 |
59 | func (b *checkboxgroupBuilder) Direction(direction string) *checkboxgroupBuilder {
60 | b.schema.XComponentProps["direction"] = direction
61 | return b
62 | }
63 |
--------------------------------------------------------------------------------