修改
This commit is contained in:
BIN
blazing.exe
Normal file
BIN
blazing.exe
Normal file
Binary file not shown.
@@ -1,72 +0,0 @@
|
||||
.PHONY: help
|
||||
help: ## 查看帮助
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
|
||||
|
||||
.PHONY: pack.template-simple
|
||||
pack.template-simple:
|
||||
@rm -fr temp
|
||||
@mkdir temp || exit 0
|
||||
@cd temp && git clone --depth=1 -b simple https://github.com/cool-team-official/cool-admin-go.git cool-admin-go-simple
|
||||
@rm -fr temp/cool-admin-go-simple/.git
|
||||
@cd temp && gf pack cool-admin-go-simple ../internal/packed/cool-admin-go-simple.go -n=packed -y
|
||||
@rm -fr temp/cool-admin-go-simple
|
||||
|
||||
.PHONY: pack.template-simple.ssh
|
||||
pack.template-simple.ssh:
|
||||
@rm -fr temp
|
||||
@mkdir temp || exit 0
|
||||
@cd temp && git clone --depth=1 -b simple git@github.com:cool-team-official/cool-admin-go.git cool-admin-go-simple
|
||||
@rm -fr temp/cool-admin-go-simple/.git
|
||||
@cd temp && gf pack cool-admin-go-simple ../internal/packed/cool-admin-go-simple.go -n=packed -y
|
||||
@rm -fr temp
|
||||
|
||||
.PHONY: pack.docs
|
||||
pack.docs:
|
||||
@rm -fr temp
|
||||
@mkdir temp || exit 0
|
||||
@cd temp && git clone --depth=1 -b gh-pages https://github.com/cool-team-official/cool-admin-go.git docs/cool-admin-go
|
||||
@rm -fr temp/docs/cool-admin-go/.git
|
||||
@cd temp && gf pack docs ../internal/packed/docs.go -n=packed -y
|
||||
@rm -fr temp/docs
|
||||
.PHONY: pack.docs.ssh
|
||||
pack.docs.ssh:
|
||||
@rm -fr temp
|
||||
@mkdir temp || exit 0
|
||||
@cd temp && git clone --depth=1 -b gh-pages git@github.com:cool-team-official/cool-admin-go.git docs/cool-admin-go
|
||||
@rm -fr temp/docs/cool-admin-go/.git
|
||||
@cd temp && gf pack docs ../internal/packed/docs.go -n=packed -y
|
||||
@rm -fr temp/docs
|
||||
|
||||
# Install/Update to the latest CLI tool.
|
||||
.PHONY: cli
|
||||
cli:
|
||||
@set -e; \
|
||||
wget -O gf https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \
|
||||
chmod +x gf && \
|
||||
./gf install && \
|
||||
rm ./gf
|
||||
|
||||
|
||||
|
||||
# Install/Update to the latest cool-tools.
|
||||
.PHONY: tools
|
||||
tools:
|
||||
@set -e; \
|
||||
curl -L https://download.fastgit.org/cool-team-official/cool-admin-go/releases/latest/download/cool-tools_$(shell go env GOOS)_$(shell go env GOARCH) -o ./cool-tools && \
|
||||
chmod +x cool-tools && \
|
||||
./cool-tools install && \
|
||||
rm ./cool-tools
|
||||
|
||||
|
||||
# Check and install cool-tools.
|
||||
.PHONY: tools.install
|
||||
tools.install:
|
||||
@set -e; \
|
||||
echo "Checking cool-tools..."; \
|
||||
cool-tools -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \
|
||||
echo "cool-tools is not installed, start proceeding auto installation..."; \
|
||||
make tools; \
|
||||
fi;\
|
||||
echo "cool-tools is installed.";
|
||||
@@ -1,19 +0,0 @@
|
||||
# CoolTools
|
||||
|
||||
[](https://pkg.go.dev/github.com/cool-team-official/cool-admin-go/cool-tools)
|
||||
|
||||
cool-tools is a collection of tools for cool people.
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
go install github.com/cool-team-official/cool-admin-go/cool-tools@latest
|
||||
```
|
||||
|
||||
## 使用
|
||||
|
||||
初始化一个新的 cool-admin-go 项目:
|
||||
|
||||
```bash
|
||||
cool-tools init <project-name>
|
||||
```
|
||||
@@ -1,32 +0,0 @@
|
||||
module github.com/cool-team-official/cool-admin-go/cool-tools
|
||||
|
||||
go 1.18
|
||||
|
||||
require github.com/gogf/gf/v2 v2.6.3
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/gorilla/websocket v1.5.1 // indirect
|
||||
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
||||
github.com/kr/pretty v0.3.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
@@ -1,72 +0,0 @@
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
|
||||
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/gogf/gf/v2 v2.6.3 h1:DoqeuwU98wotpFoDSQEx8RZbmJdK8KdGiJtzJeqpyIo=
|
||||
github.com/gogf/gf/v2 v2.6.3/go.mod h1:x2XONYcI4hRQ/4gMNbWHmZrNzSEIg20s2NULbzom5k0=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4=
|
||||
github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
|
||||
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -1,12 +0,0 @@
|
||||
|
||||
# CLI tool, only in development environment.
|
||||
# https://goframe.org/pages/viewpage.action?pageId=3673173
|
||||
gfcli:
|
||||
build:
|
||||
name: "cool-tools"
|
||||
arch: "all"
|
||||
system: "linux,darwin,windows"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
)
|
||||
|
||||
var (
|
||||
Main = gcmd.Command{
|
||||
Name: "cool-tools",
|
||||
Usage: "cool-tools [command] [args...]",
|
||||
Brief: "cool-tools is a collection of tools for cool people.",
|
||||
Description: `cool-tools is a collection of tools for cool people.`,
|
||||
}
|
||||
)
|
||||
@@ -1,328 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gbase64"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/genv"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gtag"
|
||||
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/utility/mlog"
|
||||
)
|
||||
|
||||
var (
|
||||
Build = cBuild{
|
||||
nodeNameInConfigFile: "gfcli.build",
|
||||
packedGoFileName: "internal/packed/build_pack_data.go",
|
||||
}
|
||||
)
|
||||
|
||||
type cBuild struct {
|
||||
g.Meta `name:"build" brief:"{cBuildBrief}" dc:"{cBuildDc}" eg:"{cBuildEg}" ad:"{cBuildAd}"`
|
||||
nodeNameInConfigFile string // nodeNameInConfigFile is the node name for compiler configurations in configuration file.
|
||||
packedGoFileName string // packedGoFileName specifies the file name for packing common folders into one single go file.
|
||||
}
|
||||
|
||||
const (
|
||||
cBuildBrief = `cross-building go project for lots of platforms`
|
||||
cBuildEg = `
|
||||
cool-tools build main.go
|
||||
cool-tools build main.go --pack public,template
|
||||
cool-tools build main.go --cgo
|
||||
cool-tools build main.go -m none
|
||||
cool-tools build main.go -n my-app -a all -s all
|
||||
cool-tools build main.go -n my-app -a amd64,386 -s linux -p .
|
||||
cool-tools build main.go -n my-app -v 1.0 -a amd64,386 -s linux,windows,darwin -p ./docker/bin
|
||||
`
|
||||
cBuildDc = `
|
||||
The "build" command is most commonly used command, which is designed as a powerful wrapper for
|
||||
"go build" command for convenience cross-compiling usage.
|
||||
It provides much more features for building binary:
|
||||
1. Cross-Compiling for many platforms and architectures.
|
||||
2. Configuration file support for compiling.
|
||||
3. Build-In Variables.
|
||||
`
|
||||
cBuildAd = `
|
||||
PLATFORMS
|
||||
darwin amd64,arm64
|
||||
freebsd 386,amd64,arm
|
||||
linux 386,amd64,arm,arm64,ppc64,ppc64le,mips,mipsle,mips64,mips64le
|
||||
netbsd 386,amd64,arm
|
||||
openbsd 386,amd64,arm
|
||||
windows 386,amd64
|
||||
`
|
||||
// https://golang.google.cn/doc/install/source
|
||||
cBuildPlatforms = `
|
||||
darwin amd64
|
||||
darwin arm64
|
||||
ios amd64
|
||||
ios arm64
|
||||
freebsd 386
|
||||
freebsd amd64
|
||||
freebsd arm
|
||||
linux 386
|
||||
linux amd64
|
||||
linux arm
|
||||
linux arm64
|
||||
linux ppc64
|
||||
linux ppc64le
|
||||
linux mips
|
||||
linux mipsle
|
||||
linux mips64
|
||||
linux mips64le
|
||||
netbsd 386
|
||||
netbsd amd64
|
||||
netbsd arm
|
||||
openbsd 386
|
||||
openbsd amd64
|
||||
openbsd arm
|
||||
windows 386
|
||||
windows amd64
|
||||
android arm
|
||||
dragonfly amd64
|
||||
plan9 386
|
||||
plan9 amd64
|
||||
solaris amd64
|
||||
`
|
||||
)
|
||||
|
||||
func init() {
|
||||
gtag.Sets(g.MapStrStr{
|
||||
`cBuildBrief`: cBuildBrief,
|
||||
`cBuildDc`: cBuildDc,
|
||||
`cBuildEg`: cBuildEg,
|
||||
`cBuildAd`: cBuildAd,
|
||||
})
|
||||
Main.AddObject(Build)
|
||||
}
|
||||
|
||||
type cBuildInput struct {
|
||||
g.Meta `name:"build" config:"gfcli.build"`
|
||||
File string `name:"FILE" arg:"true" brief:"building file path"`
|
||||
Name string `short:"n" name:"name" brief:"output binary name"`
|
||||
Version string `short:"v" name:"version" brief:"output binary version"`
|
||||
Arch string `short:"a" name:"arch" brief:"output binary architecture, multiple arch separated with ','"`
|
||||
System string `short:"s" name:"system" brief:"output binary system, multiple os separated with ','"`
|
||||
Output string `short:"o" name:"output" brief:"output binary path, used when building single binary file"`
|
||||
Path string `short:"p" name:"path" brief:"output binary directory path, default is './temp'" d:"./temp"`
|
||||
Extra string `short:"e" name:"extra" brief:"extra custom \"go build\" options"`
|
||||
Mod string `short:"m" name:"mod" brief:"like \"-mod\" option of \"go build\", use \"-m none\" to disable go module"`
|
||||
Cgo bool `short:"c" name:"cgo" brief:"enable or disable cgo feature, it's disabled in default" orphan:"true"`
|
||||
VarMap g.Map `short:"r" name:"varMap" brief:"custom built embedded variable into binary"`
|
||||
PackSrc string `short:"ps" name:"packSrc" brief:"pack one or more folders into one go file before building"`
|
||||
PackDst string `short:"pd" name:"packDst" brief:"temporary go file path for pack, this go file will be automatically removed after built" d:"internal/packed/build_pack_data.go"`
|
||||
ExitWhenError bool `short:"ew" name:"exitWhenError" brief:"exit building when any error occurs, default is false" orphan:"true"`
|
||||
}
|
||||
|
||||
type cBuildOutput struct{}
|
||||
|
||||
func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, err error) {
|
||||
mlog.SetHeaderPrint(true)
|
||||
|
||||
mlog.Debugf(`build input: %+v`, in)
|
||||
// Necessary check.
|
||||
if gproc.SearchBinary("go") == "" {
|
||||
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
|
||||
}
|
||||
|
||||
var (
|
||||
parser = gcmd.ParserFromCtx(ctx)
|
||||
file = parser.GetArg(2).String()
|
||||
)
|
||||
if len(file) < 1 {
|
||||
// Check and use the main.go file.
|
||||
if gfile.Exists("main.go") {
|
||||
file = "main.go"
|
||||
} else {
|
||||
mlog.Fatal("build file path cannot be empty")
|
||||
}
|
||||
}
|
||||
if in.Name == "" {
|
||||
in.Name = gfile.Name(file)
|
||||
}
|
||||
if len(in.Name) < 1 || in.Name == "*" {
|
||||
mlog.Fatal("name cannot be empty")
|
||||
}
|
||||
if in.Mod != "" && in.Mod != "none" {
|
||||
mlog.Debugf(`mod is %s`, in.Mod)
|
||||
if in.Extra == "" {
|
||||
in.Extra = fmt.Sprintf(`-mod=%s`, in.Mod)
|
||||
} else {
|
||||
in.Extra = fmt.Sprintf(`-mod=%s %s`, in.Mod, in.Extra)
|
||||
}
|
||||
}
|
||||
if in.Extra != "" {
|
||||
in.Extra += " "
|
||||
}
|
||||
var (
|
||||
customSystems = gstr.SplitAndTrim(in.System, ",")
|
||||
customArches = gstr.SplitAndTrim(in.Arch, ",")
|
||||
)
|
||||
if len(in.Version) > 0 {
|
||||
in.Path += "/" + in.Version
|
||||
}
|
||||
// System and arch checks.
|
||||
var (
|
||||
spaceRegex = regexp.MustCompile(`\s+`)
|
||||
platformMap = make(map[string]map[string]bool)
|
||||
)
|
||||
for _, line := range strings.Split(strings.TrimSpace(cBuildPlatforms), "\n") {
|
||||
line = gstr.Trim(line)
|
||||
line = spaceRegex.ReplaceAllString(line, " ")
|
||||
var (
|
||||
array = strings.Split(line, " ")
|
||||
system = strings.TrimSpace(array[0])
|
||||
arch = strings.TrimSpace(array[1])
|
||||
)
|
||||
if platformMap[system] == nil {
|
||||
platformMap[system] = make(map[string]bool)
|
||||
}
|
||||
platformMap[system][arch] = true
|
||||
}
|
||||
// Auto packing.
|
||||
if in.PackSrc != "" {
|
||||
if in.PackDst == "" {
|
||||
mlog.Fatal(`parameter "packDst" should not be empty when "packSrc" is used`)
|
||||
}
|
||||
if gfile.Exists(in.PackDst) && !gfile.IsFile(in.PackDst) {
|
||||
mlog.Fatalf(`parameter "packDst" path "%s" should be type of file not directory`, in.PackDst)
|
||||
}
|
||||
if !gfile.Exists(in.PackDst) {
|
||||
// Remove the go file that is automatically packed resource.
|
||||
defer func() {
|
||||
_ = gfile.Remove(in.PackDst)
|
||||
mlog.Printf(`remove the automatically generated resource go file: %s`, in.PackDst)
|
||||
}()
|
||||
}
|
||||
// remove black space in separator.
|
||||
in.PackSrc, _ = gregex.ReplaceString(`,\s+`, `,`, in.PackSrc)
|
||||
packCmd := fmt.Sprintf(`gf pack %s %s --keepPath=true`, in.PackSrc, in.PackDst)
|
||||
mlog.Print(packCmd)
|
||||
gproc.MustShellRun(ctx, packCmd)
|
||||
}
|
||||
|
||||
// Injected information by building flags.
|
||||
ldFlags := fmt.Sprintf(
|
||||
`-X 'github.com/gogf/gf/v2/os/gbuild.builtInVarStr=%v'`,
|
||||
c.getBuildInVarStr(ctx, in),
|
||||
)
|
||||
|
||||
// start building
|
||||
mlog.Print("start building...")
|
||||
if in.Cgo {
|
||||
genv.MustSet("CGO_ENABLED", "1")
|
||||
} else {
|
||||
genv.MustSet("CGO_ENABLED", "0")
|
||||
}
|
||||
var (
|
||||
cmd = ""
|
||||
ext = ""
|
||||
)
|
||||
for system, item := range platformMap {
|
||||
cmd = ""
|
||||
ext = ""
|
||||
if len(customSystems) > 0 && customSystems[0] != "all" && !gstr.InArray(customSystems, system) {
|
||||
continue
|
||||
}
|
||||
for arch := range item {
|
||||
if len(customArches) > 0 && customArches[0] != "all" && !gstr.InArray(customArches, arch) {
|
||||
continue
|
||||
}
|
||||
if len(customSystems) == 0 && len(customArches) == 0 {
|
||||
if runtime.GOOS == "windows" {
|
||||
ext = ".exe"
|
||||
}
|
||||
// Single binary building, output the binary to current working folder.
|
||||
output := ""
|
||||
if len(in.Output) > 0 {
|
||||
output = "-o " + in.Output + ext
|
||||
} else {
|
||||
output = "-o " + in.Name + ext
|
||||
}
|
||||
cmd = fmt.Sprintf(`go build %s -ldflags "%s" %s %s`, output, ldFlags, in.Extra, file)
|
||||
} else {
|
||||
// Cross-building, output the compiled binary to specified path.
|
||||
if system == "windows" {
|
||||
ext = ".exe"
|
||||
}
|
||||
genv.MustSet("GOOS", system)
|
||||
genv.MustSet("GOARCH", arch)
|
||||
cmd = fmt.Sprintf(
|
||||
`go build -o %s/%s/%s%s -ldflags "%s" %s%s`,
|
||||
in.Path, system+"_"+arch, in.Name, ext, ldFlags, in.Extra, file,
|
||||
)
|
||||
}
|
||||
mlog.Debug(cmd)
|
||||
// It's not necessary printing the complete command string.
|
||||
cmdShow, _ := gregex.ReplaceString(`\s+(-ldflags ".+?")\s+`, " ", cmd)
|
||||
mlog.Print(cmdShow)
|
||||
if result, err := gproc.ShellExec(ctx, cmd); err != nil {
|
||||
mlog.Printf(
|
||||
"failed to build, os:%s, arch:%s, error:\n%s\n\n%s\n",
|
||||
system, arch, gstr.Trim(result),
|
||||
`you may use command option "--debug" to enable debug info and check the details`,
|
||||
)
|
||||
if in.ExitWhenError {
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
mlog.Debug(gstr.Trim(result))
|
||||
}
|
||||
// single binary building.
|
||||
if len(customSystems) == 0 && len(customArches) == 0 {
|
||||
goto buildDone
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildDone:
|
||||
mlog.Print("done!")
|
||||
return
|
||||
}
|
||||
|
||||
// getBuildInVarMapJson retrieves and returns the custom build-in variables in configuration
|
||||
// file as json.
|
||||
func (c cBuild) getBuildInVarStr(ctx context.Context, in cBuildInput) string {
|
||||
buildInVarMap := in.VarMap
|
||||
if buildInVarMap == nil {
|
||||
buildInVarMap = make(g.Map)
|
||||
}
|
||||
buildInVarMap["builtGit"] = c.getGitCommit(ctx)
|
||||
buildInVarMap["builtTime"] = gtime.Now().String()
|
||||
b, err := json.Marshal(buildInVarMap)
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
return gbase64.EncodeToString(b)
|
||||
}
|
||||
|
||||
// getGitCommit retrieves and returns the latest git commit hash string if present.
|
||||
func (c cBuild) getGitCommit(ctx context.Context) string {
|
||||
if gproc.SearchBinary("git") == "" {
|
||||
return ""
|
||||
}
|
||||
var (
|
||||
cmd = `git log -1 --format="%cd %H" --date=format:"%Y-%m-%d %H:%M:%S"`
|
||||
s, _ = gproc.ShellExec(ctx, cmd)
|
||||
)
|
||||
mlog.Debug(cmd)
|
||||
if s != "" {
|
||||
if !gstr.Contains(s, "fatal") {
|
||||
return gstr.Trim(s)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/utility/allyes"
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/utility/mlog"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gres"
|
||||
"github.com/gogf/gf/v2/util/gtag"
|
||||
)
|
||||
|
||||
var (
|
||||
Pack = cPack{}
|
||||
)
|
||||
|
||||
type cPack struct {
|
||||
g.Meta `name:"pack" usage:"{cPackUsage}" brief:"{cPackBrief}" eg:"{cPackEg}"`
|
||||
}
|
||||
|
||||
const (
|
||||
cPackUsage = `cool-tools pack SRC DST`
|
||||
cPackBrief = `packing any file/directory to a resource file, or a go file`
|
||||
cPackEg = `
|
||||
cool-tools pack public data.bin
|
||||
cool-tools pack public,template data.bin
|
||||
cool-tools pack public,template packed/data.go
|
||||
cool-tools pack public,template,config packed/data.go
|
||||
cool-tools pack public,template,config packed/data.go -n=packed -p=/var/www/my-app
|
||||
cool-tools pack /var/www/public packed/data.go -n=packed
|
||||
`
|
||||
cPackSrcBrief = `source path for packing, which can be multiple source paths.`
|
||||
cPackDstBrief = `
|
||||
destination file path for packed file. if extension of the filename is ".go" and "-n" option is given,
|
||||
it enables packing SRC to go file, or else it packs SRC into a binary file.
|
||||
`
|
||||
cPackNameBrief = `package name for output go file, it's set as its directory name if no name passed`
|
||||
cPackPrefixBrief = `prefix for each file packed into the resource file`
|
||||
cPackKeepPathBrief = `keep the source path from system to resource file, usually for relative path`
|
||||
)
|
||||
|
||||
func init() {
|
||||
gtag.Sets(g.MapStrStr{
|
||||
`cPackUsage`: cPackUsage,
|
||||
`cPackBrief`: cPackBrief,
|
||||
`cPackEg`: cPackEg,
|
||||
`cPackSrcBrief`: cPackSrcBrief,
|
||||
`cPackDstBrief`: cPackDstBrief,
|
||||
`cPackNameBrief`: cPackNameBrief,
|
||||
`cPackPrefixBrief`: cPackPrefixBrief,
|
||||
`cPackKeepPathBrief`: cPackKeepPathBrief,
|
||||
})
|
||||
Main.AddObject(Pack)
|
||||
|
||||
}
|
||||
|
||||
type cPackInput struct {
|
||||
g.Meta `name:"pack"`
|
||||
Src string `name:"SRC" arg:"true" v:"required" brief:"{cPackSrcBrief}"`
|
||||
Dst string `name:"DST" arg:"true" v:"required" brief:"{cPackDstBrief}"`
|
||||
Name string `name:"name" short:"n" brief:"{cPackNameBrief}"`
|
||||
Prefix string `name:"prefix" short:"p" brief:"{cPackPrefixBrief}"`
|
||||
KeepPath bool `name:"keepPath" short:"k" brief:"{cPackKeepPathBrief}" orphan:"true"`
|
||||
}
|
||||
|
||||
type cPackOutput struct{}
|
||||
|
||||
func (c cPack) Index(ctx context.Context, in cPackInput) (out *cPackOutput, err error) {
|
||||
if gfile.Exists(in.Dst) && gfile.IsDir(in.Dst) {
|
||||
mlog.Fatalf("DST path '%s' cannot be a directory", in.Dst)
|
||||
}
|
||||
if !gfile.IsEmpty(in.Dst) && !allyes.Check() {
|
||||
s := gcmd.Scanf("path '%s' is not empty, files might be overwrote, continue? [y/n]: ", in.Dst)
|
||||
if strings.EqualFold(s, "n") {
|
||||
return
|
||||
}
|
||||
}
|
||||
if in.Name == "" && gfile.ExtName(in.Dst) == "go" {
|
||||
in.Name = gfile.Basename(gfile.Dir(in.Dst))
|
||||
}
|
||||
var option = gres.Option{
|
||||
Prefix: in.Prefix,
|
||||
KeepPath: in.KeepPath,
|
||||
}
|
||||
if in.Name != "" {
|
||||
if err = gres.PackToGoFileWithOption(in.Src, in.Dst, in.Name, option); err != nil {
|
||||
mlog.Fatalf("pack failed: %v", err)
|
||||
}
|
||||
} else {
|
||||
if err = gres.PackToFileWithOption(in.Src, in.Dst, option); err != nil {
|
||||
mlog.Fatalf("pack failed: %v", err)
|
||||
}
|
||||
}
|
||||
mlog.Print("done!")
|
||||
return
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// 同步自 gf v2.2.2 https://github.com/gogf/gf/blob/60d828397149ed281111a7530074ce20f997224a/cmd/gf/internal/cmd/cmd_build.go
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/gogf/gf/v2/container/gtype"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gfsnotify"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/os/gtimer"
|
||||
"github.com/gogf/gf/v2/util/gtag"
|
||||
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/utility/mlog"
|
||||
)
|
||||
|
||||
var (
|
||||
Run = cRun{}
|
||||
)
|
||||
|
||||
type cRun struct {
|
||||
g.Meta `name:"run" usage:"{cRunUsage}" brief:"{cRunBrief}" eg:"{cRunEg}" dc:"{cRunDc}"`
|
||||
}
|
||||
|
||||
type cRunApp struct {
|
||||
File string // Go run file name.
|
||||
Path string // Directory storing built binary.
|
||||
Options string // Extra "go run" options.
|
||||
Args string // Custom arguments.
|
||||
}
|
||||
|
||||
const (
|
||||
cRunUsage = `cool-tools run FILE [OPTION]`
|
||||
cRunBrief = `running go codes with hot-compiled-like feature`
|
||||
cRunEg = `
|
||||
cool-tools run main.go
|
||||
cool-tools run main.go --args "server -p 8080"
|
||||
cool-tools run main.go -mod=vendor
|
||||
`
|
||||
cRunDc = `
|
||||
The "run" command is used for running go codes with hot-compiled-like feature,
|
||||
which compiles and runs the go codes asynchronously when codes change.
|
||||
`
|
||||
cRunFileBrief = `building file path.`
|
||||
cRunPathBrief = `output directory path for built binary file. it's "manifest/output" in default`
|
||||
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
|
||||
cRunArgsBrief = `custom arguments for your process`
|
||||
)
|
||||
|
||||
var (
|
||||
process *gproc.Process
|
||||
)
|
||||
|
||||
func init() {
|
||||
gtag.Sets(g.MapStrStr{
|
||||
`cRunUsage`: cRunUsage,
|
||||
`cRunBrief`: cRunBrief,
|
||||
`cRunEg`: cRunEg,
|
||||
`cRunDc`: cRunDc,
|
||||
`cRunFileBrief`: cRunFileBrief,
|
||||
`cRunPathBrief`: cRunPathBrief,
|
||||
`cRunExtraBrief`: cRunExtraBrief,
|
||||
`cRunArgsBrief`: cRunArgsBrief,
|
||||
})
|
||||
// 注册命令
|
||||
Main.AddObject(Run)
|
||||
}
|
||||
|
||||
type (
|
||||
cRunInput struct {
|
||||
g.Meta `name:"run"`
|
||||
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
|
||||
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
|
||||
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
|
||||
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
|
||||
}
|
||||
cRunOutput struct{}
|
||||
)
|
||||
|
||||
func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err error) {
|
||||
// Necessary check.
|
||||
if gproc.SearchBinary("go") == "" {
|
||||
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
|
||||
}
|
||||
|
||||
app := &cRunApp{
|
||||
File: in.File,
|
||||
Path: in.Path,
|
||||
Options: in.Extra,
|
||||
Args: in.Args,
|
||||
}
|
||||
dirty := gtype.NewBool()
|
||||
_, err = gfsnotify.Add(gfile.RealPath("."), func(event *gfsnotify.Event) {
|
||||
if gfile.ExtName(event.Path) != "go" {
|
||||
return
|
||||
}
|
||||
// Variable `dirty` is used for running the changes only one in one second.
|
||||
if !dirty.Cas(false, true) {
|
||||
return
|
||||
}
|
||||
// With some delay in case of multiple code changes in very short interval.
|
||||
gtimer.SetTimeout(ctx, 1500*gtime.MS, func(ctx context.Context) {
|
||||
defer dirty.Set(false)
|
||||
mlog.Printf(`go file changes: %s`, event.String())
|
||||
app.Run(ctx)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
go app.Run(ctx)
|
||||
select {}
|
||||
}
|
||||
|
||||
func (app *cRunApp) Run(ctx context.Context) {
|
||||
// Rebuild and run the codes.
|
||||
renamePath := ""
|
||||
mlog.Printf("build: %s", app.File)
|
||||
outputPath := gfile.Join(app.Path, gfile.Name(app.File))
|
||||
if runtime.GOOS == "windows" {
|
||||
outputPath += ".exe"
|
||||
if gfile.Exists(outputPath) {
|
||||
renamePath = outputPath + "~"
|
||||
if err := gfile.Rename(outputPath, renamePath); err != nil {
|
||||
mlog.Print(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// In case of `pipe: too many open files` error.
|
||||
// Build the app.
|
||||
buildCommand := fmt.Sprintf(
|
||||
`go build -o %s %s %s`,
|
||||
outputPath,
|
||||
app.Options,
|
||||
app.File,
|
||||
)
|
||||
mlog.Print(buildCommand)
|
||||
result, err := gproc.ShellExec(ctx, buildCommand)
|
||||
if err != nil {
|
||||
mlog.Printf("build error: \n%s%s", result, err.Error())
|
||||
return
|
||||
}
|
||||
// Kill the old process if build successfully.
|
||||
if process != nil {
|
||||
if err := process.Kill(); err != nil {
|
||||
mlog.Debugf("kill process error: %s", err.Error())
|
||||
//return
|
||||
}
|
||||
}
|
||||
// Run the binary file.
|
||||
runCommand := fmt.Sprintf(`%s %s`, outputPath, app.Args)
|
||||
mlog.Print(runCommand)
|
||||
if runtime.GOOS == "windows" {
|
||||
// Special handling for windows platform.
|
||||
// DO NOT USE "cmd /c" command.
|
||||
process = gproc.NewProcess(runCommand, nil)
|
||||
} else {
|
||||
process = gproc.NewProcessCmd(runCommand, nil)
|
||||
}
|
||||
if pid, err := process.Start(ctx); err != nil {
|
||||
mlog.Printf("build running error: %s", err.Error())
|
||||
} else {
|
||||
mlog.Printf("build running pid: %d", pid)
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/utility/mlog"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
var (
|
||||
Docs = gcmd.Command{
|
||||
Name: "docs",
|
||||
Usage: "cool-tools docs",
|
||||
Brief: "查看帮助文档",
|
||||
Description: "查看帮助文档",
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) error {
|
||||
s := g.Server("docs")
|
||||
// 获取本机未占用的端口
|
||||
port, err := getfreeport()
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
return err
|
||||
}
|
||||
// 获取本机ip
|
||||
// ip, err := getlocalip()
|
||||
// if err != nil {
|
||||
// mlog.Fatal(err)
|
||||
// return err
|
||||
// }
|
||||
s.SetServerRoot("docs")
|
||||
s.BindHandler("/", func(r *ghttp.Request) {
|
||||
r.Response.RedirectTo("/cool-admin-go/")
|
||||
})
|
||||
// 设置端口
|
||||
s.SetPort(gconv.Int(port))
|
||||
mlog.Printf("CoolAdminGo docs server is running at %s", "http://"+"127.0.0.1"+":"+gconv.String(port)+"/cool-admin-go/")
|
||||
s.Run()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
Main.AddCommand(&Docs)
|
||||
}
|
||||
|
||||
// getfreeport 获取本机未占用的端口
|
||||
func getfreeport() (int, error) {
|
||||
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
l, err := net.ListenTCP("tcp", addr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer l.Close()
|
||||
return l.Addr().(*net.TCPAddr).Port, nil
|
||||
}
|
||||
|
||||
// getlocalip 获取本机ip
|
||||
// func getlocalip() (string, error) {
|
||||
// addrs, err := net.InterfaceAddrs()
|
||||
// if err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
// for _, address := range addrs {
|
||||
// // 检查ip地址判断是否回环地址
|
||||
// if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||
// if ipnet.IP.To4() != nil {
|
||||
// return ipnet.IP.String(), nil
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return "", nil
|
||||
// }
|
||||
@@ -1,27 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gres"
|
||||
)
|
||||
|
||||
var (
|
||||
Dump = &gcmd.Command{
|
||||
Name: "dump",
|
||||
Usage: "cool-tools dump",
|
||||
Brief: "查看打包的资源文件",
|
||||
Description: "查看打包的资源文件",
|
||||
Arguments: []gcmd.Argument{},
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
gres.Dump()
|
||||
return nil
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// init
|
||||
func init() {
|
||||
Main.AddCommand(Dump)
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
var (
|
||||
Gen = cGen{}
|
||||
)
|
||||
|
||||
type cGen struct {
|
||||
g.Meta `name:"gen" brief:"生成代码" description:"生成代码, 例如: cool-tools gen model"`
|
||||
cGenModel
|
||||
}
|
||||
|
||||
func init() {
|
||||
Main.AddObject(Gen)
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/cool-team-official/cool-admin-go/cool"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"gorm.io/gen"
|
||||
)
|
||||
|
||||
type cGenModel struct {
|
||||
g.Meta `name:"model" brief:"生成模型代码" description:"生成模型代码, 例如: cool-tools gen model"`
|
||||
}
|
||||
|
||||
var (
|
||||
GenModel = cGenModel{}
|
||||
)
|
||||
|
||||
type cGenModelInput struct {
|
||||
g.Meta `name:"model" brief:"生成模型代码" description:"生成模型代码, 例如: cool-tools gen model"`
|
||||
Database string `v:"required#请输入数据库名称" arg:"true" name:"database" brief:"数据库名称" description:"数据库名称"`
|
||||
}
|
||||
type cGenModelOutput struct{}
|
||||
|
||||
func (c *cGenModel) Index(ctx g.Ctx, in cGenModelInput) (out cGenModelOutput, err error) {
|
||||
g.Log().Print(ctx, in.Database)
|
||||
// 获取数据库
|
||||
db, err := cool.InitDB(in.Database)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
generator := gen.NewGenerator(gen.Config{
|
||||
OutPath: "temp/gen/model",
|
||||
OutFile: "",
|
||||
ModelPkgPath: "",
|
||||
WithUnitTest: false,
|
||||
FieldNullable: true,
|
||||
FieldCoverable: true,
|
||||
FieldSignable: true,
|
||||
FieldWithIndexTag: true,
|
||||
FieldWithTypeTag: true,
|
||||
Mode: 0,
|
||||
})
|
||||
generator.UseDB(db)
|
||||
generator.GenerateAllTable()
|
||||
generator.Execute()
|
||||
return
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gres"
|
||||
)
|
||||
|
||||
var (
|
||||
Init = gcmd.Command{
|
||||
Name: "init",
|
||||
Usage: "cool-tools init [dst]",
|
||||
Brief: "创建一个新的cool-admin-go项目",
|
||||
Arguments: []gcmd.Argument{
|
||||
{
|
||||
Name: "dst",
|
||||
// Short: "m",
|
||||
Brief: "the destination path",
|
||||
IsArg: true,
|
||||
},
|
||||
},
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
dst := parser.GetArg(2).String()
|
||||
if dst == "" {
|
||||
dst = "."
|
||||
}
|
||||
// 如果目标路径不存在,则创建目标路径
|
||||
if gfile.IsEmpty(dst) {
|
||||
if err = gfile.Mkdir(dst); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if !gfile.IsDir(dst) {
|
||||
g.Log().Panicf(ctx, "%s is not a directory", dst)
|
||||
} else {
|
||||
s := gcmd.Scanf(`the folder "%s" is not empty, files might be overwrote, continue? [y/n]: `, dst)
|
||||
if strings.EqualFold(s, "n") {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
err = gres.Export("cool-admin-go-simple", dst, gres.ExportOption{
|
||||
RemovePrefix: "cool-admin-go-simple",
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = gfile.ReplaceDir("cool-admin-go-simple", gfile.Basename(gfile.RealPath(dst)), dst, "*", true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
g.Log().Infof(ctx, "init success")
|
||||
return nil
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// init 初始化模块
|
||||
func init() {
|
||||
Main.AddCommand(&Init)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/service"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
)
|
||||
|
||||
var (
|
||||
Install = gcmd.Command{
|
||||
Name: "install",
|
||||
Usage: "cool-tools install",
|
||||
Brief: "Install cool-tools to the system.",
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
err = service.Install.Run(ctx)
|
||||
return
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// init
|
||||
func init() {
|
||||
Main.AddCommand(&Install)
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/service"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
)
|
||||
|
||||
var (
|
||||
Module = &gcmd.Command{
|
||||
Name: "module",
|
||||
Usage: "cool-tools module moduleName",
|
||||
Brief: "在modules目录下创建模块",
|
||||
Description: "在modules目录下创建模块, 并且创建相应的目录结构,注意: 如果模块已经存在, 则会覆盖原有的模块,本命令需在项目根目录下执行.",
|
||||
Arguments: []gcmd.Argument{
|
||||
{
|
||||
Name: "moduleName",
|
||||
IsArg: true,
|
||||
Orphan: false,
|
||||
},
|
||||
},
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
moduleName := parser.GetArg(2).String()
|
||||
if moduleName == "" {
|
||||
println("moduleName is empty")
|
||||
return nil
|
||||
}
|
||||
err = service.CreatModule(ctx, moduleName)
|
||||
return
|
||||
},
|
||||
}
|
||||
M = &gcmd.Command{
|
||||
Name: "m",
|
||||
Usage: "cool-tools module moduleName",
|
||||
Brief: "在modules目录下创建模块,为module的简写模式",
|
||||
Description: "在modules目录下创建模块, 并且创建相应的目录结构,注意: 如果模块已经存在, 则会覆盖原有的模块,本命令需在项目根目录下执行.",
|
||||
Arguments: []gcmd.Argument{
|
||||
{
|
||||
Name: "moduleName",
|
||||
IsArg: true,
|
||||
Orphan: false,
|
||||
},
|
||||
},
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
moduleName := parser.GetArg(2).String()
|
||||
if moduleName == "" {
|
||||
println("moduleName is empty")
|
||||
return nil
|
||||
}
|
||||
err = service.CreatModule(ctx, moduleName)
|
||||
return
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
Main.AddCommand(Module)
|
||||
Main.AddCommand(M)
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
)
|
||||
|
||||
var (
|
||||
SnippetsMaker = gcmd.Command{
|
||||
Name: "snippetsmaker",
|
||||
Usage: "snippetsmaker",
|
||||
Brief: "代码片段生成器",
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
g.Log().Debug(ctx, "snippetsmaker,生成工具^.^")
|
||||
files := garray.New(true)
|
||||
files.Append("modules/demo/model/demo_sample.go")
|
||||
files.Append("modules/demo/service/demo_sample.go")
|
||||
files.Append("modules/demo/controller/admin/demo_sample.go")
|
||||
// 遍历files
|
||||
for _, file := range files.Slice() {
|
||||
sArray := garray.NewStrArray()
|
||||
gfile.ReadLines(file.(string), func(line string) error {
|
||||
// g.Log().Debug(ctx, line)
|
||||
// println(line)
|
||||
// search := `Sample`
|
||||
// replace := `${TM_FILENAME_BASE/(.*)/${1:/capitalize}/}`
|
||||
// replaceArray := []string{"Sample", "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}", "sample", "${TM_FILENAME_BASE/(.*)/${1:/downcase}/}", "demo", "${2:模块名称}", "app", "${TM_DIRECTORY/^.+[\\/\\\\]+(.*)$/$1/}"}
|
||||
replaceArray := []string{"DemoSample", "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}", "demo_sample", "${TM_FILENAME_BASE/(.*)/${1:/downcase}/}"}
|
||||
|
||||
result := gstr.ReplaceByArray(line, replaceArray)
|
||||
sArray.Append(gstr.AddSlashes(result))
|
||||
|
||||
return nil
|
||||
})
|
||||
// g.Dump(sArray)
|
||||
println(file.(string))
|
||||
println("--------------------------------------code start------------------------------------------")
|
||||
println(`"body":[`)
|
||||
sArray.Iterator(
|
||||
func(index int, value string) bool {
|
||||
println("\"" + value + "\",")
|
||||
return true
|
||||
},
|
||||
)
|
||||
println("]")
|
||||
println("--------------------------------------code end------------------------------------------")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
Main.AddCommand(&SnippetsMaker)
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gbuild"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/util/gutil"
|
||||
)
|
||||
|
||||
type sVersion struct {
|
||||
Name string //程序名称
|
||||
Homepage string //程序主页
|
||||
Version string //程序版本
|
||||
GoFrame string //goframe version
|
||||
Golang string //golang version
|
||||
Git string //git commit id
|
||||
Time string //build datetime
|
||||
InstallPath string //安装路径
|
||||
}
|
||||
|
||||
var (
|
||||
Version = gcmd.Command{
|
||||
Name: "version",
|
||||
Usage: "cool-tools version",
|
||||
Brief: "查看版本信息",
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
info := gbuild.Info()
|
||||
binVersion := "v1.5.10"
|
||||
|
||||
// 生成sVersion结构体
|
||||
res := sVersion{
|
||||
Name: "cool-tools",
|
||||
Homepage: "https://cool-js.com",
|
||||
Version: binVersion,
|
||||
GoFrame: info.GoFrame,
|
||||
Golang: info.Golang,
|
||||
Git: info.Git,
|
||||
Time: info.Time,
|
||||
InstallPath: gfile.SelfDir(),
|
||||
}
|
||||
// mlog.Printf(`CLI Installed At: %s`, gfile.SelfPath())
|
||||
gutil.Dump(res)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// init 初始化模块
|
||||
func init() {
|
||||
Main.AddCommand(&Version)
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package consts
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
package packed
|
||||
@@ -1,235 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/utility/allyes"
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/utility/mlog"
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/genv"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
var (
|
||||
Install = serviceInstall{}
|
||||
)
|
||||
|
||||
type serviceInstall struct{}
|
||||
|
||||
type serviceInstallAvailablePath struct {
|
||||
dirPath string
|
||||
filePath string
|
||||
writable bool
|
||||
installed bool
|
||||
}
|
||||
|
||||
func (s serviceInstall) Run(ctx context.Context) (err error) {
|
||||
// Ask where to install.
|
||||
paths := s.getAvailablePaths()
|
||||
if len(paths) <= 0 {
|
||||
mlog.Printf("no path detected, you can manually install cool-tools by copying the binary to path folder.")
|
||||
return
|
||||
}
|
||||
mlog.Printf("I found some installable paths for you(from $PATH): ")
|
||||
mlog.Printf(" %2s | %8s | %9s | %s", "Id", "Writable", "Installed", "Path")
|
||||
|
||||
// Print all paths status and determine the default selectedID value.
|
||||
var (
|
||||
selectedID = -1
|
||||
newPaths []serviceInstallAvailablePath
|
||||
pathSet = gset.NewStrSet() // Used for repeated items filtering.
|
||||
)
|
||||
for _, path := range paths {
|
||||
if !pathSet.AddIfNotExist(path.dirPath) {
|
||||
continue
|
||||
}
|
||||
newPaths = append(newPaths, path)
|
||||
}
|
||||
paths = newPaths
|
||||
for id, path := range paths {
|
||||
mlog.Printf(" %2d | %8t | %9t | %s", id, path.writable, path.installed, path.dirPath)
|
||||
if selectedID == -1 {
|
||||
// Use the previously installed path as the most priority choice.
|
||||
if path.installed {
|
||||
selectedID = id
|
||||
}
|
||||
}
|
||||
}
|
||||
// If there's no previously installed path, use the first writable path.
|
||||
if selectedID == -1 {
|
||||
// Order by choosing priority.
|
||||
commonPaths := garray.NewStrArrayFrom(g.SliceStr{
|
||||
s.getGoPathBin(),
|
||||
`/usr/local/bin`,
|
||||
`/usr/bin`,
|
||||
`/usr/sbin`,
|
||||
`C:\Windows`,
|
||||
`C:\Windows\system32`,
|
||||
`C:\Go\bin`,
|
||||
`C:\Program Files`,
|
||||
`C:\Program Files (x86)`,
|
||||
})
|
||||
// Check the common installation directories.
|
||||
commonPaths.Iterator(func(k int, v string) bool {
|
||||
for id, aPath := range paths {
|
||||
if strings.EqualFold(aPath.dirPath, v) {
|
||||
selectedID = id
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
if selectedID == -1 {
|
||||
selectedID = 0
|
||||
}
|
||||
}
|
||||
|
||||
if allyes.Check() {
|
||||
// Use the default selectedID.
|
||||
mlog.Printf("please choose one installation destination [default %d]: %d", selectedID, selectedID)
|
||||
} else {
|
||||
for {
|
||||
// Get input and update selectedID.
|
||||
var (
|
||||
inputID int
|
||||
input = gcmd.Scanf("please choose one installation destination [default %d]: ", selectedID)
|
||||
)
|
||||
if input != "" {
|
||||
inputID = gconv.Int(input)
|
||||
}
|
||||
// Check if out of range.
|
||||
if inputID >= len(paths) || inputID < 0 {
|
||||
mlog.Printf("invalid install destination Id: %d", inputID)
|
||||
continue
|
||||
}
|
||||
selectedID = inputID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Get selected destination path.
|
||||
dstPath := paths[selectedID]
|
||||
|
||||
// Install the new binary.
|
||||
err = gfile.CopyFile(gfile.SelfPath(), dstPath.filePath)
|
||||
if err != nil {
|
||||
mlog.Printf("install cool-tools binary to '%s' failed: %v", dstPath.dirPath, err)
|
||||
mlog.Printf("you can manually install cool-tools by copying the binary to folder: %s", dstPath.dirPath)
|
||||
} else {
|
||||
mlog.Printf("cool-tools binary is successfully installed to: %s", dstPath.dirPath)
|
||||
}
|
||||
|
||||
// Uninstall the old binary.
|
||||
for _, path := range paths {
|
||||
// Do not delete myself.
|
||||
if path.filePath != "" && path.filePath != dstPath.filePath && gfile.SelfPath() != path.filePath {
|
||||
_ = gfile.Remove(path.filePath)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// IsInstalled checks and returns whether the binary is installed.
|
||||
func (s serviceInstall) IsInstalled() bool {
|
||||
paths := s.getAvailablePaths()
|
||||
for _, aPath := range paths {
|
||||
if aPath.installed {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// getGoPathBinFilePath retrieves ad returns the GOPATH/bin path for binary.
|
||||
func (s serviceInstall) getGoPathBin() string {
|
||||
if goPath := genv.Get(`GOPATH`).String(); goPath != "" {
|
||||
return gfile.Join(goPath, "bin")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// getAvailablePaths returns the installation paths data for the binary.
|
||||
func (s serviceInstall) getAvailablePaths() []serviceInstallAvailablePath {
|
||||
var (
|
||||
folderPaths []serviceInstallAvailablePath
|
||||
binaryFileName = "cool-tools" + gfile.Ext(gfile.SelfPath())
|
||||
)
|
||||
// $GOPATH/bin
|
||||
if goPathBin := s.getGoPathBin(); goPathBin != "" {
|
||||
folderPaths = s.checkAndAppendToAvailablePath(
|
||||
folderPaths, goPathBin, binaryFileName,
|
||||
)
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
darwinInstallationCheckPaths := []string{"/usr/local/bin"}
|
||||
for _, v := range darwinInstallationCheckPaths {
|
||||
folderPaths = s.checkAndAppendToAvailablePath(
|
||||
folderPaths, v, binaryFileName,
|
||||
)
|
||||
}
|
||||
fallthrough
|
||||
|
||||
default:
|
||||
// Search and find the writable directory path.
|
||||
envPath := genv.Get("PATH", genv.Get("Path").String()).String()
|
||||
if gstr.Contains(envPath, ";") {
|
||||
// windows.
|
||||
for _, v := range gstr.SplitAndTrim(envPath, ";") {
|
||||
if v == "." {
|
||||
continue
|
||||
}
|
||||
folderPaths = s.checkAndAppendToAvailablePath(
|
||||
folderPaths, v, binaryFileName,
|
||||
)
|
||||
}
|
||||
} else if gstr.Contains(envPath, ":") {
|
||||
// *nix.
|
||||
for _, v := range gstr.SplitAndTrim(envPath, ":") {
|
||||
if v == "." {
|
||||
continue
|
||||
}
|
||||
folderPaths = s.checkAndAppendToAvailablePath(
|
||||
folderPaths, v, binaryFileName,
|
||||
)
|
||||
}
|
||||
} else if envPath != "" {
|
||||
folderPaths = s.checkAndAppendToAvailablePath(
|
||||
folderPaths, envPath, binaryFileName,
|
||||
)
|
||||
} else {
|
||||
folderPaths = s.checkAndAppendToAvailablePath(
|
||||
folderPaths, "/usr/local/bin", binaryFileName,
|
||||
)
|
||||
}
|
||||
}
|
||||
return folderPaths
|
||||
}
|
||||
|
||||
// checkAndAppendToAvailablePath checks if `path` is writable and already installed.
|
||||
// It adds the `path` to `folderPaths` if it is writable or already installed, or else it ignores the `path`.
|
||||
func (s serviceInstall) checkAndAppendToAvailablePath(folderPaths []serviceInstallAvailablePath, dirPath string, binaryFileName string) []serviceInstallAvailablePath {
|
||||
var (
|
||||
filePath = gfile.Join(dirPath, binaryFileName)
|
||||
writable = gfile.IsWritable(dirPath)
|
||||
installed = gfile.Exists(filePath)
|
||||
)
|
||||
if !writable && !installed {
|
||||
return folderPaths
|
||||
}
|
||||
return append(
|
||||
folderPaths,
|
||||
serviceInstallAvailablePath{
|
||||
dirPath: dirPath,
|
||||
writable: writable,
|
||||
filePath: filePath,
|
||||
installed: installed,
|
||||
})
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gres"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
func CreatModule(ctx context.Context, moduleName string) (err error) {
|
||||
// 检测当前目录是否存在go.mod文件
|
||||
if !gfile.Exists("go.mod") {
|
||||
err = gerror.New("当前目录不存在go.mod文件,请在项目根目录下执行")
|
||||
return
|
||||
}
|
||||
module := ""
|
||||
// 读取go.mod文件第一行文本
|
||||
gfile.ReadLines("go.mod", func(text string) error {
|
||||
if gstr.Contains(text, "module") && module == "" {
|
||||
// println("module:", text)
|
||||
module = gstr.StrEx(text, "module")
|
||||
// println("module:", module)
|
||||
module = gstr.TrimAll(module)
|
||||
// println("module:", module)
|
||||
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if module == "" {
|
||||
err = gerror.New("go.mod文件中不存在module行")
|
||||
return
|
||||
}
|
||||
// println(module)
|
||||
// 创建模块目录
|
||||
moduleDir := gfile.Join(gfile.Pwd(), "modules", moduleName)
|
||||
if gfile.Exists(moduleDir) {
|
||||
err = gerror.New("模块已经存在,请先删除原有模块")
|
||||
return
|
||||
}
|
||||
err = gfile.Mkdir(moduleDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 创建模块目录结构
|
||||
err = gres.Export("cool-admin-go-simple/modules/demo", moduleDir, gres.ExportOption{
|
||||
RemovePrefix: "cool-admin-go-simple/modules/demo",
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 替换import路径
|
||||
err = gfile.ReplaceDir("cool-admin-go-simple/modules/demo", module+"/modules/"+moduleName, moduleDir, "*", true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 重命名demo.go 为 moduleName.go
|
||||
err = gfile.Rename(gfile.Join(moduleDir, "demo.go"), gfile.Join(moduleDir, moduleName+".go"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
println("创建模块成功:", moduleDir)
|
||||
return nil
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package allyes
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/genv"
|
||||
)
|
||||
|
||||
const (
|
||||
EnvName = "GF_CLI_ALL_YES"
|
||||
)
|
||||
|
||||
// Init initializes the package manually.
|
||||
func Init() {
|
||||
if gcmd.GetOpt("y") != nil {
|
||||
genv.MustSet(EnvName, "1")
|
||||
}
|
||||
}
|
||||
|
||||
// Check checks whether option allow all yes for command.
|
||||
func Check() bool {
|
||||
return genv.Get(EnvName).String() == "1"
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package mlog
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/genv"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
headerPrintEnvName = "GF_CLI_MLOG_HEADER"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
logger = glog.New()
|
||||
)
|
||||
|
||||
func init() {
|
||||
logger.SetStack(false)
|
||||
if genv.Get(headerPrintEnvName).String() == "1" {
|
||||
logger.SetHeaderPrint(true)
|
||||
} else {
|
||||
logger.SetHeaderPrint(false)
|
||||
}
|
||||
if gcmd.GetOpt("debug") != nil || gcmd.GetOpt("gf.debug") != nil {
|
||||
logger.SetDebug(true)
|
||||
} else {
|
||||
logger.SetDebug(false)
|
||||
}
|
||||
}
|
||||
|
||||
// SetHeaderPrint enables/disables header printing to stdout.
|
||||
func SetHeaderPrint(enabled bool) {
|
||||
logger.SetHeaderPrint(enabled)
|
||||
if enabled {
|
||||
_ = genv.Set(headerPrintEnvName, "1")
|
||||
} else {
|
||||
_ = genv.Set(headerPrintEnvName, "0")
|
||||
}
|
||||
}
|
||||
|
||||
func Print(v ...interface{}) {
|
||||
logger.Print(ctx, v...)
|
||||
}
|
||||
|
||||
func Printf(format string, v ...interface{}) {
|
||||
logger.Printf(ctx, format, v...)
|
||||
}
|
||||
|
||||
func Fatal(v ...interface{}) {
|
||||
logger.Fatal(ctx, v...)
|
||||
}
|
||||
|
||||
func Fatalf(format string, v ...interface{}) {
|
||||
logger.Fatalf(ctx, format, v...)
|
||||
}
|
||||
|
||||
func Debug(v ...interface{}) {
|
||||
logger.Debug(ctx, v...)
|
||||
}
|
||||
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
logger.Debugf(ctx, format, v...)
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/cmd"
|
||||
_ "github.com/cool-team-official/cool-admin-go/cool-tools/internal/packed"
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/utility/allyes"
|
||||
"github.com/cool-team-official/cool-admin-go/cool-tools/internal/utility/mlog"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcfg"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
)
|
||||
|
||||
const (
|
||||
cliFolderName = `hack`
|
||||
)
|
||||
|
||||
func main() {
|
||||
// gres.Dump()
|
||||
// CLI configuration.
|
||||
if path, _ := gfile.Search(cliFolderName); path != "" {
|
||||
if adapter, ok := g.Cfg().GetAdapter().(*gcfg.AdapterFile); ok {
|
||||
if err := adapter.SetPath(path); err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// -y option checks.
|
||||
allyes.Init()
|
||||
|
||||
err := cmd.Main.RunWithError(gctx.New())
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
server:
|
||||
address: ":8000"
|
||||
openapiPath: "/api.json"
|
||||
swaggerPath: "/swagger"
|
||||
|
||||
logger:
|
||||
level : "all"
|
||||
stdout: true
|
||||
|
||||
|
||||
|
||||
database:
|
||||
default:
|
||||
- type: "mysql"
|
||||
link: "root:123456@tcp(127.0.0.1:3306)/cooltest?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
role: "master"
|
||||
debug: true
|
||||
createdAt: "createTime"
|
||||
updatedAt: "updateTime"
|
||||
- type: "mysql"
|
||||
link: "root:123456@tcp(127.0.0.1:3306)/cooltest?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
role: "slave"
|
||||
debug: true
|
||||
createdAt: "createTime"
|
||||
updatedAt: "updateTime"
|
||||
test:
|
||||
type: "sqlite"
|
||||
link: "./temp/db.sqlite"
|
||||
logLevel: "all"
|
||||
createdAt: "createTime"
|
||||
updatedAt: "updateTime"
|
||||
bill:
|
||||
type: "mssql"
|
||||
# link: "sqlserver://sa:fjTGgpaFlp3LLi3tsB@localhost:1433?database=bill"
|
||||
link: "server=localhost;user id=sa;password=fjTGgpaFlp3LLi3tsB;port=1433;database=bill;"
|
||||
logLevel: "all"
|
||||
createdAt: "createTime"
|
||||
updatedAt: "updateTime"
|
||||
@@ -1,21 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: template-single
|
||||
labels:
|
||||
app: template-single
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: template-single
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: template-single
|
||||
spec:
|
||||
containers:
|
||||
- name : main
|
||||
image: template-single
|
||||
imagePullPolicy: Always
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: template-single
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
protocol: TCP
|
||||
targetPort: 8000
|
||||
selector:
|
||||
app: template-single
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: template-single-configmap
|
||||
data:
|
||||
config.yaml: |
|
||||
server:
|
||||
address: ":8000"
|
||||
openapiPath: "/api.json"
|
||||
swaggerPath: "/swagger"
|
||||
|
||||
logger:
|
||||
level : "all"
|
||||
stdout: true
|
||||
@@ -1,10 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: template-single
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name : main
|
||||
image: template-single:develop
|
||||
@@ -1,14 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
- configmap.yaml
|
||||
|
||||
patchesStrategicMerge:
|
||||
- deployment.yaml
|
||||
|
||||
namespace: default
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
FROM loads/alpine:3.8
|
||||
|
||||
###############################################################################
|
||||
# INSTALLATION
|
||||
###############################################################################
|
||||
|
||||
ENV WORKDIR /app
|
||||
ADD resource $WORKDIR/
|
||||
ADD ./temp/linux_amd64/main $WORKDIR/main
|
||||
RUN chmod +x $WORKDIR/main
|
||||
|
||||
###############################################################################
|
||||
# START
|
||||
###############################################################################
|
||||
WORKDIR $WORKDIR
|
||||
CMD ./main
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This shell is executed before docker build.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,37 +0,0 @@
|
||||
module.exports = {
|
||||
title: 'CoolAdminGo文档',
|
||||
description: 'CoolAdminGo文档',
|
||||
base: '/cool-admin-go/',
|
||||
locales: {
|
||||
'/': {
|
||||
lang: 'zh-CN',
|
||||
title: 'CoolAdminGo文档',
|
||||
description: 'CoolAdminGo文档',
|
||||
},
|
||||
},
|
||||
themeConfig: {
|
||||
logo: '/logo-admin-new.png',
|
||||
repo: 'https://github.com/cool-team-official/cool-admin-go',
|
||||
docsDir: 'docs',
|
||||
editLinks: true,
|
||||
editLinkText: '在 GitHub 上编辑此页',
|
||||
nav: [
|
||||
{ text: '首页', link: '/' },
|
||||
{ text: 'CoolAdmin官网', link: 'https://cool-js.com' },
|
||||
{ text: 'GoFrame官网', link: 'https://goframe.org' },
|
||||
],
|
||||
lastUpdated: '上次更新',
|
||||
sidebar: [
|
||||
"/",
|
||||
"/introduction",
|
||||
"/feedback",
|
||||
"/development",
|
||||
"/cli",
|
||||
"/quick_start",
|
||||
"/config",
|
||||
"/changelog",
|
||||
"/known_issues",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.8 KiB |
@@ -1,89 +0,0 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# Install Golang 安装Golang,仅限linux系统. #
|
||||
# Author: LiDong #
|
||||
# Email: cnlidong@live.cn #
|
||||
# Date: 2022-08-15 #
|
||||
###############################################################################
|
||||
# 出错退出
|
||||
set -e
|
||||
# 进入脚本所在目录
|
||||
|
||||
# 获取第一个参数设为版本号
|
||||
VERSION=$1
|
||||
# 判断版本号参数是否为空
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "Usage: $0 VERSION [mirror]"
|
||||
echo "Example: $0 1.19.2 https://mirrors.aliyun.com/golang"
|
||||
echo "You can visit https://go.dev/dl/ to find version"
|
||||
exit 1
|
||||
fi
|
||||
echo "version: $VERSION"
|
||||
# 获取第二个参数为镜像地址前缀
|
||||
PREFIX=$2
|
||||
# 判断镜像地址前缀参数是否为空
|
||||
if [ -z "$PREFIX" ]; then
|
||||
PREFIX="https://go.dev/dl"
|
||||
fi
|
||||
echo "prefix: $PREFIX"
|
||||
# 判断当前用户是否为root,不是则退出
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "Error: This script must be run as root."
|
||||
echo "You can use 'sudo su' command switch to root "
|
||||
exit 1
|
||||
fi
|
||||
# 安装Golang
|
||||
echo "Install Golang..."
|
||||
# 获取当前操作系统
|
||||
OS=$(uname)
|
||||
# 判断是否是Linux系统,如果不是则退出
|
||||
if [ $OS != "Linux" ]; then
|
||||
echo "Not Linux system, exit..."
|
||||
exit
|
||||
else
|
||||
OS="linux"
|
||||
fi
|
||||
# 获取CPU类型
|
||||
ARCH=$(uname -m)
|
||||
# 转换CPU类型为go env arch格式
|
||||
if [ $ARCH = "x86_64" ]; then
|
||||
ARCH="amd64"
|
||||
elif [ $ARCH = "i686" ]; then
|
||||
ARCH="386"
|
||||
elif [ $ARCH = "armv6l" ]; then
|
||||
ARCH="armv6l"
|
||||
elif [ $ARCH = "aarch64" ]; then
|
||||
ARCH="arm64"
|
||||
else
|
||||
echo "Not support CPU, exit..."
|
||||
exit
|
||||
fi
|
||||
# 安装Golang
|
||||
echo "Download Golang..."
|
||||
echo $PREFIX/go${VERSION}.$OS-$ARCH.tar.gz
|
||||
curl -L $PREFIX/go${VERSION}.$OS-$ARCH.tar.gz -o /tmp/go${VERSION}.$OS-$ARCH.tar.gz
|
||||
tar -C /usr/local -xzf /tmp/go${VERSION}.$OS-$ARCH.tar.gz
|
||||
# 删除临时文件
|
||||
rm -f /tmp/go${VERSION}.$OS-$ARCH.tar.gz
|
||||
# 配置环境变量
|
||||
echo 'export PATH=$PATH:/usr/local/node/bin' >>/etc/profile
|
||||
|
||||
echo 'export PATH=$PATH:/usr/local/go/bin' >>/etc/profile
|
||||
|
||||
source /etc/profile
|
||||
|
||||
echo 'export PATH=$PATH:$(go env GOPATH)/bin' >>/etc/profile
|
||||
go env -w GO111MODULE=on
|
||||
go env -w GOPROXY=https://goproxy.cn,direct
|
||||
|
||||
source /etc/profile
|
||||
|
||||
# 安装成功
|
||||
echo "Install Golang success!"
|
||||
# 查看Golang版本
|
||||
go version
|
||||
# 提示重启终端
|
||||
echo "Please restart the terminal to take effect!"
|
||||
echo "安装成功,请重启终端使其生效!"
|
||||
echo "You can use 'source /etc/profile' command to make the PATH changes effective immediately."
|
||||
echo "你可以使用 'source /etc/profile' 命令使其立即生效."
|
||||
@@ -1,75 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Install Node.js on linux x86_64
|
||||
|
||||
# 出错时停止
|
||||
set -e
|
||||
|
||||
# 判断当前操作系统是否为Linux,如果不是则退出
|
||||
if [ "$(uname)" != "Linux" ]; then
|
||||
echo "Error: This script only supports Linux."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 获取当前CPU架构
|
||||
ARCH=$(uname -m)
|
||||
|
||||
# 判断当前CPU架构是否为x86_64,如果不是则退出
|
||||
if [ "$ARCH" != "x86_64" ]; then
|
||||
echo "Error: This script only supports x86_64."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 判断当前是否为root,如果不是则退出
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "Error: This script must be run as root."
|
||||
echo "You can use 'sudo su' command switch to root "
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 获取第一个参数为版本号
|
||||
VERSION=$1
|
||||
|
||||
# 校验版本号
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "Usage: $0 VERSION"
|
||||
echo "Example: $0 18.12.0"
|
||||
echo "You can visit https://nodejs.org/en/download/ to find version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 校验版本号格式
|
||||
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
||||
echo "Invalid version: $VERSION, should be like 1.2.3"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 下载安装包
|
||||
wget https://nodejs.org/dist/v$VERSION/node-v$VERSION-linux-x64.tar.xz
|
||||
|
||||
# 解压
|
||||
tar -xvf node-v$VERSION-linux-x64.tar.xz
|
||||
|
||||
# 移动到 /usr/local
|
||||
mv node-v$VERSION-linux-x64 /usr/local/node
|
||||
|
||||
# 添加到环境变量
|
||||
echo 'export PATH=$PATH:/usr/local/node/bin' >>/etc/profile
|
||||
|
||||
# 使环境变量生效
|
||||
source /etc/profile
|
||||
# 删除安装包
|
||||
rm node-v$VERSION-linux-x64.tar.xz
|
||||
# 查看版本
|
||||
node -v
|
||||
npm -v
|
||||
# 激活yarn
|
||||
corepack enable
|
||||
# 配置淘宝镜像
|
||||
npm config set registry https://registry.npmmirror.com
|
||||
# 查看配置
|
||||
npm config list
|
||||
# 提示安装成功
|
||||
echo "Node.js $VERSION installed successfully."
|
||||
# 提示用户重启终端
|
||||
echo "Please restart your terminal to make the PATH changes effective."
|
||||
echo "You can use 'source /etc/profile' command to make the PATH changes effective immediately."
|
||||
@@ -1,25 +0,0 @@
|
||||
# CoolAdminGo 文档
|
||||
|
||||
本文档使用`vuepress`编写,可使用`cool-tools docs`进行本地预览。版本随`CoolAdminGo`版本更新。
|
||||
|
||||
## 文档目录
|
||||
|
||||
- [介绍](introduction.md)
|
||||
- [问题反馈](feedback.md)
|
||||
- [开发环境](development.md)
|
||||
- [开发工具](cli.md)
|
||||
- [快速开始](quick_start.md)
|
||||
- [配置](config.md)
|
||||
- [CRUD](crud.md)
|
||||
- [数据库](database.md)
|
||||
- [文件上传](file_upload.md)
|
||||
- [表单验证](form_validate.md)
|
||||
- [系统模块](system_module.md)
|
||||
- [分布式函数](distributed_function.md)
|
||||
- [定时任务](cron.md)
|
||||
- [部署](deploy.md)
|
||||
- [日志](log.md)
|
||||
- [常见问题](faq.md)
|
||||
- [更新日志](changelog.md)
|
||||
- [已知问题](known_issues.md)
|
||||
- [贡献代码](contributing.md)
|
||||
@@ -1,92 +0,0 @@
|
||||
# 更新日志
|
||||
|
||||
## 1.5.0
|
||||
|
||||
- 更新 gf 至 v2.4.0
|
||||
|
||||
## 1.0.19
|
||||
|
||||
- 修复base/parma模块的bug 感谢 @vera-byte
|
||||
|
||||
## 1.0.18
|
||||
|
||||
- 增加app接口下的EPS以匹配cool-uni
|
||||
- 更新依赖
|
||||
|
||||
|
||||
## 1.0.17
|
||||
|
||||
- list page 接口增加 ModifyAfter 钩子,用于对数据进行修改
|
||||
- 更新 gf 至 v2.3.2
|
||||
|
||||
|
||||
## 1.0.16
|
||||
|
||||
- 更新依赖
|
||||
- cool-tools创建的项目增加容器开发环境
|
||||
|
||||
## 1.0.15
|
||||
|
||||
- 更新 gf 至 v2.3.1
|
||||
|
||||
## 1.0.14
|
||||
|
||||
- 更新 gf 至 v2.3.0
|
||||
- 调整 base 模块中的事务对象为接口定义以匹配 gf 的变更
|
||||
- 引入 redis 库(gf v2.3.0 版本 redis 拆分为单独的库)
|
||||
- 增加用户时对密码进行 md5 加密
|
||||
|
||||
## 1.0.13
|
||||
|
||||
- 增加 pgsql 支持
|
||||
- 调整部分表字段类型以兼容 pgsql
|
||||
|
||||
## 1.0.12
|
||||
|
||||
- 更新 gf 版本至 v2.2.6(sql 统计中 total 由 int64 修改为 int)
|
||||
|
||||
## 1.0.11
|
||||
|
||||
- 修复 dict 模块的 bug
|
||||
|
||||
## 1.0.10
|
||||
|
||||
- 修复 base/menu/add 不支持数组菜单的问题
|
||||
|
||||
## 1.0.9
|
||||
|
||||
- GetCfgWithDefault 函数支持环境变量,优先级 配置文件>环境变量>默认值
|
||||
- 更新 gf 版本至 v2.2.5 修复软删除 bug
|
||||
|
||||
## 1.0.8
|
||||
|
||||
- 更新依赖包版本
|
||||
- 调整 cool-tools version 命令输出格式
|
||||
- 修复 go install 模式安装的 cool-tools docs 命令无法使用的问题
|
||||
|
||||
## 1.0.7
|
||||
|
||||
- 更新 gf 依赖至 v2.2.4
|
||||
- cool-tools 增加 -y 支持
|
||||
- 集成 gf pack
|
||||
|
||||
## 1.0.6
|
||||
|
||||
- docs 独立为单独 mod,减小主库体积
|
||||
- 清理部分无用文件,减小主库体积
|
||||
- 更新依赖
|
||||
- 主库移除内置的前端
|
||||
- 增加 make frontend 命令,用于构建前端
|
||||
- 权限中间件移除部分 Debug 日志
|
||||
- 清理 cool-tools 模块部分无用文件
|
||||
- 引入 gf 的 run 命令至 cool-tools 模块
|
||||
- 引入 gf 的 build 命令至 cool-tools 模块
|
||||
- 调整 cool-tools 使用 hack 目录下的配置文件
|
||||
|
||||
## 1.0.5
|
||||
|
||||
- 本次更新主要针对主库开发环境
|
||||
- Added changelog.md
|
||||
- 更新主框架开发用前端打包脚本 使用 make public 更新
|
||||
- 更新主框架支持 remote container 开发, 基于`cool-admin-codespace`镜像
|
||||
- 调整优化文档发布,更新了一些依赖
|
||||
88
docs/cli.md
88
docs/cli.md
@@ -1,88 +0,0 @@
|
||||
# 开发工具
|
||||
|
||||
[返回目录](README.md)
|
||||
|
||||
::: warning 注意
|
||||
以下部分命令需您已经安装了 Go 语言环境,如果没有安装,请自行安装,如果已经安装,请自行配置环境变量
|
||||
:::
|
||||
|
||||
## cool-tools
|
||||
|
||||
cool-tools 是一个用于快速生成`CoolAdminGo`项目的脚手架工具,可用于快速生成项目、模块、页面、接口等。
|
||||
|
||||
### `cool-tools`安装
|
||||
|
||||
Linux, Mac 可使用以下命令安装:
|
||||
|
||||
从 github 下载
|
||||
|
||||
```bash
|
||||
wget -O cool-tools \
|
||||
https://github.com/cool-team-official/cool-admin-go/releases/latest/download/cool-tools_$(go env GOOS)_$(go env GOARCH) \
|
||||
&& chmod +x cool-tools \
|
||||
&& ./cool-tools install \
|
||||
&& rm ./cool-tools
|
||||
```
|
||||
|
||||
从镜像下载
|
||||
|
||||
```bash
|
||||
wget -O cool-tools \
|
||||
https://gh.hjmcloud.cn/github.com/cool-team-official/cool-admin-go/releases/latest/download/cool-tools_$(go env GOOS)_$(go env GOARCH) \
|
||||
&& chmod +x cool-tools \
|
||||
&& ./cool-tools install \
|
||||
&& rm ./cool-tools
|
||||
```
|
||||
|
||||
验证
|
||||
|
||||
```bash
|
||||
cool-tools version
|
||||
```
|
||||
|
||||
Windows 可以直接下载编译后的可执行文件,下载地址:[releases](https://github.com/cool-team-official/cool-admin-go/releases),选择对应的版本下载。下载后复制到`PATH`环境变量中的目录下即可。
|
||||
|
||||
::: tip 提示
|
||||
在正确地将 GOPATH/bin 目录添加到 PATH 环境变量中后,可以直接使用`go install`命令安装,因为该安装方式为本地编译安装,可享受`goproxy`的加速服务,安装速度更快,适用于所有平台。
|
||||
:::
|
||||
|
||||
```bash
|
||||
go install github.com/cool-team-official/cool-admin-go/cool-tools@latest
|
||||
```
|
||||
|
||||
|
||||
## gf
|
||||
|
||||
`GoFrame`框架提供了功能强大的`gf`命令行开发辅助工具,是框架发展的一个重要组成部分。
|
||||
|
||||
### `gf`安装
|
||||
|
||||
Linux, Mac 可使用以下命令安装:
|
||||
|
||||
从 github 下载
|
||||
|
||||
```bash
|
||||
wget -O gf \
|
||||
https://github.com/gogf/gf/releases/latest/download/gf_$(go env GOOS)_$(go env GOARCH) \
|
||||
&& chmod +x gf \
|
||||
&& ./gf install \
|
||||
&& rm ./gf
|
||||
```
|
||||
|
||||
使用镜像下载
|
||||
|
||||
```
|
||||
wget -O gf \
|
||||
https://gh.hjmcloud.cn/github.com/gogf/gf/releases/latest/download/gf_$(go env GOOS)_$(go env GOARCH) \
|
||||
&& chmod +x gf \
|
||||
&& ./gf install \
|
||||
&& rm ./gf
|
||||
```
|
||||
|
||||
验证
|
||||
|
||||
```bash
|
||||
gf version
|
||||
```
|
||||
|
||||
更多`gf`工具的安装使用说明,可以访问 [https://goframe.org/pages/viewpage.action?pageId=1114260](https://goframe.org/pages/viewpage.action?pageId=1114260)
|
||||
154
docs/config.md
154
docs/config.md
@@ -1,154 +0,0 @@
|
||||
# 配置
|
||||
|
||||
[返回目录](README.md)
|
||||
|
||||
## 配置文件
|
||||
|
||||
`CoolAdminGo`配置文件默认位于`mainfest/config/config.yaml`.继承自`GoFrame`的配置文件,支持多种格式,包括`yaml`、`toml`、`json`、`ini`、`xml`等。可访问[GoFrame 配置文件](https://goframe.org/pages/viewpage.action?pageId=1114668)查看更多配置文件格式。
|
||||
|
||||
## 数据库配置
|
||||
|
||||
`CoolAdminGo`支持多种数据库,可通过引入不同的依赖包进行切换,同时您也可以开发自己的数据库驱动。
|
||||
|
||||
### SQLite 配置
|
||||
|
||||
使用`sqllite`数据库时,需在`main.go`中引入`_ "github.com/cool-team-official/cool-admin-go/contrib/drivers/sqlite"`包,然后在`config.yaml`中配置`sqlite`数据库。
|
||||
|
||||
::: warning 注意
|
||||
`sqlite`引入应早于使用数据库的包, 为防止编辑器自动排序,可在数据包引入下方加一个空行。
|
||||
:::
|
||||
|
||||
```go
|
||||
// main.go
|
||||
import (
|
||||
// 引入sqlite驱动
|
||||
_ "github.com/cool-team-official/cool-admin-go/contrib/drivers/sqlite"
|
||||
|
||||
// 引入其他包
|
||||
"github.com/cool-team-official/cool-admin-go/pkg/dao"
|
||||
|
||||
)
|
||||
```
|
||||
|
||||
配置文件中相关配置如下:
|
||||
|
||||
```yaml
|
||||
database:
|
||||
default: # 数据源名称,当不指定数据源时 default 为默认数据源
|
||||
type: "sqlite" # 数据库类型
|
||||
link: "cool.sqlite" # 数据库文件名称,可以带路径,如:/tmp/cool.sqlite
|
||||
extra: busy_timeout=5000 # 数据库连接扩展参数
|
||||
createdAt: "createTime" # 创建时间字段
|
||||
updatedAt: "updateTime" # 更新时间字段
|
||||
debug: true # 是否开启调试模式,开启后会打印SQL日志
|
||||
```
|
||||
|
||||
### MySQL 配置
|
||||
|
||||
使用`mysql`数据库时,需在`main.go`中引入`_ "github.com/cool-team-official/cool-admin-go/contrib/drivers/mysql"`包,然后在`config.yaml`中配置`mysql`数据库。
|
||||
|
||||
::: warning 注意
|
||||
`mysql`引入应早于使用数据库的包, 为防止编辑器自动排序,可在数据包引入下方加一个空行。
|
||||
:::
|
||||
|
||||
```go
|
||||
// main.go
|
||||
import (
|
||||
// 引入mysql驱动
|
||||
_ "github.com/cool-team-official/cool-admin-go/contrib/drivers/mysql"
|
||||
|
||||
// 引入其他包
|
||||
"github.com/cool-team-official/cool-admin-go/pkg/dao"
|
||||
|
||||
)
|
||||
```
|
||||
|
||||
配置文件中相关配置如下:
|
||||
|
||||
```yaml
|
||||
database:
|
||||
default: # 数据源名称,当不指定数据源时 default 为默认数据源
|
||||
type: "mysql" # 数据库类型
|
||||
host: "127.0.0.1" # 数据库地址
|
||||
port: "3306" # 数据库端口
|
||||
user: "root" # 数据库用户名
|
||||
pass: "123456" # 数据库密码
|
||||
name: "cooltest" # 数据库名称
|
||||
charset: "utf8mb4" # 数据库编码
|
||||
timezone: "Asia/Shanghai" # 数据库时区
|
||||
debug: true # 是否开启调试模式,开启后会打印SQL日志
|
||||
createdAt: "createTime" # 创建时间字段
|
||||
updatedAt: "updateTime" # 更新时间字段
|
||||
```
|
||||
|
||||
可以使用`docker-compose`快速启动一个`mysql`数据库,配置如下:
|
||||
|
||||
```yaml
|
||||
# docker-compose.yaml
|
||||
version: "3"
|
||||
services:
|
||||
# mysql8 数据库
|
||||
mysql8:
|
||||
image: mysql:8
|
||||
container_name: mysql8
|
||||
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||
# restart: always # 重启策略
|
||||
environment:
|
||||
TZ: Asia/Shanghai # 指定时区
|
||||
MYSQL_ROOT_PASSWORD: "123456" # 配置root用户密码
|
||||
MYSQL_DATABASE: "cooltest" # 业务库名
|
||||
MYSQL_USER: "cooltest" # 业务库用户名
|
||||
MTSQL_PASSWORD: "123123" # 业务库密码
|
||||
ports:
|
||||
- 3306:3306
|
||||
volumes:
|
||||
- ./data/mysql/:/var/lib/mysql/
|
||||
```
|
||||
|
||||
启动`mysql`数据库:
|
||||
|
||||
```bash
|
||||
docker compose -f "docker-compose.yml" up -d --build mysql8
|
||||
```
|
||||
|
||||
关闭`mysql`数据库:
|
||||
|
||||
```bash
|
||||
docker compose -f "docker-compose.yml" down mysql8
|
||||
```
|
||||
|
||||
### PostgreSQL 配置
|
||||
|
||||
使用`postgresql`数据库时,需在`main.go`中引入`_ "github.com/cool-team-official/cool-admin-go/contrib/drivers/pgsql"`包,然后在`config.yaml`中配置`postgresql`数据库。
|
||||
|
||||
::: warning 注意
|
||||
`postgresql`引入应早于使用数据库的包, 为防止编辑器自动排序,可在数据包引入下方加一个空行。
|
||||
:::
|
||||
|
||||
```go
|
||||
// main.go
|
||||
import (
|
||||
// 引入postgresql驱动
|
||||
_ "github.com/cool-team-official/cool-admin-go/contrib/drivers/pgsql"
|
||||
|
||||
// 引入其他包
|
||||
"github.com/cool-team-official/cool-admin-go/pkg/dao"
|
||||
|
||||
)
|
||||
```
|
||||
|
||||
配置文件中相关配置如下:
|
||||
|
||||
```yaml
|
||||
database:
|
||||
default:
|
||||
type: "pgsql" # 数据库类型
|
||||
host: "127.0.0.1" # 数据库地址
|
||||
port: "5432" # 数据库端口
|
||||
user: "cooltest" # 数据库用户名
|
||||
pass: "123456" # 数据库密码
|
||||
name: "cooltest" # 数据库名称
|
||||
debug: true # 是否开启调试模式,开启后会打印SQL日志
|
||||
createdAt: "createTime" # 创建时间字段
|
||||
updatedAt: "updateTime" # 更新时间字段
|
||||
```
|
||||
@@ -1,118 +0,0 @@
|
||||
# 开发环境
|
||||
|
||||
[返回目录](README.md)
|
||||
|
||||
::: warning 注意
|
||||
推荐使用 Linux 或 MacOS 进行开发,Windows 下可使用 WSL2。
|
||||
|
||||
Linux 及 WSL2 下推荐使用 root 用户进行开发.
|
||||
:::
|
||||
|
||||
## Node.js 环境
|
||||
|
||||
官网下载地址:[https://nodejs.org/en/download/](https://nodejs.org/en/download/)
|
||||
|
||||
一般选择 LTS 版本即可。
|
||||
|
||||
MacOS 下可使用 Homebrew 进行安装 nvm:
|
||||
|
||||
```bash
|
||||
brew install nvm
|
||||
```
|
||||
|
||||
nvm 是 node 版本管理工具,可以通过`nvm install <version>` 安装指定版本,使用 `nvm use <version>` 切换版本。
|
||||
|
||||
或者直接下载 pkg 安装包进行安装。
|
||||
|
||||
Linux 下可使用以下脚本进行安装:
|
||||
|
||||
```bash
|
||||
wget -O nodejs-install.sh https://cool-team-official.github.io/cool-admin-go/scripts/nodejs-install.sh \
|
||||
&& chmod +x nodejs-install.sh \
|
||||
&& ./nodejs-install.sh 18.12.0
|
||||
```
|
||||
|
||||
脚本文件内容如下:
|
||||
|
||||
<<< @/docs/.vuepress/public/scripts/nodejs-install.sh
|
||||
|
||||
::: tip
|
||||
安装完成后,可使用`node -v`查看版本号,使用`npm -v`查看 npm 版本号。
|
||||
为提高依赖包下载速度,可使用`npm config set registry https://registry.npmmirror.com`切换到淘宝镜像。
|
||||
新版本的 node 已经集成了 yarn,需激活`corepack`,可使用 `corepack enable`命令激活。激活后可使用`yarn -v`查看版本号。
|
||||
|
||||
Linux 安装脚本已完成镜像切换及 corepack 激活。
|
||||
:::
|
||||
|
||||
## Go 环境
|
||||
|
||||
官网下载地址:[https://go.dev/dl/](https://go.dev/dl/)
|
||||
|
||||
一般选择最新版本即可。
|
||||
|
||||
MacOS 下可使用 Homebrew 进行安装:
|
||||
|
||||
```bash
|
||||
brew install go
|
||||
```
|
||||
|
||||
或者直接下载 pkg 安装包进行安装。
|
||||
|
||||
Linux 下可使用以下脚本进行安装:
|
||||
|
||||
```bash
|
||||
wget -O golang-install.sh https://cool-team-official.github.io/cool-admin-go/scripts/golang-install.sh \
|
||||
&& chmod +x golang-install.sh \
|
||||
&& ./golang-install.sh 1.19.3
|
||||
```
|
||||
|
||||
脚本文件内容如下:
|
||||
|
||||
<<< @/docs/.vuepress/public/scripts/golang-install.sh
|
||||
|
||||
::: tip
|
||||
安装完成后,可使用`go version`查看版本号。
|
||||
为提高依赖下载速度,推荐配置`goproxy`,可使用`go env -w GOPROXY=https://goproxy.cn,direct`切换到 goproxy.cn 镜像。
|
||||
:::
|
||||
|
||||
## VSCode
|
||||
|
||||
官网下载地址:[https://code.visualstudio.com/](https://code.visualstudio.com/)
|
||||
|
||||
一般选择最新版本即可。
|
||||
|
||||
推荐安装以下插件:
|
||||
|
||||
- [Go](https://marketplace.visualstudio.com/items?itemName=golang.go)
|
||||
- [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur)
|
||||
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
|
||||
- [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
|
||||
- [EditorConfig](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig)
|
||||
- [GitLens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens)
|
||||
|
||||
## Docker
|
||||
|
||||
云原生时代,Docker 已经成为开发者必备的工具之一。
|
||||
|
||||
开发过程中,我们将使用 Docker 进行数据库管理,以及打包测试。
|
||||
|
||||
官网下载地址:[https://www.docker.com/products/docker-desktop](https://www.docker.com/products/docker-desktop)
|
||||
|
||||
一般选择最新版本即可。
|
||||
|
||||
配置 Docker 镜像加速器:
|
||||
|
||||
```bash
|
||||
# Linux
|
||||
sudo mkdir -p /etc/docker
|
||||
sudo tee /etc/docker/daemon.json <<-'EOF'
|
||||
{
|
||||
"registry-mirrors": ["https://registry.docker-cn.com"]
|
||||
}
|
||||
EOF
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart docker
|
||||
|
||||
```
|
||||
|
||||
MacOS 及 Windows 下可在 Docker Desktop 的设置中配置。
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
# This script deploys the documentation to the gh-pages branch.
|
||||
# 发布文档到 https://cooladmingo.github.io
|
||||
|
||||
# 确保脚本抛出遇到的错误
|
||||
set -e
|
||||
# 检测是否存在 package.json,如果不存在,说明运行目录不对
|
||||
if [ ! -f "package.json" ]; then
|
||||
echo "package.json not found, please run this script in the root directory of the project"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# 生成静态文件
|
||||
npm run docs:build
|
||||
|
||||
# 进入生成的文件夹
|
||||
cd docs/.vuepress/dist
|
||||
|
||||
# 如果是发布到自定义域名
|
||||
# echo 'www.example.com' > CNAME
|
||||
|
||||
# 获取当前时间
|
||||
now=$(date "+%Y.%m.%d-%H.%M.%S")
|
||||
echo "${now}" > version.txt
|
||||
|
||||
|
||||
git init
|
||||
git add -A
|
||||
git commit -m 'deploy'
|
||||
|
||||
# 如果当前运行在 github codespace 中, 则使用 https 方式提交.否则使用 ssh 方式提交
|
||||
if [ -n "$CODESPACES" ]; then
|
||||
echo "github codespace detected, using https to push"
|
||||
git push -f https://github.com/cool-team-official/cool-admin-go.git main:gh-pages
|
||||
else
|
||||
echo "github codespace not detected, use ssh"
|
||||
git push -f git@github.com:cool-team-official/cool-admin-go.git master:gh-pages
|
||||
fi
|
||||
|
||||
# 如果发布到 https://<USERNAME>.github.io
|
||||
# git push -f git@github.com:cooladmingo/cooladmingo.github.io.git master:gh-pages
|
||||
# git push -f https://github.com/cool-team-official/cool-admin-go.git master:gh-pages
|
||||
|
||||
# 如果发布到 https://<USERNAME>.github.io/<REPO>
|
||||
# git push -f git@github.com:<USERNAME>/<REPO>.git master:gh-pages
|
||||
|
||||
cd -
|
||||
@@ -1 +0,0 @@
|
||||
package docs
|
||||
@@ -1,13 +0,0 @@
|
||||
# 问题反馈
|
||||
|
||||
[返回目录](README.md)
|
||||
|
||||
## 方式一
|
||||
|
||||
在代码仓库中提交[issue](https://github.com/cool-team-official/cool-admin-go/issues)
|
||||
|
||||
## 方式二
|
||||
|
||||
技术交流群
|
||||
|
||||

|
||||
@@ -1,3 +0,0 @@
|
||||
module github.com/cool-team-official/cool-admin-go/docs
|
||||
|
||||
go 1.18
|
||||
@@ -1,30 +0,0 @@
|
||||
# 项目介绍
|
||||
|
||||
[返回目录](README.md)
|
||||
|
||||
`CoolAdminGo` 基于 [goframe](https://goframe.org) 开发的后端项目,提供了基础的 CURD 结构,以及基础的用户管理模块,可以快速搭建后端项目。做为`CoolAdmin`系列的`go`版本后端,提供了与`node`版本后端相同的接口,可以快速切换前端项目。
|
||||
|
||||
`GoFrame`是一款模块化、高性能、企业级的 Go 基础开发框架。`GoFrame`是一款通用性的基础开发框架,是 Golang 标准库的一个增强扩展级,包含通用核心的基础开发组件,优点是实战化、模块化、文档全面、模块丰富、易用性高、通用性强、面向团队。如果您想使用 Golang 开发一个业务型项目,无论是小型还是中大型项目,`GoFrame`是您的不二之选。如果您想开发一个 Golang 组件库,`GoFrame`提供开箱即用、丰富强大的基础组件库也能助您的工作事半功倍。如果您是团队 Leader,`GoFrame`丰富的资料文档、详尽的代码注释、活跃的社区成员将会极大降低您的指导成本,支持团队快速接入、语言转型与能力提升。
|
||||
|
||||
## 代码仓库
|
||||
|
||||
CoolAdminGo 是开源免费的,遵循`MIT`开源协议,意味着您无需支付任何费用,也无需授权,即可将它应用到您的产品中。
|
||||
|
||||
::: warning 注意
|
||||
开源免费,并不意味着您可以将 cool-admin 应用到非法的领域,比如涉及赌博,暴力等方面。如因此产生纠纷等法律问题,cool-admin 不承担任何责任。
|
||||
:::
|
||||
|
||||
CoolAdminGo 代码仓库地址:[https://github.com/cool-team-official/cool-admin-go](https://github.com/cool-team-official/cool-admin-go)
|
||||
|
||||
::: tip 提示
|
||||
如果您觉得 CoolAdminGo 帮助到了您,欢迎给我们点个 star,您的支持是我们最大的动力。
|
||||
|
||||
通常情况下,您并不需要直接使用 CoolAdminGo 代码仓库,而是使用我们提供的脚手架工具,快速搭建项目。
|
||||
:::
|
||||
|
||||
## 技术选型
|
||||
|
||||
- [CoolAdmin](https://cool-js.com):`CoolAdmin` 项目官网。
|
||||
- [GoFrame](https://goframe.org):`GoFrame` 项目官网, `CoolAdminGo` 基于 `GoFrame` 开发。
|
||||
- [Gorm](https://gorm.io):`Gorm` 数据库操作库, `CoolAdminGo` 基于 `Gorm` 实现数据表创建功能。
|
||||
- [Goproxy](https://goproxy.cn):`Goproxy` 代理。
|
||||
@@ -1,4 +0,0 @@
|
||||
# 已知问题
|
||||
|
||||
[返回目录](README.md)
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
# 快速开始
|
||||
|
||||
[返回目录](README.md)
|
||||
|
||||
## 工程目录
|
||||
|
||||
一个合理的工程目录可以让开发更加高效,`CoolAdminGo`项目推荐的工程目录如下:
|
||||
|
||||
```bash
|
||||
# 假定项目名称为 cool-study
|
||||
|
||||
cool-study/
|
||||
├── backend # 后端代码
|
||||
├── cool-study # 主库,存放生产部署相关脚本等
|
||||
├── frontend # 前端代码
|
||||
└── mobile # 移动端代码
|
||||
```
|
||||
|
||||
## 创建后端项目
|
||||
|
||||
```bash
|
||||
# 创建工程目录
|
||||
mkdir cool-study
|
||||
# 进入工程目录
|
||||
cd cool-study
|
||||
# 创建后端代码目录
|
||||
cool-tools init backend
|
||||
# 进入后端代码目录
|
||||
cd backend
|
||||
# 安装依赖
|
||||
go mod tidy
|
||||
# 开发模式运行后端项目
|
||||
gf run main.go
|
||||
```
|
||||
|
||||
## 创建前端项目
|
||||
|
||||
```bash
|
||||
# 进入工程目录
|
||||
cd cool-study
|
||||
# 拉取前端代码
|
||||
git clone https://github.com/cool-team-official/cool-admin-vue frontend
|
||||
# 如果网络不好,可以使用国内镜像
|
||||
git clone https://gitee.com/cool-team-official/cool-admin-vue frontend
|
||||
# 进入前端代码目录
|
||||
cd frontend
|
||||
# 安装依赖
|
||||
yarn
|
||||
```
|
||||
@@ -1,5 +0,0 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
@@ -1,11 +0,0 @@
|
||||
# 🎨 editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
@@ -1 +0,0 @@
|
||||
vite.config.ts
|
||||
@@ -1,66 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true
|
||||
},
|
||||
parser: "vue-eslint-parser",
|
||||
parserOptions: {
|
||||
parser: "@typescript-eslint/parser",
|
||||
ecmaVersion: 2020,
|
||||
sourceType: "module",
|
||||
jsxPragma: "React",
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
tsx: true
|
||||
}
|
||||
},
|
||||
extends: [
|
||||
"plugin:vue/vue3-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
rules: {
|
||||
"@typescript-eslint/ban-ts-ignore": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"vue/component-name-in-template-casing": ["error", "kebab-case"],
|
||||
"vue/component-definition-name-casing": ["error", "kebab-case"],
|
||||
"no-use-before-define": "off",
|
||||
"@typescript-eslint/no-use-before-define": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/ban-types": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
argsIgnorePattern: "^h$",
|
||||
varsIgnorePattern: "^h$"
|
||||
}
|
||||
],
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
argsIgnorePattern: "^h$",
|
||||
varsIgnorePattern: "^h$"
|
||||
}
|
||||
],
|
||||
"space-before-function-paren": "off",
|
||||
"vue/attributes-order": "off",
|
||||
"vue/one-component-per-file": "off",
|
||||
"vue/html-closing-bracket-newline": "off",
|
||||
"vue/max-attributes-per-line": "off",
|
||||
"vue/multiline-html-element-content-newline": "off",
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/singleline-html-element-content-newline": "off",
|
||||
"vue/attribute-hyphenation": "off",
|
||||
"vue/html-self-closing": "off",
|
||||
"vue/require-default-prop": "off",
|
||||
"vue/v-on-event-hyphenation": "off"
|
||||
}
|
||||
};
|
||||
4
frontend/.gitattributes
vendored
4
frontend/.gitattributes
vendored
@@ -1,4 +0,0 @@
|
||||
*.js text eol=lf
|
||||
*.json text eol=lf
|
||||
*.ts text eol=lf
|
||||
*.vue text eol=lf
|
||||
5
frontend/.gitignore
vendored
5
frontend/.gitignore
vendored
@@ -1,5 +0,0 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"useTabs": true,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "none"
|
||||
}
|
||||
15
frontend/.vscode/config.code-snippets
vendored
15
frontend/.vscode/config.code-snippets
vendored
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"module-config": {
|
||||
"prefix": "module-config",
|
||||
"scope": "typescript",
|
||||
"body": [
|
||||
"import { ModuleConfig } from \"/@/cool\";",
|
||||
"",
|
||||
"export default (): ModuleConfig => {",
|
||||
" return {};",
|
||||
"};",
|
||||
""
|
||||
],
|
||||
"description": "module config snippets"
|
||||
}
|
||||
}
|
||||
66
frontend/.vscode/crud.code-snippets
vendored
66
frontend/.vscode/crud.code-snippets
vendored
@@ -1,66 +0,0 @@
|
||||
{
|
||||
"cl-crud": {
|
||||
"prefix": "cl-crud",
|
||||
"scope": "vue",
|
||||
"body": [
|
||||
"<template>",
|
||||
" <cl-crud ref=\"Crud\">",
|
||||
" <cl-row>",
|
||||
" <!-- 刷新按钮 -->",
|
||||
" <cl-refresh-btn />",
|
||||
" <!-- 新增按钮 -->",
|
||||
" <cl-add-btn />",
|
||||
" <!-- 删除按钮 -->",
|
||||
" <cl-multi-delete-btn />",
|
||||
" <cl-flex1 />",
|
||||
" <!-- 关键字搜索 -->",
|
||||
" <cl-search-key />",
|
||||
" </cl-row>",
|
||||
"",
|
||||
" <cl-row>",
|
||||
" <!-- 数据表格 -->",
|
||||
" <cl-table ref=\"Table\" />",
|
||||
" </cl-row>",
|
||||
"",
|
||||
" <cl-row>",
|
||||
" <cl-flex1 />",
|
||||
" <!-- 分页控件 -->",
|
||||
" <cl-pagination />",
|
||||
" </cl-row>",
|
||||
"",
|
||||
" <!-- 新增、编辑 -->",
|
||||
" <cl-upsert ref=\"Upsert\" />",
|
||||
" </cl-crud>",
|
||||
"</template>",
|
||||
"",
|
||||
"<script lang=\"ts\" name=\"菜单名称\" setup>",
|
||||
"import { useCrud, useTable, useUpsert } from \"@cool-vue/crud\";",
|
||||
"import { useCool } from \"/@/cool\";",
|
||||
"",
|
||||
"const { service } = useCool();",
|
||||
"",
|
||||
"// cl-upsert 配置",
|
||||
"const Upsert = useUpsert({",
|
||||
" items: []",
|
||||
"});",
|
||||
"",
|
||||
"// cl-table 配置",
|
||||
"const Table = useTable({",
|
||||
" columns: []",
|
||||
"});",
|
||||
"",
|
||||
"// cl-crud 配置",
|
||||
"const Crud = useCrud(",
|
||||
" {",
|
||||
" service: service.demo.goods",
|
||||
" },",
|
||||
" (app) => {",
|
||||
" app.refresh();",
|
||||
" }",
|
||||
");",
|
||||
"</script>",
|
||||
""
|
||||
],
|
||||
"description": "cl-crud snippets"
|
||||
}
|
||||
}
|
||||
4
frontend/.vscode/settings.json
vendored
4
frontend/.vscode/settings.json
vendored
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"editor.cursorSmoothCaretAnimation": true,
|
||||
"editor.formatOnSave": true,
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
FROM node:lts-alpine
|
||||
WORKDIR /build
|
||||
# 设置Node-Sass的镜像地址
|
||||
RUN npm config set sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
|
||||
# 设置npm镜像
|
||||
RUN npm config set registry https://registry.npm.taobao.org
|
||||
COPY package.json /build/package.json
|
||||
RUN yarn
|
||||
COPY ./ /build
|
||||
RUN npm run build
|
||||
|
||||
FROM nginx
|
||||
RUN mkdir /app
|
||||
COPY --from=0 /build/dist /app
|
||||
COPY --from=0 /build/nginx.conf /etc/nginx/nginx.conf
|
||||
EXPOSE 80
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 cool-team-official
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,65 +0,0 @@
|
||||
# cool-admin [vue3 - ts - vite]
|
||||
|
||||
<p align="center">
|
||||
<a href="https://show.cool-admin.com/" target="blank"><img src="https://admin.cool-js.com/logo.png" width="200" alt="cool-admin Logo" /></a>
|
||||
</p>
|
||||
|
||||
<p align="center">cool-admin 一个很酷的后台权限管理系统,开源免费,模块化、插件化、极速开发 CRUD,方便快速构建迭代后台管理系统, 到<a href="https://cool-js.com" target="_blank">文档</a> 进一步了解</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/cool-team-official/cool-admin-vue/blob/master/LICENSE" target="_blank"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="GitHub license" />
|
||||
<a href=""><img src="https://img.shields.io/github/package-json/v/cool-team-official/cool-admin-vue?style=flat-square" alt="GitHub tag"></a>
|
||||
<img src="https://img.shields.io/github/last-commit/cool-team-official/cool-admin-vue?style=flat-square" alt="GitHub tag"></a>
|
||||
</p>
|
||||
|
||||
## 地址
|
||||
|
||||
- [⚡️ vue2.x + element-ui](https://github.com/cool-team-official/cool-admin-vue)
|
||||
|
||||
- [⚡️ vue3.x + element-plus + ts + webpack](https://github.com/cool-team-official/cool-admin-vue/tree/vue3-ts-webpack)
|
||||
|
||||
- [📌 vue3.x + element-plus + ts + vite](https://github.com/cool-team-official/cool-admin-vue/tree/vue3-ts-vite)
|
||||
|
||||
- [🌐 码云仓库地址](https://gitee.com/cool-team-official/cool-admin-vue)
|
||||
|
||||
## 演示
|
||||
|
||||
[https://show.cool-admin.com](https://show.cool-admin.com)
|
||||
|
||||
账户:admin,密码:123456
|
||||
|
||||
<img src="https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/home-mini.png" alt="Admin Home" ></a>
|
||||
|
||||
## 项目后端
|
||||
|
||||
[https://github.com/cool-team-official/cool-admin-midway](https://github.com/cool-team-official/cool-admin-midway)
|
||||
|
||||
## 微信群
|
||||
|
||||
<img width="260" src="https://cool-show.oss-cn-shanghai.aliyuncs.com/admin/wechat.jpeg" alt="Admin Wechat"></a>
|
||||
|
||||
## 安装项目依赖
|
||||
|
||||
推荐使用 `yarn`:
|
||||
|
||||
```shell
|
||||
yarn
|
||||
```
|
||||
|
||||
解决 `node-sass` 网络慢的方法:
|
||||
|
||||
```shell
|
||||
yarn config set sass-binary-site http://npm.taobao.org/mirrors/node-sass
|
||||
```
|
||||
|
||||
## 运行应用程序
|
||||
|
||||
安装过程完成后,运行以下命令启动服务。您可以在浏览器中预览网站 [http://localhost:9000](http://localhost:9000)
|
||||
|
||||
```shell
|
||||
yarn dev
|
||||
```
|
||||
|
||||
### 低价服务器
|
||||
|
||||
[阿里云、腾讯云、华为云低价云服务器,不限新老](https://cool-js.com/ad/server.html)
|
||||
@@ -1,69 +0,0 @@
|
||||
import { Plugin } from "vite";
|
||||
import { parseJson } from "./utils";
|
||||
import { createEps, createMenu, createSvg, createTag, getEps, getModules } from "./lib";
|
||||
|
||||
export function cool(): Plugin {
|
||||
return {
|
||||
name: "vite-cool",
|
||||
enforce: "pre",
|
||||
configureServer(server) {
|
||||
server.middlewares.use(async (req, res, next) => {
|
||||
function done(data: any) {
|
||||
res.writeHead(200, { "Content-Type": "text/html;charset=UTF-8" });
|
||||
res.end(JSON.stringify(data));
|
||||
}
|
||||
|
||||
if (req.url?.includes("__cool")) {
|
||||
const body = await parseJson(req);
|
||||
let next: any;
|
||||
|
||||
switch (req.url) {
|
||||
// 快速创建菜单
|
||||
case "/__cool_createMenu":
|
||||
next = createMenu(body);
|
||||
break;
|
||||
|
||||
// 获取模块列表
|
||||
case "/__cool_modules":
|
||||
next = getModules();
|
||||
break;
|
||||
|
||||
// 创建描述文件
|
||||
case "/__cool_eps":
|
||||
next = createEps(body);
|
||||
break;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next.then((data: any) => {
|
||||
done({
|
||||
code: 1000,
|
||||
data
|
||||
});
|
||||
}).catch((err: Error) => {
|
||||
done({
|
||||
code: 1001,
|
||||
message: err.message
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
},
|
||||
transform(code, id) {
|
||||
return createTag(code, id);
|
||||
},
|
||||
transformIndexHtml(html) {
|
||||
return createSvg(html);
|
||||
},
|
||||
config() {
|
||||
return {
|
||||
define: {
|
||||
__EPS__: getEps()
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
export default {
|
||||
entity: {
|
||||
mapping: [
|
||||
{
|
||||
// 自定义匹配
|
||||
custom: ({ entityName, propertyName, type }) => {
|
||||
// status 原本是tinyint,如果是1的话,== true 是可以的,但是不能 === true,请谨慎使用
|
||||
if (propertyName === "status" && type == "tinyint") return "boolean";
|
||||
// 如果没有,返回null或者不返回,则继续遍历其他匹配规则
|
||||
return null;
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
test: ["varchar", "text","simple-json"]
|
||||
},
|
||||
{
|
||||
type: "string[]",
|
||||
test: ["simple-array"]
|
||||
},
|
||||
{
|
||||
type: "Date",
|
||||
test: ["datetime", "date"]
|
||||
},
|
||||
{
|
||||
type: "number",
|
||||
test: ["tinyint", "int", "decimal"]
|
||||
},
|
||||
{
|
||||
type: "BigInt",
|
||||
test: ["bigint"]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
@@ -1,311 +0,0 @@
|
||||
import prettier from "prettier";
|
||||
import { isEmpty, last } from "lodash";
|
||||
import { createDir, firstUpperCase, readFile, toCamel } from "../../utils";
|
||||
import { createWriteStream } from "fs";
|
||||
import { join } from "path";
|
||||
import config from "./config";
|
||||
|
||||
interface Options {
|
||||
list: {
|
||||
prefix: string;
|
||||
name: string;
|
||||
columns: any[];
|
||||
api: {
|
||||
name: string;
|
||||
method: string;
|
||||
path: string;
|
||||
summary: string;
|
||||
dts: {
|
||||
parameters: {
|
||||
description: string;
|
||||
schema: {
|
||||
type: string;
|
||||
};
|
||||
name: string;
|
||||
required: boolean;
|
||||
}[];
|
||||
};
|
||||
}[];
|
||||
}[];
|
||||
service: {
|
||||
[key: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
// 临时目录路径
|
||||
const tempPath = join(__dirname, "../../temp");
|
||||
|
||||
// 获取类型
|
||||
function getType({ entityName, propertyName, type }) {
|
||||
for (const map of config.entity.mapping) {
|
||||
if (map.custom) {
|
||||
const resType = map.custom({ entityName, propertyName, type });
|
||||
if (resType) return resType;
|
||||
}
|
||||
if (map.test) {
|
||||
if (map.test.includes(type)) return map.type;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// 创建 Entity
|
||||
function createEntity({ list }: Options) {
|
||||
const t0: any[] = [];
|
||||
|
||||
for (const item of list) {
|
||||
if (!item.name) continue;
|
||||
const t = [`interface ${item.name} {`];
|
||||
for (const col of item.columns || []) {
|
||||
// 描述
|
||||
t.push("\n");
|
||||
t.push("/**\n");
|
||||
t.push(` * ${col.comment}\n`);
|
||||
t.push(" */\n");
|
||||
t.push(
|
||||
`${col.propertyName}?: ${getType({
|
||||
entityName: item.name,
|
||||
propertyName: col.propertyName,
|
||||
type: col.type
|
||||
})};`
|
||||
);
|
||||
}
|
||||
t.push("\n");
|
||||
t.push("/**\n");
|
||||
t.push(` * 任意键值\n`);
|
||||
t.push(" */\n");
|
||||
t.push(`[key: string]: any;`);
|
||||
t.push("}");
|
||||
t0.push(t);
|
||||
}
|
||||
|
||||
return t0.map((e) => e.join("")).join("\n\n");
|
||||
}
|
||||
|
||||
// 创建 Service
|
||||
function createService({ list, service }: Options) {
|
||||
const t0: any[] = [];
|
||||
|
||||
const t1 = [
|
||||
`type Service = {
|
||||
request(options: {
|
||||
url: string;
|
||||
method?: 'POST' | 'GET' | string;
|
||||
data?: any;
|
||||
params?: any;
|
||||
proxy?: boolean;
|
||||
[key: string]: any;
|
||||
}): Promise<any>;
|
||||
`
|
||||
];
|
||||
|
||||
// 处理数据
|
||||
function deep(d: any, k?: string) {
|
||||
if (!k) k = "";
|
||||
|
||||
for (const i in d) {
|
||||
const name = k + toCamel(firstUpperCase(i.replace(/[:]/g, "")));
|
||||
|
||||
if (d[i].namespace) {
|
||||
// 查找配置
|
||||
const item = list.find((e) => (e.prefix || "").includes(d[i].namespace));
|
||||
|
||||
if (item) {
|
||||
const t = [`interface ${name} {`];
|
||||
|
||||
t1.push(`${i}: ${name};`);
|
||||
|
||||
// 插入方法
|
||||
if (item.api) {
|
||||
// 权限列表
|
||||
const permission: string[] = [];
|
||||
|
||||
item.api.forEach((a) => {
|
||||
// 方法名
|
||||
const n = toCamel(a.name || last(a.path.split("/")) || "").replace(
|
||||
/[:\/-]/g,
|
||||
""
|
||||
);
|
||||
|
||||
if (n) {
|
||||
// 参数类型
|
||||
let q: string[] = [];
|
||||
|
||||
// 参数列表
|
||||
const { parameters = [] } = a.dts || {};
|
||||
|
||||
parameters.forEach((p) => {
|
||||
if (p.description) {
|
||||
q.push(`\n/** ${p.description} */\n`);
|
||||
}
|
||||
|
||||
if (p.name.includes(":")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const a = `${p.name}${p.required ? "" : "?"}`;
|
||||
const b = `${p.schema.type || "string"}`;
|
||||
|
||||
q.push(`${a}: ${b},`);
|
||||
});
|
||||
|
||||
if (isEmpty(q)) {
|
||||
q = ["any"];
|
||||
} else {
|
||||
q.unshift("{");
|
||||
q.push("}");
|
||||
}
|
||||
|
||||
// 返回类型
|
||||
let res = "";
|
||||
|
||||
// 实体名
|
||||
const en = item.name || "any";
|
||||
|
||||
switch (a.path) {
|
||||
case "/page":
|
||||
res = `
|
||||
{
|
||||
pagination: { size: number; page: number; total: number };
|
||||
list: ${en} [];
|
||||
[key: string]: any;
|
||||
}
|
||||
`;
|
||||
break;
|
||||
|
||||
case "/list":
|
||||
res = `${en} []`;
|
||||
break;
|
||||
|
||||
case "/info":
|
||||
res = en;
|
||||
break;
|
||||
|
||||
default:
|
||||
res = "any";
|
||||
break;
|
||||
}
|
||||
|
||||
// 描述
|
||||
t.push("\n");
|
||||
t.push("/**\n");
|
||||
t.push(` * ${a.summary || n}\n`);
|
||||
t.push(" */\n");
|
||||
|
||||
t.push(
|
||||
`${n}(data${q.length == 1 ? "?" : ""}: ${q.join(
|
||||
""
|
||||
)}): Promise<${res}>;`
|
||||
);
|
||||
}
|
||||
|
||||
permission.push(n);
|
||||
});
|
||||
|
||||
// 权限标识
|
||||
t.push("\n");
|
||||
t.push("/**\n");
|
||||
t.push(" * 权限标识\n");
|
||||
t.push(" */\n");
|
||||
t.push(
|
||||
`permission: { ${permission.map((e) => `${e}: string;`).join("\n")} };`
|
||||
);
|
||||
|
||||
// 权限状态
|
||||
t.push("\n");
|
||||
t.push("/**\n");
|
||||
t.push(" * 权限状态\n");
|
||||
t.push(" */\n");
|
||||
t.push(
|
||||
`_permission: { ${permission
|
||||
.map((e) => `${e}: boolean;`)
|
||||
.join("\n")} };`
|
||||
);
|
||||
|
||||
// 请求
|
||||
t.push("\n");
|
||||
t.push("/**\n");
|
||||
t.push(" * 请求\n");
|
||||
t.push(" */\n");
|
||||
t.push(`request: Service['request']`);
|
||||
}
|
||||
|
||||
t.push("}");
|
||||
t0.push(t);
|
||||
}
|
||||
} else {
|
||||
t1.push(`${i}: {`);
|
||||
deep(d[i], name);
|
||||
t1.push(`},`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 深度
|
||||
deep(service);
|
||||
|
||||
// 结束
|
||||
t1.push("}");
|
||||
|
||||
// 追加
|
||||
t0.push(t1);
|
||||
|
||||
return t0.map((e) => e.join("")).join("\n\n");
|
||||
}
|
||||
|
||||
// 创建描述文件
|
||||
export async function createEps(options: Options) {
|
||||
// 文件内容
|
||||
const text = `
|
||||
declare namespace Eps {
|
||||
${createEntity(options)}
|
||||
${createService(options)}
|
||||
}
|
||||
`;
|
||||
|
||||
// 文本内容
|
||||
const content = prettier.format(text, {
|
||||
parser: "typescript",
|
||||
useTabs: true,
|
||||
tabWidth: 4,
|
||||
endOfLine: "lf",
|
||||
semi: true,
|
||||
singleQuote: false,
|
||||
printWidth: 100,
|
||||
trailingComma: "none"
|
||||
});
|
||||
|
||||
// 创建 temp 目录
|
||||
createDir(tempPath);
|
||||
|
||||
// 创建 eps 描述文件
|
||||
createWriteStream(join(tempPath, "eps.d.ts"), {
|
||||
flags: "w"
|
||||
}).write(content);
|
||||
|
||||
// 创建 eps 数据文件
|
||||
createWriteStream(join(tempPath, "eps.json"), {
|
||||
flags: "w"
|
||||
}).write(
|
||||
JSON.stringify(
|
||||
(options.list || []).map((e) => {
|
||||
const req = e.api.map((a) => {
|
||||
const arr = [a.name ? `/${a.name}` : a.path];
|
||||
|
||||
if (a.method) {
|
||||
arr.push(a.method);
|
||||
}
|
||||
|
||||
return arr;
|
||||
});
|
||||
|
||||
return [e.prefix, e.name || "", req];
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// 获取描述
|
||||
export function getEps() {
|
||||
return JSON.stringify(readFile(join(tempPath, "eps.json")));
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export * from "./eps";
|
||||
export * from "./menu";
|
||||
export * from "./module";
|
||||
export * from "./svg";
|
||||
export * from "./tag";
|
||||
@@ -1,364 +0,0 @@
|
||||
import { createWriteStream } from "fs";
|
||||
import prettier from "prettier";
|
||||
import { join } from "path";
|
||||
import { mkdirs } from "../../utils";
|
||||
import rules from "./rules";
|
||||
import { isFunction, isRegExp, isString } from "lodash";
|
||||
|
||||
// 格式化
|
||||
function format(data: any) {
|
||||
return {
|
||||
label: data.label,
|
||||
prop: data.prop,
|
||||
...data,
|
||||
component: data.component
|
||||
};
|
||||
}
|
||||
|
||||
// 颜色
|
||||
const colors = [
|
||||
"#409EFF",
|
||||
"#67C23A",
|
||||
"#E6A23C",
|
||||
"#F56C6C",
|
||||
"#909399",
|
||||
"#B0CFEB",
|
||||
"#FF9B91",
|
||||
"#E6A23C",
|
||||
"#BFAD6F",
|
||||
"#FB78F2"
|
||||
];
|
||||
|
||||
// 组件处理器
|
||||
const handler = {
|
||||
// 单选
|
||||
dict({ comment }) {
|
||||
const [label, ...arr] = comment.split(" ");
|
||||
|
||||
// 选择列表
|
||||
const list = arr.map((e: string, i: number) => {
|
||||
const [value, label] = e.split("-");
|
||||
const d: any = {
|
||||
label,
|
||||
value: isNaN(Number(value)) ? value : Number(value)
|
||||
};
|
||||
|
||||
if (i > 0 && colors[i]) {
|
||||
d.color = colors[i];
|
||||
}
|
||||
|
||||
return d;
|
||||
});
|
||||
|
||||
const d: any = {
|
||||
table: {
|
||||
label,
|
||||
dict: list
|
||||
},
|
||||
form: {
|
||||
label,
|
||||
component: {
|
||||
name: "",
|
||||
options: list
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 默认值
|
||||
if (list[0]) {
|
||||
d.form.value = list[0].value;
|
||||
}
|
||||
|
||||
// 匹配组件
|
||||
d.form.component.name = arr.length > 4 ? "el-select" : "el-radio-group";
|
||||
|
||||
return d;
|
||||
},
|
||||
|
||||
// 多选
|
||||
dict_multiple({ comment }) {
|
||||
const { table, form }: any = handler.dict({ comment });
|
||||
|
||||
if (!form.component.props) {
|
||||
form.component.props = {};
|
||||
}
|
||||
|
||||
if (!form.value) {
|
||||
form.value = [];
|
||||
}
|
||||
|
||||
switch (form.component.name) {
|
||||
case "el-select":
|
||||
form.component.props.multiple = true;
|
||||
form.component.props.filterable = true;
|
||||
break;
|
||||
case "el-radio-group":
|
||||
form.component.name = "el-checkbox-group";
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
table,
|
||||
form
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// 创建组件
|
||||
function createComponent(item: any) {
|
||||
const prop = item.propertyName;
|
||||
let label = item.comment;
|
||||
let d: any;
|
||||
|
||||
rules.forEach((r: any) => {
|
||||
const s = r.test.find((e: any) => {
|
||||
if (isRegExp(e)) {
|
||||
return e.test(prop);
|
||||
}
|
||||
|
||||
if (isFunction(e)) {
|
||||
return e(prop);
|
||||
}
|
||||
|
||||
if (isString(e)) {
|
||||
const re = new RegExp(`${e}$`);
|
||||
return re.test(prop.toLocaleLowerCase());
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (s) {
|
||||
if (r.handler) {
|
||||
const fn = isString(r.handler) ? handler[r.handler] : r.handler;
|
||||
|
||||
if (isFunction(fn)) {
|
||||
d = fn(item);
|
||||
}
|
||||
} else {
|
||||
d = {
|
||||
...r,
|
||||
test: undefined
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function parse(v: any) {
|
||||
label = label.split(" ")[0];
|
||||
|
||||
if (v?.name) {
|
||||
return {
|
||||
prop,
|
||||
label,
|
||||
component: v
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
prop,
|
||||
label,
|
||||
...v
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
column: parse(d?.table),
|
||||
item: parse(d?.form)
|
||||
};
|
||||
}
|
||||
|
||||
// 获取页面标识
|
||||
function getPageName(router: string) {
|
||||
if (router.indexOf("/") === 0) {
|
||||
router = router.substr(1, router.length);
|
||||
}
|
||||
|
||||
return router ? router.replace(/\//g, "-") : "";
|
||||
}
|
||||
|
||||
// 时间合并
|
||||
function datetimeMerge({ columns, item }: any) {
|
||||
if (["startTime", "startDate"].includes(item.prop)) {
|
||||
const key = item.prop.replace("start", "");
|
||||
|
||||
if (columns.find((e: any) => e.propertyName == "end" + key)) {
|
||||
item.prop = key.toLocaleLowerCase();
|
||||
const isTime = item.prop == "time";
|
||||
item.label = isTime ? "时间范围" : "日期范围";
|
||||
item.hook = "datetimeRange";
|
||||
item.component = {
|
||||
name: "el-date-picker",
|
||||
props: {
|
||||
type: isTime ? "datetimerange" : "daterange",
|
||||
valueFormat: isTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD 00:00:00",
|
||||
defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建文件
|
||||
export async function createMenu({ router, columns, prefix, api, filePath }: any) {
|
||||
const upsert: any = {
|
||||
items: []
|
||||
};
|
||||
|
||||
const table: any = {
|
||||
columns: []
|
||||
};
|
||||
|
||||
// 遍历
|
||||
columns.forEach((e: any) => {
|
||||
// 组件
|
||||
const { item, column }: any = createComponent(e);
|
||||
|
||||
// 验证规则
|
||||
if (!e.nullable) {
|
||||
item.required = true;
|
||||
}
|
||||
|
||||
// 忽略部分字段
|
||||
if (!["createTime", "updateTime", "id", "endTime", "endDate"].includes(item.prop)) {
|
||||
datetimeMerge({ columns, item });
|
||||
|
||||
if (!item.component) {
|
||||
item.component = {
|
||||
name: "el-input"
|
||||
};
|
||||
}
|
||||
|
||||
upsert.items.push(format(item));
|
||||
}
|
||||
|
||||
if (!column.component?.name.includes("cl-editor-")) {
|
||||
table.columns.push(format(column));
|
||||
}
|
||||
});
|
||||
|
||||
// 服务
|
||||
const service = prefix.replace("/admin", "service").replace(/\//g, ".");
|
||||
|
||||
// 请求路径
|
||||
const paths = api.map((e: any) => e.path);
|
||||
|
||||
// 权限
|
||||
const permission: any = {
|
||||
add: paths.includes("/add"),
|
||||
del: paths.includes("/delete"),
|
||||
update: paths.includes("/info") && paths.includes("/update"),
|
||||
page: paths.includes("/page"),
|
||||
upsert: true
|
||||
};
|
||||
permission.upsert = permission.add || permission.update;
|
||||
|
||||
// 是否有操作栏
|
||||
if (permission.del || permission.upsert) {
|
||||
const d: any = {
|
||||
type: "op",
|
||||
buttons: []
|
||||
};
|
||||
|
||||
if (permission.upsert) {
|
||||
d.buttons.push("edit");
|
||||
}
|
||||
|
||||
if (permission.del) {
|
||||
d.buttons.push("delete");
|
||||
}
|
||||
|
||||
table.columns.push(d);
|
||||
}
|
||||
|
||||
// 是否多选、序号
|
||||
if (permission.del) {
|
||||
table.columns.unshift({
|
||||
type: "selection"
|
||||
});
|
||||
} else {
|
||||
table.columns.unshift({
|
||||
label: "#",
|
||||
type: "index"
|
||||
});
|
||||
}
|
||||
|
||||
// 代码模板
|
||||
const temp = `<template>
|
||||
<cl-crud ref="Crud">
|
||||
<cl-row>
|
||||
<!-- 刷新按钮 -->
|
||||
<cl-refresh-btn />
|
||||
${permission.add ? "<!-- 新增按钮 -->\n<cl-add-btn />" : ""}
|
||||
${permission.del ? "<!-- 删除按钮 -->\n<cl-multi-delete-btn />" : ""}
|
||||
<cl-flex1 />
|
||||
<!-- 关键字搜索 -->
|
||||
<cl-search-key />
|
||||
</cl-row>
|
||||
|
||||
<cl-row>
|
||||
<!-- 数据表格 -->
|
||||
<cl-table ref="Table" />
|
||||
</cl-row>
|
||||
|
||||
<cl-row>
|
||||
<cl-flex1 />
|
||||
<!-- 分页控件 -->
|
||||
<cl-pagination />
|
||||
</cl-row>
|
||||
|
||||
<!-- 新增、编辑 -->
|
||||
<cl-upsert ref="Upsert" />
|
||||
</cl-crud>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="${getPageName(router)}" setup>
|
||||
import { useCrud, useTable, useUpsert } from "@cool-vue/crud";
|
||||
import { useCool } from "/@/cool";
|
||||
|
||||
const { service } = useCool();
|
||||
|
||||
// cl-upsert 配置
|
||||
const Upsert = useUpsert(${JSON.stringify(upsert)});
|
||||
|
||||
// cl-table 配置
|
||||
const Table = useTable(${JSON.stringify(table)});
|
||||
|
||||
// cl-crud 配置
|
||||
const Crud = useCrud(
|
||||
{
|
||||
service: ${service}
|
||||
},
|
||||
(app) => {
|
||||
app.refresh();
|
||||
}
|
||||
);
|
||||
</script>`;
|
||||
|
||||
// 文件内容
|
||||
const content = prettier.format(temp, {
|
||||
parser: "vue",
|
||||
useTabs: true,
|
||||
tabWidth: 4,
|
||||
endOfLine: "lf",
|
||||
semi: true,
|
||||
jsxBracketSameLine: true,
|
||||
singleQuote: false,
|
||||
printWidth: 100,
|
||||
trailingComma: "none"
|
||||
});
|
||||
|
||||
// 目录路径
|
||||
const dir = filePath.split("/");
|
||||
|
||||
// 文件名
|
||||
const fname = dir.pop();
|
||||
|
||||
// 创建目录
|
||||
const path = mkdirs(`./src/modules/${dir.join("/")}`);
|
||||
|
||||
// 创建文件
|
||||
createWriteStream(join(path, fname), {
|
||||
flags: "w"
|
||||
}).write(content);
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
export default [
|
||||
{
|
||||
test: ["avatar", "img", "image", "pic", "photo", "picture", "head", "icon"],
|
||||
table: {
|
||||
name: "cl-image",
|
||||
props: {
|
||||
size: 60
|
||||
}
|
||||
},
|
||||
form: {
|
||||
name: "cl-upload"
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["avatars", "imgs", "images", "pics", "photos", "pictures", "heads", "icons"],
|
||||
table: {
|
||||
name: "cl-image",
|
||||
props: {
|
||||
size: 60
|
||||
}
|
||||
},
|
||||
form: {
|
||||
name: "cl-upload",
|
||||
props: {
|
||||
listType: "picture-card",
|
||||
multiple: true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["file", "attachment", "attach", "url", "video", "music"],
|
||||
table: {
|
||||
name: "cl-link"
|
||||
},
|
||||
form: {
|
||||
name: "cl-upload",
|
||||
props: {
|
||||
listType: "text",
|
||||
limit: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["files", "attachments", "attachs", "urls", "videos", "musics"],
|
||||
table: {
|
||||
name: "cl-link"
|
||||
},
|
||||
form: {
|
||||
name: "cl-upload",
|
||||
props: {
|
||||
listType: "text",
|
||||
multiple: true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["enable", "status"],
|
||||
table: {
|
||||
name: "cl-switch"
|
||||
},
|
||||
form: {
|
||||
name: "el-switch"
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["type", "classify", "category"],
|
||||
handler: "dict"
|
||||
},
|
||||
{
|
||||
test: ["types", "classifys", "categorys"],
|
||||
handler: "dict_multiple"
|
||||
},
|
||||
{
|
||||
test: ["date"],
|
||||
table: {
|
||||
name: "cl-date-text",
|
||||
props: {
|
||||
format: "YYYY-MM-DD"
|
||||
}
|
||||
},
|
||||
form: {
|
||||
name: "el-date-picker",
|
||||
props: {
|
||||
type: "date",
|
||||
valueFormat: "YYYY-MM-DD"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["dates", "dateRange", "dateScope"],
|
||||
table: {
|
||||
name: "cl-date-text",
|
||||
props: {
|
||||
format: "YYYY-MM-DD"
|
||||
}
|
||||
},
|
||||
form: {
|
||||
component: {
|
||||
name: "el-date-picker",
|
||||
props: {
|
||||
type: "daterange",
|
||||
valueFormat: "YYYY-MM-DD"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["time"],
|
||||
form: {
|
||||
name: "el-date-picker",
|
||||
props: {
|
||||
type: "datetime",
|
||||
valueFormat: "YYYY-MM-DD HH:mm:ss"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["times", "timeRange", "timeScope"],
|
||||
form: {
|
||||
component: {
|
||||
name: "el-date-picker",
|
||||
props: {
|
||||
type: "datetimerange",
|
||||
valueFormat: "YYYY-MM-DD HH:mm:ss",
|
||||
defaultTime: [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["star", "stars"],
|
||||
table: {
|
||||
name: "el-rate",
|
||||
props: {
|
||||
disabled: true
|
||||
}
|
||||
},
|
||||
form: {
|
||||
name: "el-rate"
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["progress", "rate", "ratio"],
|
||||
table: {
|
||||
name: "el-progress"
|
||||
},
|
||||
form: {
|
||||
name: "el-slider",
|
||||
props: {
|
||||
style: {
|
||||
width: "200px"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["num", "price", "age", "amount"],
|
||||
form: {
|
||||
name: "el-input-number",
|
||||
props: {
|
||||
min: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["remark", "desc"],
|
||||
table: {
|
||||
showOverflowTooltip: true
|
||||
},
|
||||
form: {
|
||||
name: "el-input",
|
||||
props: {
|
||||
type: "textarea",
|
||||
rows: 4
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["rich", "text", "html", "content", "introduce", "description", "desc"],
|
||||
form: {
|
||||
name: "cl-editor-wang"
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["code", "codes"],
|
||||
form: {
|
||||
name: "cl-editor-monaco"
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["createTime"],
|
||||
table: {
|
||||
sortable: "desc"
|
||||
}
|
||||
},
|
||||
{
|
||||
test: ["updateTime"],
|
||||
table: {
|
||||
sortable: "custom"
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -1,12 +0,0 @@
|
||||
import fs from "fs";
|
||||
|
||||
export function getModules() {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const dirs = fs.readdirSync("./src/modules");
|
||||
resolve(dirs.filter((e) => !e.includes(".")));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import { readFileSync, readdirSync } from "fs";
|
||||
import { extname } from "path";
|
||||
|
||||
function findFiles(dir: string): string[] {
|
||||
const res: string[] = [];
|
||||
const dirs = readdirSync(dir, {
|
||||
withFileTypes: true
|
||||
});
|
||||
for (const d of dirs) {
|
||||
if (d.isDirectory()) {
|
||||
res.push(...findFiles(dir + d.name + "/"));
|
||||
} else {
|
||||
if (extname(d.name) == ".svg") {
|
||||
const svg = readFileSync(dir + d.name)
|
||||
.toString()
|
||||
.replace(/(\r)|(\n)/g, "")
|
||||
.replace(/<svg([^>+].*?)>/, (_: any, $2: any) => {
|
||||
let width = 0;
|
||||
let height = 0;
|
||||
let content = $2.replace(
|
||||
/(width|height)="([^>+].*?)"/g,
|
||||
(_: any, s2: any, s3: any) => {
|
||||
if (s2 === "width") {
|
||||
width = s3;
|
||||
} else if (s2 === "height") {
|
||||
height = s3;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
);
|
||||
if (!/(viewBox="[^>+].*?")/g.test($2)) {
|
||||
content += `viewBox="0 0 ${width} ${height}"`;
|
||||
}
|
||||
return `<symbol id="icon-${d.name.replace(".svg", "")}" ${content}>`;
|
||||
})
|
||||
.replace("</svg>", "</symbol>");
|
||||
res.push(svg);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
export function createSvg(html: string) {
|
||||
const res = findFiles("./src/modules/");
|
||||
|
||||
return html.replace(
|
||||
"<body>",
|
||||
`<body>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">
|
||||
${res.join("")}
|
||||
</svg>`
|
||||
);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import { parse, compileScript } from "@vue/compiler-sfc";
|
||||
import magicString from "magic-string";
|
||||
|
||||
export function createTag(code: string, id: string) {
|
||||
if (/\.vue$/.test(id)) {
|
||||
let s: any;
|
||||
const str = () => s || (s = new magicString(code));
|
||||
const { descriptor } = parse(code);
|
||||
|
||||
if (!descriptor.script && descriptor.scriptSetup) {
|
||||
const res = compileScript(descriptor, { id });
|
||||
const { name, lang }: any = res.attrs;
|
||||
|
||||
str().appendLeft(
|
||||
0,
|
||||
`<script lang="${lang}">
|
||||
import { defineComponent } from 'vue'
|
||||
export default defineComponent({
|
||||
name: "${name}"
|
||||
})
|
||||
<\/script>`
|
||||
);
|
||||
|
||||
return {
|
||||
map: str().generateMap(),
|
||||
code: str().toString()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
import fs from "fs";
|
||||
import { join, sep } from "path";
|
||||
|
||||
// 首字母大写
|
||||
export function firstUpperCase(value: string): string {
|
||||
return value.replace(/\b(\w)(\w*)/g, function ($0, $1, $2) {
|
||||
return $1.toUpperCase() + $2;
|
||||
});
|
||||
}
|
||||
|
||||
// 横杠转驼峰
|
||||
export function toCamel(str: string): string {
|
||||
return str.replace(/([^-])(?:-+([^-]))/g, function ($0, $1, $2) {
|
||||
return $1 + $2.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
// 创建目录
|
||||
export function createDir(path: string) {
|
||||
if (!fs.existsSync(path)) fs.mkdirSync(path);
|
||||
}
|
||||
|
||||
// 读取文件
|
||||
export function readFile(name: string) {
|
||||
try {
|
||||
return fs.readFileSync(name, "utf8");
|
||||
} catch (e) {}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
// 解析body
|
||||
export function parseJson(req: any): Promise<any> {
|
||||
return new Promise((resolve) => {
|
||||
let d = "";
|
||||
req.on("data", function (chunk: Buffer) {
|
||||
d += chunk;
|
||||
});
|
||||
req.on("end", function () {
|
||||
try {
|
||||
resolve(JSON.parse(d));
|
||||
} catch {
|
||||
resolve({});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 深度创建目录
|
||||
export function mkdirs(path: string) {
|
||||
const arr = path.split(sep);
|
||||
let p = "";
|
||||
|
||||
arr.forEach((e) => {
|
||||
try {
|
||||
fs.statSync(join(p, e));
|
||||
} catch (err) {
|
||||
try {
|
||||
fs.mkdirSync(join(p, e));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
p = join(p, e);
|
||||
});
|
||||
|
||||
return p;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package frontend
|
||||
@@ -1,3 +0,0 @@
|
||||
module github.com/cool-team-official/cool-admin-go/frontend
|
||||
|
||||
go 1.18
|
||||
@@ -1,163 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="referer" content="never" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0"
|
||||
/>
|
||||
<title></title>
|
||||
<link rel="icon" href="favicon.ico" />
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
|
||||
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
|
||||
}
|
||||
|
||||
.preload__wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
letter-spacing: 1px;
|
||||
background-color: #2f3447;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.preload__container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
user-select: none;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.preload__name {
|
||||
font-size: 30px;
|
||||
color: #fff;
|
||||
letter-spacing: 5px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.preload__title {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
margin: 30px 0 20px 0;
|
||||
}
|
||||
|
||||
.preload__sub-title {
|
||||
color: #ababab;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.preload__footer {
|
||||
text-align: center;
|
||||
padding: 10px 0 20px 0;
|
||||
}
|
||||
|
||||
.preload__footer a {
|
||||
font-size: 12px;
|
||||
color: #ababab;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.preload__loading {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
border-radius: 30px;
|
||||
border: 7px solid currentColor;
|
||||
border-bottom-color: #2f3447 !important;
|
||||
position: relative;
|
||||
animation: r 1s infinite cubic-bezier(0.17, 0.67, 0.83, 0.67),
|
||||
bc 2s infinite ease-in;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
@keyframes r {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.preload__loading::after,
|
||||
.preload__loading::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
height: 7px;
|
||||
width: 7px;
|
||||
border-radius: 10px;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
.preload__loading::after {
|
||||
left: -1px;
|
||||
}
|
||||
|
||||
.preload__loading::before {
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
@keyframes bc {
|
||||
0% {
|
||||
color: #689cc5;
|
||||
}
|
||||
|
||||
25% {
|
||||
color: #b3b7e2;
|
||||
}
|
||||
|
||||
50% {
|
||||
color: #93dbe9;
|
||||
}
|
||||
|
||||
75% {
|
||||
color: #abbd81;
|
||||
}
|
||||
|
||||
100% {
|
||||
color: #689cc5;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="preload__wrap" id="Loading">
|
||||
<div class="preload__container">
|
||||
<p class="preload__name">COOL-ADMIN</p>
|
||||
<div class="preload__loading"></div>
|
||||
<p class="preload__title">正在加载资源...</p>
|
||||
<p class="preload__sub-title">初次加载资源可能需要较多时间 请耐心等待</p>
|
||||
</div>
|
||||
|
||||
<div class="preload__footer">
|
||||
<a href="https://cool-js.com/" target="_blank"> https://cool-js.com </a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,123 +0,0 @@
|
||||
user nginx;
|
||||
worker_processes 1;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
access_log /var/log/nginx/access.log main;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
upstream backend {
|
||||
server midway:8001;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
location / {
|
||||
root /app;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
location /api/
|
||||
{
|
||||
proxy_pass http://backend/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header REMOTE-HOST $remote_addr;
|
||||
|
||||
#缓存相关配置
|
||||
#proxy_cache cache_one;
|
||||
#proxy_cache_key $host$request_uri$is_args$args;
|
||||
#proxy_cache_valid 200 304 301 302 1h;
|
||||
|
||||
#持久化连接相关配置
|
||||
proxy_connect_timeout 3000s;
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 3000s;
|
||||
#proxy_http_version 1.1;
|
||||
#proxy_set_header Upgrade $http_upgrade;
|
||||
#proxy_set_header Connection "upgrade";
|
||||
|
||||
add_header X-Cache $upstream_cache_status;
|
||||
|
||||
#expires 12h;
|
||||
}
|
||||
# location /im {
|
||||
# proxy_pass http://backend/im;
|
||||
# proxy_connect_timeout 3600s; #配置点1
|
||||
# proxy_read_timeout 3600s; #配置点2,如果没效,可以考虑这个时间配置长一点
|
||||
# proxy_send_timeout 3600s; #配置点3
|
||||
# proxy_set_header Host $host;
|
||||
# proxy_set_header X-Real-IP $remote_addr;
|
||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
# proxy_set_header REMOTE-HOST $remote_addr;
|
||||
# #proxy_bind $remote_addr transparent;
|
||||
# proxy_http_version 1.1;
|
||||
# proxy_set_header Upgrade $http_upgrade;
|
||||
# proxy_set_header Connection "upgrade";
|
||||
# # rewrite /socket/(.*) /$1 break;
|
||||
# proxy_redirect off;
|
||||
|
||||
# }
|
||||
|
||||
# location /socket {
|
||||
# proxy_pass http://backend/socket;
|
||||
# proxy_connect_timeout 3600s; #配置点1
|
||||
# proxy_read_timeout 3600s; #配置点2,如果没效,可以考虑这个时间配置长一点
|
||||
# proxy_send_timeout 3600s; #配置点3
|
||||
# proxy_set_header Host $host;
|
||||
# proxy_set_header X-Real-IP $remote_addr;
|
||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
# proxy_set_header REMOTE-HOST $remote_addr;
|
||||
# #proxy_bind $remote_addr transparent;
|
||||
# proxy_http_version 1.1;
|
||||
# proxy_set_header Upgrade $http_upgrade;
|
||||
# proxy_set_header Connection "upgrade";
|
||||
# rewrite /socket/(.*) /$1 break;
|
||||
# proxy_redirect off;
|
||||
|
||||
# }
|
||||
|
||||
|
||||
location /adminer/
|
||||
{
|
||||
proxy_pass http://adminer:8080/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header REMOTE-HOST $remote_addr;
|
||||
|
||||
#缓存相关配置
|
||||
#proxy_cache cache_one;
|
||||
#proxy_cache_key $host$request_uri$is_args$args;
|
||||
#proxy_cache_valid 200 304 301 302 1h;
|
||||
|
||||
#持久化连接相关配置
|
||||
proxy_connect_timeout 3000s;
|
||||
proxy_read_timeout 86400s;
|
||||
proxy_send_timeout 3000s;
|
||||
#proxy_http_version 1.1;
|
||||
#proxy_set_header Upgrade $http_upgrade;
|
||||
#proxy_set_header Connection "upgrade";
|
||||
|
||||
add_header X-Cache $upstream_cache_status;
|
||||
|
||||
#expires 12h;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
{
|
||||
"name": "front-next",
|
||||
"version": "5.12.3",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
|
||||
"lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cool-vue/crud": "^6.0.3",
|
||||
"@element-plus/icons-vue": "^2.0.10",
|
||||
"@vueuse/core": "^9.1.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"axios": "^0.27.2",
|
||||
"core-js": "^3.23.5",
|
||||
"echarts": "^5.3.3",
|
||||
"element-plus": "^2.2.28",
|
||||
"file-saver": "^2.0.5",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.0",
|
||||
"mockjs": "^1.1.0",
|
||||
"monaco-editor": "^0.34.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.28",
|
||||
"quill": "^1.3.7",
|
||||
"socket.io-client": "^4.5.1",
|
||||
"store": "^2.0.12",
|
||||
"vue": "^3.2.45",
|
||||
"vue-echarts": "^6.2.3",
|
||||
"vue-router": "^4.1.6",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/mockjs": "^1.0.6",
|
||||
"@types/node": "^18.0.6",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/quill": "^2.0.10",
|
||||
"@types/store": "^2.0.2",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.6",
|
||||
"@typescript-eslint/parser": "^5.30.6",
|
||||
"@vitejs/plugin-vue": "^3.0.1",
|
||||
"@vitejs/plugin-vue-jsx": "^2.0.0",
|
||||
"@vue/cli-plugin-babel": "^5.0.8",
|
||||
"@vue/cli-plugin-typescript": "^5.0.8",
|
||||
"@vue/compiler-sfc": "^3.2.37",
|
||||
"@vue/composition-api": "^1.7.0",
|
||||
"eslint": "^8.20.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-vue": "^9.2.0",
|
||||
"lodash": "^4.17.21",
|
||||
"magic-string": "^0.26.2",
|
||||
"prettier": "^2.7.1",
|
||||
"rollup-plugin-visualizer": "^5.9.0",
|
||||
"sass": "^1.53.0",
|
||||
"sass-loader": "^13.0.2",
|
||||
"typescript": "^4.7.4",
|
||||
"vite": "^4.0.3",
|
||||
"vite-plugin-compression": "^0.5.1"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 66 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,10 +0,0 @@
|
||||
<template>
|
||||
<el-config-provider :locale="zhCn">
|
||||
<router-view />
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElConfigProvider } from "element-plus";
|
||||
import zhCn from "element-plus/lib/locale/lang/zh-cn";
|
||||
</script>
|
||||
@@ -1,204 +0,0 @@
|
||||
import { isDev, config } from "../config";
|
||||
import { BaseService, service } from "../service";
|
||||
import { Data, toCamel } from "../utils";
|
||||
import { isArray, isEmpty } from "lodash-es";
|
||||
|
||||
// 获取标签名
|
||||
function getNames(v: any) {
|
||||
return [...Object.getOwnPropertyNames(v.constructor.prototype), ...Object.keys(v)].filter(
|
||||
(e) => !["namespace", "constructor", "request", "permission"].includes(e)
|
||||
);
|
||||
}
|
||||
|
||||
// 标签名
|
||||
const names = getNames(new BaseService());
|
||||
|
||||
// 创建
|
||||
export async function createEps() {
|
||||
// 创建描述文件
|
||||
function createDts(list: any[]) {
|
||||
if (!isDev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function deep(v: any) {
|
||||
for (const i in v) {
|
||||
if (v[i].namespace) {
|
||||
v[i].namespace = v[i].namespace;
|
||||
|
||||
// 模块
|
||||
const item: any = list.find((e: any) => e.prefix.includes(v[i].namespace));
|
||||
|
||||
// 接口
|
||||
const api: any[] = item ? item.api : [];
|
||||
|
||||
// 获取方法集合
|
||||
[...names, ...getNames(v[i])].forEach((e) => {
|
||||
if (!api.find((a) => a.path.includes(e))) {
|
||||
api.push({
|
||||
path: `/${e}`
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (item) {
|
||||
item.api = api;
|
||||
} else {
|
||||
list.push({
|
||||
prefix: `/${v[i].namespace}`,
|
||||
api
|
||||
});
|
||||
}
|
||||
} else {
|
||||
deep(v[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deep(service);
|
||||
|
||||
// 本地服务
|
||||
return service.request({
|
||||
url: "/__cool_eps",
|
||||
method: "POST",
|
||||
proxy: false,
|
||||
data: {
|
||||
service,
|
||||
list
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 设置
|
||||
async function set(d?: any) {
|
||||
const list: any[] = [];
|
||||
|
||||
if (isArray(d)) {
|
||||
d = { d };
|
||||
}
|
||||
|
||||
for (const i in d) {
|
||||
if (isArray(d[i])) {
|
||||
d[i].forEach((e: any) => {
|
||||
// 分隔路径
|
||||
const arr = e.prefix
|
||||
.replace(/\//, "")
|
||||
.replace("admin", "")
|
||||
.split("/")
|
||||
.filter(Boolean)
|
||||
.map(toCamel);
|
||||
|
||||
// 遍历
|
||||
function deep(d: any, i: number) {
|
||||
const k = arr[i];
|
||||
|
||||
if (k) {
|
||||
// 是否最后一个
|
||||
if (arr[i + 1]) {
|
||||
if (!d[k]) {
|
||||
d[k] = {};
|
||||
}
|
||||
|
||||
deep(d[k], i + 1);
|
||||
} else {
|
||||
// 本地不存在则创建实例
|
||||
if (!d[k]) {
|
||||
d[k] = new BaseService({
|
||||
namespace: e.prefix.substr(1, e.prefix.length - 1)
|
||||
});
|
||||
}
|
||||
|
||||
// 创建方法
|
||||
e.api.forEach((a: any) => {
|
||||
// 方法名
|
||||
const n = a.path.replace("/", "");
|
||||
|
||||
// 过滤
|
||||
if (!names.includes(n)) {
|
||||
// 本地不存在则创建
|
||||
if (!d[k][n]) {
|
||||
if (n && !/[-:]/g.test(n)) {
|
||||
d[k][n] = function (data: any) {
|
||||
return this.request({
|
||||
url: a.path,
|
||||
method: a.method,
|
||||
[a.method.toLocaleLowerCase() == "post"
|
||||
? "data"
|
||||
: "params"]: data
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 创建权限
|
||||
if (!d[k].permission) {
|
||||
d[k].permission = {};
|
||||
|
||||
const ks = Array.from(new Set([...names, ...getNames(d[k])]));
|
||||
|
||||
ks.forEach((e) => {
|
||||
d[k].permission[e] = `${d[k].namespace.replace(
|
||||
"admin/",
|
||||
""
|
||||
)}/${e}`.replace(/\//g, ":");
|
||||
});
|
||||
}
|
||||
|
||||
list.push(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deep(service, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存数据
|
||||
Data.set("service", service);
|
||||
|
||||
createDts(list);
|
||||
}
|
||||
|
||||
// 获取
|
||||
async function getEps() {
|
||||
try {
|
||||
// 本地数据
|
||||
let list = JSON.parse(__EPS__ || "[]").map(([prefix, name, api]: any[]) => {
|
||||
return {
|
||||
prefix,
|
||||
name,
|
||||
api: api.map(([path, method]: string[]) => {
|
||||
return {
|
||||
method,
|
||||
path
|
||||
};
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
// 接口数据
|
||||
if (isDev && config.test.eps) {
|
||||
await service
|
||||
.request({
|
||||
url: "/admin/base/open/eps"
|
||||
})
|
||||
.then((res) => {
|
||||
if (!isEmpty(res)) {
|
||||
list = res;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (list) {
|
||||
set(list);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("[Eps] 获取失败!", err);
|
||||
}
|
||||
}
|
||||
|
||||
await getEps();
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import { createPinia } from "pinia";
|
||||
import mitt from "mitt";
|
||||
import VueECharts from "vue-echarts";
|
||||
import { App } from "vue";
|
||||
import { createModule } from "./module";
|
||||
import { createEps } from "./eps";
|
||||
import { router } from "../router";
|
||||
import ElementPlus from "element-plus";
|
||||
import "element-plus/theme-chalk/src/index.scss";
|
||||
import { Loading } from "../utils";
|
||||
|
||||
export async function bootstrap(app: App) {
|
||||
// pinia
|
||||
app.use(createPinia());
|
||||
|
||||
// element-plus
|
||||
app.use(ElementPlus);
|
||||
|
||||
// mitt
|
||||
app.provide("mitt", mitt());
|
||||
|
||||
// charts
|
||||
app.component("v-chart", VueECharts);
|
||||
|
||||
// 路由
|
||||
app.use(router);
|
||||
|
||||
// 模块
|
||||
const { eventLoop } = createModule(app);
|
||||
|
||||
// eps
|
||||
await createEps();
|
||||
|
||||
// 加载
|
||||
Loading.set([eventLoop()]);
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import { App } from "vue";
|
||||
import { isFunction, orderBy } from "lodash-es";
|
||||
import { Data, deepMerge, filename, mergeService } from "../utils";
|
||||
import { service } from "../service";
|
||||
import { module } from "../module";
|
||||
|
||||
// 扫描文件
|
||||
const files: any = import.meta.glob("/src/modules/*/{config.ts,service/**,directives/**}", {
|
||||
eager: true
|
||||
});
|
||||
|
||||
// 模块列表
|
||||
module.list = Data.get("modules", []);
|
||||
|
||||
// 解析
|
||||
for (const i in files) {
|
||||
// 分割
|
||||
const [, , , name, action] = i.split("/");
|
||||
|
||||
// 文件名
|
||||
const fname = filename(i);
|
||||
|
||||
// 文件内容
|
||||
const v = files[i]?.default;
|
||||
|
||||
// 模块是否存在
|
||||
const m = module.get(name);
|
||||
|
||||
// 数据
|
||||
const d = m || {
|
||||
name,
|
||||
value: null,
|
||||
services: [],
|
||||
directives: []
|
||||
};
|
||||
|
||||
switch (action) {
|
||||
// 配置参数
|
||||
case "config.ts":
|
||||
d.value = v;
|
||||
break;
|
||||
|
||||
// 请求服务
|
||||
case "service":
|
||||
const s = new v();
|
||||
|
||||
if (s) {
|
||||
d.services?.push({
|
||||
path: s.namespace,
|
||||
value: s
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
// 指令
|
||||
case "directives":
|
||||
d.directives?.push({ name: fname, value: v });
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m) {
|
||||
module.add(d);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建
|
||||
export function createModule(app: App) {
|
||||
// 模块加载
|
||||
const list = orderBy(module.list, "order").map((e) => {
|
||||
const d = isFunction(e.value) ? e.value(app) : e.value;
|
||||
|
||||
if (d) {
|
||||
Object.assign(e, d);
|
||||
|
||||
// 注册组件
|
||||
e.components?.forEach(async (c: any) => {
|
||||
const v = await (isFunction(c) ? c() : c);
|
||||
const n = v.default || v;
|
||||
app.component(n.name, n);
|
||||
});
|
||||
|
||||
// 注册指令
|
||||
e.directives?.forEach((v) => {
|
||||
app.directive(v.name, v.value);
|
||||
});
|
||||
|
||||
// 安装事件
|
||||
if (d.install) {
|
||||
d.install(app, d.options);
|
||||
}
|
||||
}
|
||||
|
||||
// 合并
|
||||
deepMerge(service, mergeService(e.services || []));
|
||||
|
||||
return e;
|
||||
});
|
||||
|
||||
return {
|
||||
// 事件加载
|
||||
async eventLoop() {
|
||||
const events = {};
|
||||
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (list[i].onLoad) {
|
||||
Object.assign(events, await list[i].onLoad(events));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { getUrlParam, storage } from "../utils";
|
||||
import { proxy } from "./proxy";
|
||||
|
||||
export default {
|
||||
// 根地址
|
||||
host: proxy["/dev"].target,
|
||||
|
||||
// 请求地址
|
||||
get baseUrl() {
|
||||
let proxy = getUrlParam("proxy");
|
||||
|
||||
if (proxy) {
|
||||
storage.set("proxy", proxy);
|
||||
} else {
|
||||
proxy = storage.get("proxy") || "dev";
|
||||
}
|
||||
|
||||
return `/${proxy}`;
|
||||
}
|
||||
};
|
||||
@@ -1,54 +0,0 @@
|
||||
import dev from "./dev";
|
||||
import prod from "./prod";
|
||||
|
||||
// 是否开发模式
|
||||
export const isDev = import.meta.env.MODE === "development";
|
||||
|
||||
// 配置
|
||||
export const config = {
|
||||
// 项目信息
|
||||
app: {
|
||||
name: "COOL-ADMIN",
|
||||
|
||||
// 菜单
|
||||
menu: {
|
||||
// 是否分组显示
|
||||
isGroup: false,
|
||||
// 自定义菜单列表
|
||||
list: []
|
||||
},
|
||||
|
||||
// 路由
|
||||
router: {
|
||||
// 模式
|
||||
mode: "hash",
|
||||
// 转场动画
|
||||
transition: "slide",
|
||||
// 首页组件
|
||||
home: () => import("/$/demo/views/home/index.vue")
|
||||
},
|
||||
|
||||
// 字体图标库
|
||||
iconfont: []
|
||||
},
|
||||
|
||||
// 忽略规则
|
||||
ignore: {
|
||||
// 不显示请求进度条
|
||||
NProgress: ["/base/comm/upload", "/base/comm/uploadMode"],
|
||||
// 页面不需要登录验证
|
||||
token: ["/login", "/401", "/403", "/404", "/500", "/502"]
|
||||
},
|
||||
|
||||
// 调试
|
||||
test: {
|
||||
token: "",
|
||||
mock: false,
|
||||
eps: true
|
||||
},
|
||||
|
||||
// 当前环境
|
||||
...(isDev ? dev : prod)
|
||||
};
|
||||
|
||||
export * from "./proxy";
|
||||
@@ -1,9 +0,0 @@
|
||||
import { proxy } from "./proxy";
|
||||
|
||||
export default {
|
||||
// 根地址
|
||||
host: proxy["/prod"].target,
|
||||
|
||||
// 请求地址
|
||||
baseUrl: ""
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
export const proxy = {
|
||||
"/dev": {
|
||||
target: "http://127.0.0.1:8001",
|
||||
changeOrigin: true,
|
||||
rewrite: (path: string) => path.replace(/^\/dev/, "")
|
||||
},
|
||||
|
||||
"/prod": {
|
||||
target: "https://show.cool-admin.com",
|
||||
changeOrigin: true,
|
||||
rewrite: (path: string) => path.replace(/^\/prod/, "/api")
|
||||
}
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { useEventListener } from "@vueuse/core";
|
||||
import { reactive, watch } from "vue";
|
||||
import { getBrowser } from "../utils";
|
||||
|
||||
const browser = reactive(getBrowser());
|
||||
const events: (() => void)[] = [];
|
||||
|
||||
watch(
|
||||
() => browser.screen,
|
||||
() => {
|
||||
events.forEach((ev) => ev());
|
||||
}
|
||||
);
|
||||
|
||||
useEventListener(window, "resize", () => {
|
||||
Object.assign(browser, getBrowser());
|
||||
});
|
||||
|
||||
export function useBrowser() {
|
||||
return {
|
||||
browser,
|
||||
onScreenChange(ev: () => void, immediate = true) {
|
||||
events.push(ev);
|
||||
|
||||
if (immediate) {
|
||||
ev();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
import { Emitter } from "mitt";
|
||||
import { inject, getCurrentInstance, Ref, reactive } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { service } from "../service";
|
||||
import { Data } from "../utils";
|
||||
import { useBrowser } from "./browser";
|
||||
|
||||
export function useService(): Eps.Service {
|
||||
return Data.get("service" || service);
|
||||
}
|
||||
|
||||
export function useRefs() {
|
||||
const refs = reactive<{ [key: string]: any }>({});
|
||||
function setRefs(name: string) {
|
||||
return (el: any) => {
|
||||
refs[name] = el;
|
||||
};
|
||||
}
|
||||
|
||||
return { refs, setRefs };
|
||||
}
|
||||
|
||||
export function useParent(name: string, r: Ref) {
|
||||
const d = getCurrentInstance();
|
||||
|
||||
if (d) {
|
||||
let parent = d.proxy?.$.parent;
|
||||
|
||||
if (parent) {
|
||||
while (parent && parent.type?.name != name && parent.type?.name != "cl-crud") {
|
||||
parent = parent?.parent;
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
if (parent.type.name == name) {
|
||||
r.value = parent.proxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
export function useCool() {
|
||||
return {
|
||||
service: useService(),
|
||||
route: useRoute(),
|
||||
router: useRouter(),
|
||||
mitt: inject("mitt") as Emitter<any>,
|
||||
...useBrowser(),
|
||||
...useRefs()
|
||||
};
|
||||
}
|
||||
|
||||
export * from "./browser";
|
||||
@@ -1,8 +0,0 @@
|
||||
export * from "./service";
|
||||
export * from "./bootstrap";
|
||||
export * from "./hook";
|
||||
export * from "./module";
|
||||
export * from "./router";
|
||||
export * from "./config";
|
||||
export * from "./types/index.d";
|
||||
export { storage } from "./utils";
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user