Repository: liuquanhao/moyu Branch: main Commit: 880e71a214fe Files: 89 Total size: 125.3 KB Directory structure: gitextract_ebjt9uy3/ ├── .github/ │ └── workflows/ │ └── release.yml ├── .gitignore ├── Makefile ├── ManagerDockerfile ├── PageDockerfile ├── README.md ├── manager/ │ ├── backend/ │ │ ├── .gitignore │ │ ├── controller/ │ │ │ ├── page_data_controller/ │ │ │ │ └── page_data_controller.go │ │ │ ├── page_url_controller/ │ │ │ │ └── page_url_controller.go │ │ │ └── user_controller/ │ │ │ └── user_controller.go │ │ ├── database/ │ │ │ └── init.sql │ │ ├── go.mod │ │ ├── go.sum │ │ ├── main.go │ │ ├── middleware/ │ │ │ ├── logged.go │ │ │ └── ws_options.go │ │ └── model/ │ │ ├── db.go │ │ ├── remote_url_model/ │ │ │ └── remote_url_model.go │ │ ├── session.go │ │ └── user_model/ │ │ └── user_model.go │ └── frontend/ │ ├── .babelrc │ ├── .editorconfig │ ├── .gitignore │ ├── .postcssrc.js │ ├── README.md │ ├── build/ │ │ ├── build.js │ │ ├── check-versions.js │ │ ├── utils.js │ │ ├── vue-loader.conf.js │ │ ├── webpack.base.conf.js │ │ ├── webpack.dev.conf.js │ │ └── webpack.prod.conf.js │ ├── config/ │ │ ├── dev.env.js │ │ ├── index.js │ │ └── prod.env.js │ ├── index.html │ ├── package.json │ ├── src/ │ │ ├── App.vue │ │ ├── components/ │ │ │ ├── Login.vue │ │ │ ├── MoyuFooter.vue │ │ │ └── MoyuNav.vue │ │ ├── layouts/ │ │ │ └── PageLayout.vue │ │ ├── main.js │ │ ├── pages/ │ │ │ ├── AddUrlPage.vue │ │ │ ├── LoginPage.vue │ │ │ └── MainPage.vue │ │ └── router/ │ │ └── index.js │ └── static/ │ └── .gitkeep └── page/ ├── backend/ │ ├── .gitignore │ ├── controller/ │ │ └── system.go │ ├── go.mod │ ├── go.sum │ ├── main.go │ ├── middleware/ │ │ └── ws_options.go │ └── service/ │ ├── cpu.go │ ├── disk.go │ ├── host.go │ ├── memory.go │ ├── network.go │ ├── page_data.go │ └── system.go └── frontend/ ├── .babelrc ├── .editorconfig ├── .gitignore ├── .postcssrc.js ├── README.md ├── build/ │ ├── build.js │ ├── check-versions.js │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ └── webpack.prod.conf.js ├── config/ │ ├── dev.env.js │ ├── index.js │ └── prod.env.js ├── index.html ├── package.json ├── src/ │ ├── App.vue │ ├── common/ │ │ └── filters.js │ ├── components/ │ │ ├── Cpu.vue │ │ ├── Disk.vue │ │ ├── Host.vue │ │ └── Mem.vue │ ├── layouts/ │ │ └── Main.vue │ ├── main.js │ ├── pages/ │ │ └── SystemPage.vue │ └── router/ │ └── index.js └── static/ └── .gitkeep ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/release.yml ================================================ name: 编译并发布项目 on: push: tags: - 'v*' jobs: release: name: "编译发布release程序" runs-on: ubuntu-latest strategy: matrix: node-version: [18.x] go-version: [1.19.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: Use Go ${{ matrix.go-version }} uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} - name: Build moyu-manager frontend working-directory: ./manager/frontend run: | npm install npm run build - name: Build moyu-manager release binary working-directory: ./manager/backend run: | go get . GOOS=linux GOARCH=amd64 go build --ldflags="-w -s" -o moyu-manager-linux-amd64 . GOOS=linux GOARCH=arm64 go build --ldflags="-w -s" -o moyu-manager-linux-arm64 . zip -r ../../moyu-manager-linux-amd64.zip moyu-manager-linux-amd64 zip -r ../../moyu-manager-linux-arm64.zip moyu-manager-linux-arm64 zip -r ../../init.sql.zip database/init.sql - name: Build moyu-page frontend working-directory: ./page/frontend run: | npm install npm run build - name: Build moyu-page release binary working-directory: ./page/backend run: | go get . GOOS=linux GOARCH=amd64 go build --ldflags="-w -s" -o moyu-page-linux-amd64 . GOOS=linux GOARCH=arm64 go build --ldflags="-w -s" -o moyu-page-linux-arm64 . zip -r ../../moyu-page-linux-amd64.zip moyu-page-linux-amd64 zip -r ../../moyu-page-linux-arm64.zip moyu-page-linux-arm64 - uses: "marvinpinto/action-automatic-releases@latest" with: repo_token: "${{ secrets.GITHUB_TOKEN }}" prerelease: false files: | *.zip ================================================ FILE: .gitignore ================================================ target/ ================================================ FILE: Makefile ================================================ all: manager page mkdir -p target/bin && mkdir -p target/db && mv manager/backend/moyu-manager target/bin/ && mv page/backend/moyu-page target/bin/ && cat manager/backend/database/init.sql | sqlite3 target/db/moyu_manager.db manager: manager-frontend cd manager/backend && go build -o moyu-manager --ldflags="-w -s" . manager-frontend: cd manager/frontend && npm install && npm run build page: page-frontend cd page/backend && go build -o moyu-page --ldflags="-w -s" . page-frontend: cd page/frontend && npm install && npm run build clean: -rm -rf page/backend/dist page/backend/moyu-page manager/backend/dist manager/backend/moyu-manager target .PHONY: page-frontend page manager-frontend manager clean ================================================ FILE: ManagerDockerfile ================================================ FROM alpine:3.17.1 as builder COPY . . RUN apk add go nodejs npm RUN cd manager/frontend && npm install && npm run build && \ cd ../backend && go get . && go build -o /tmp/moyu-manager --ldflags="-w -s" . FROM alpine:3.17.1 as deploy EXPOSE 8080 RUN mkdir -p /moyu-manager/bin && mkdir -p /moyu-manager/db COPY --from=builder /tmp/moyu-manager /moyu-manager/bin/ ENTRYPOINT /moyu-manager/bin/moyu-manager ================================================ FILE: PageDockerfile ================================================ FROM alpine:3.17.1 as builder COPY . . RUN apk add go nodejs npm RUN cd page/frontend && npm install && npm run build && \ cd ../backend && go get . && go build -o moyu-page --ldflags="-w -s" . FROM alpine:3.17.1 as deploy EXPOSE 8081 COPY --from=builder backend/moyu-page . ENTRYPOINT /moyu-page ================================================ FILE: README.md ================================================ # 墨鱼探针 ## 简介 墨鱼探针为主从模式,主为`墨鱼manager`,从为`墨鱼page`。`墨鱼manager`可获取展示多个墨鱼page的简要状态信息,登录后可点击title进入墨鱼page页面。`墨鱼page`独立部署,可独立使用。 技术栈:go(fiber) + vue2 + element-ui + nes.css。 最终将前端和后端全部编译到单个二进制程序中,分为`moyu-manager`和`moyu-page`2个二进制程序。 ## 展示 ### 墨鱼page  ### 墨鱼manager 未登录主页:  已登录主页:  登录页:  添加墨鱼page页面:  ## 直接使用release文件 ### moyu-page 1. 直接运行 ```bash PORT=8081 ./moyu-page ``` ### moyu-manager 1. 初始化数据库(第一次运行) ```bash cat init.sql | sqlite3 db/moyu_manager.db ``` 2. 目录结构 ```bash ├── bin │ └── moyu-manager └── db └── moyu_manager.db ``` 3. 运行 ```bash PORT=8080 ./bin/moyu-manager ``` 4. 添加墨鱼page。如本项目在线demo:`https://moyu-manager.linux.plus/`,直接复制墨鱼page主页`https://moyu-page.linux.plus/`到`添加墨鱼page页面`即可。在墨鱼manager中,如果已登录,可以点击title访问墨鱼page。 ## 编译使用 ### 依赖: make: ^4.0 nodejs: ^18.0 go: ^1.19.0 sqlite: ^3.0 ### 一键编译 1. 进入项目目录。 ```bash cd moyu ``` 2. 一键编译。 ```bash make ``` 3. 运行墨鱼manager和墨鱼page。 ```bash PORT=8081 target/bin/moyu-page PORT=8080 target/bin/moyu-manager ``` 4. (可选)清理项目,删除编译的墨鱼探针二进制等文件。 ```bash make clean ``` ### 手动编译 #### 编译墨鱼page 1. 进入项目目录。 ```bash cd moyu/page ``` 2. 编译前端资源。 ```bash cd frontend npm run build ``` 3. 编译后端项目。 ```bash cd ../backend go build -o moyu-page --ldflags="-w -s" . ``` #### 编译墨鱼manager 1. 进入项目目录。 ```bash cd moyu/manager ``` 2. 编译前端资源。 ```bash cd frontend npm run build ``` 3. 编译后端项目。 ```bash cd ../backend go build -o moyu-manager --ldflags="-w -s" . ``` ## Docker运行 ### 前提说明 #### 墨鱼page 墨鱼page直接运行docker无法获取宿主机信息,需要添加一些运行参数: 1. 由于需要获取宿主机网络接口流量,所以需要以host方式运行docker。 2. 获取磁盘分区信息需要`/proc/N/mountinfo`,所以需要将宿主机的某个进程的文件挂载到docker中,然后设置`HOST_PROC_MOUNTINFO`并运行项目。 3. 项目`PORT`变量默认`8081`,可自行指定其他端口。 #### 墨鱼manager 1. 墨鱼manager依赖`sqlite3`,需要使用`moyu/manager/backend/database/init.sql`创建和初始化用户表数据。 2. 请使用一下目录格式存放`moyu-manager`程序和数据库,容器挂载时需要注意目录位置,默认编译的项目根目录为`/moyu-manager`。 ```bash root@liuxu:/moyu-manager# tree . ├── bin │ └── moyu-manager └── db └── moyu_manager.db ``` ### 运行容器 #### 墨鱼page 1. 编译page镜像。 ```bash docker build -t moyu-page -f PageDockerfile . ``` 2. 单磁盘挂载情况下运行,其中`--network=host`指定使用宿主机网络,`--mount`挂载`dockerd`的进程`mountinfo`文件到docker中,并设置`HOST_PROC_MOUNTINFO`为挂载的文件路径。 ```bash docker run --network=host -e PORT=8081 --mount type=bind,source="/proc/$(pidof dockerd)/mountinfo",target=/root/mountinfo -e HOST_PROC_MOUNTINFO=/root/mountinfo moyu-page ``` 3. (可选)如果还有其他分区,如我的`/boot/efi`挂载到了独立分区,想获取到这个分区信息,需要把这个目录挂载到docker中。 ```bash docker run --network=host -e PORT=8081 -v /boot/efi:/boot/efi:ro --mount type=bind,source="/proc/$(pidof dockerd)/mountinfo",target=/root/mountinfo -e HOST_PROC_MOUNTINFO=/root/mountinfo moyu-page ``` #### 墨鱼manager 1. 编译manager镜像。 ```bash docker build -t moyu-manager -f ManagerDockerfile . ``` 2. 创建数据库。 ```bash mkdir db cat manager/backend/database/init.sql | sqlite3 db/moyu_manager.db ``` 3. 挂载数据库运行。 ```bash docker run -e PORT=8080 -p 8080:8080 -v ./db:/moyu-manager/db moyu-manager ``` ## FAQ 1. 我使用nginx做反代,设置了`location /moyu{}`该怎么办 答:运行墨鱼page或墨鱼manager时,添加`BASEURL=/moyu`环境变量运行。 2. 运行墨鱼manager,程序报找不到`moyu_manager.db`怎么办 答:确认自己的目录结构是不是如下: ```bash ├── bin │ └── moyu-manager └── db └── moyu_manager.db ``` 然后进入`bin/`目录下运行`moyu-manager` 3. 我想修改账号或者token 答:运行sqlite3,通过sql修改。 ```bash sqlite3 moyu_manager.db sqlite> UPDATE users SET token='token123' WHERE user='user' ``` 4. 我想创建新的账户和token 答:运行sqlite3,通过sql添加。 ```bash sqlite3 moyu_manager.db sqlite> INSERT INTO users(user, token) VALUES('user1', 'token1'); ``` ================================================ FILE: manager/backend/.gitignore ================================================ dist/ moyu-manager ================================================ FILE: manager/backend/controller/page_data_controller/page_data_controller.go ================================================ package page_data_controller import ( "encoding/json" "net/http" "time" "github.com/gofiber/websocket/v2" "github.com/liuquanhao/moyu/model" "github.com/liuquanhao/moyu/model/remote_url_model" ) // define: page/backend/service/page_data.go type PageData struct { Uptime uint64 `json:"uptime"` CPUPercent float64 `json:"cpu_percent"` MemoryPercent float64 `json:"memory_percent"` DiskPercent float64 `json:"disk_percent"` NetSendTotal uint64 `json:"net_send"` NetRecvTotal uint64 `json:"net_recv"` Timestamp int64 `json:"timestamp"` } type PageInfo struct { PageId uint32 `json:"page_id"` PageData *PageData `json:"page_data"` } func getPageData(myClient *http.Client, url string, target interface{}) error { resp, err := http.Get(url + "api/page_data") if err != nil { return err } if resp.StatusCode != 200 { return err } defer resp.Body.Close() return json.NewDecoder(resp.Body).Decode(target) } func loopPullPageData(pageId uint32, url string, ch chan *PageInfo) { var myClient = &http.Client{Timeout: 5 * time.Second} pageData := new(PageData) for { start := time.Now() err := getPageData(myClient, url, pageData) if err != nil { time.Sleep(3 * time.Second) } else { ch <- &PageInfo{ PageId: pageId, PageData: pageData, } } end := time.Now() useTime := end.Sub(start) if useTime < 1*time.Second { time.Sleep(1000*time.Millisecond - useTime) } } } func PushPageData(c *websocket.Conn) { db := model.DBConn var pageUrls []remote_url_model.PageUrl db.Find(&pageUrls) ch := make(chan *PageInfo, len(pageUrls)) defer close(ch) for _, pageUrl := range pageUrls { go loopPullPageData(pageUrl.Id, pageUrl.PageUrl, ch) } for pageInfo := range ch { c.WriteJSON(pageInfo) } } ================================================ FILE: manager/backend/controller/page_url_controller/page_url_controller.go ================================================ package page_url_controller import ( "github.com/gofiber/fiber/v2" "github.com/liuquanhao/moyu/model" "github.com/liuquanhao/moyu/model/remote_url_model" "github.com/go-playground/validator/v10" ) var validate = validator.New() func Add(c *fiber.Ctx) error { db := model.DBConn pageUrl := new(remote_url_model.PageUrl) if err := c.BodyParser(pageUrl); err != nil { return c.Status(fiber.StatusBadRequest).SendString(err.Error()) } if err := validate.Struct(pageUrl); err != nil { return c.Status(fiber.StatusBadRequest).SendString(err.Error()) } db.Create(&pageUrl) return c.JSON(pageUrl) } func Delete(c *fiber.Ctx) error { id := c.Params("id") db := model.DBConn var pageUrl remote_url_model.PageUrl db.Take(&pageUrl, id) if pageUrl.Title == "" { return c.Status(fiber.StatusNotFound).SendString("Not Found") } db.Delete(&pageUrl) return c.SendString("Delete success") } func List(c *fiber.Ctx) error { db := model.DBConn var pageUrls []remote_url_model.PageUrl db.Find(&pageUrls) s, _ := model.SessionStore.Get(c) if !s.Fresh() { return c.JSON(pageUrls) } // unlogin for _, pageUrl := range pageUrls { pageUrl.PageUrl = "" } return c.JSON(pageUrls) } ================================================ FILE: manager/backend/controller/user_controller/user_controller.go ================================================ package user_controller import ( "strconv" "time" "github.com/go-playground/validator/v10" "github.com/gofiber/fiber/v2" "github.com/liuquanhao/moyu/model" "github.com/liuquanhao/moyu/model/user_model" ) var validate = validator.New() func Login(c *fiber.Ctx) error { db := model.DBConn user := new(user_model.User) if err := c.BodyParser(user); err != nil { return c.Status(fiber.StatusBadRequest).SendString(err.Error()) } if err := validate.Struct(user); err != nil { return c.Status(fiber.StatusBadRequest).SendString(err.Error()) } db.Where(&user).Take(&user) if user.Id == 0 { return c.Status(fiber.StatusUnauthorized).SendString("Not Found User") } s, _ := model.SessionStore.Get(c) s.Set("uid", user.Id) s.Set("sid", s.ID()) s.Set("ip", c.Context().RemoteIP().String()) s.Set("login", time.Unix(time.Now().Unix(), 0).UTC().String()) s.Set("ua", string(c.Request().Header.UserAgent())) err := s.Save() if err != nil { return c.Status(fiber.StatusServiceUnavailable).SendString(err.Error()) } cookie := new(fiber.Cookie) cookie.Name = "uid" cookie.Value = strconv.FormatUint(uint64(user.Id), 10) cookie.Expires = time.Now().Add(24 * time.Hour) c.Cookie(cookie) c.Status(fiber.StatusNoContent) return nil } func Account(c *fiber.Ctx) error { s, _ := model.SessionStore.Get(c) if s.Fresh() { c.Status(fiber.StatusNotFound) return nil } return c.JSON(fiber.Map{ "sid": s.ID(), "uid": s.Get("uid"), "ip": s.Get("ip"), "login": s.Get("login"), "ua": s.Get("ua"), }) } func Logout(c *fiber.Ctx) error { s, _ := model.SessionStore.Get(c) if err := s.Destroy(); err != nil { return c.Status(fiber.StatusServiceUnavailable).SendString(err.Error()) } c.Status(fiber.StatusNoContent) return nil } ================================================ FILE: manager/backend/database/init.sql ================================================ CREATE TABLE IF NOT EXISTS sessions ( k VARCHAR(64) PRIMARY KEY NOT NULL DEFAULT '', v BLOB NOT NULL, e BIGINT NOT NULL DEFAULT '0', u TEXT ); CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, user VARCHAR(16) UNIQUE NOT NULL, token VARCHAR(32) NOT NULL ); CREATE TABLE IF NOT EXISTS page_urls ( id INTEGER PRIMARY KEY AUTOINCREMENT, title VARCHAR(32) NOT NULL, page_url VARCHAR(512) NOT NULL ); CREATE UNIQUE INDEX user_uiq on users (user); INSERT INTO users(user, token) VALUES ("user", "token123"); ================================================ FILE: manager/backend/go.mod ================================================ module github.com/liuquanhao/moyu go 1.19 require ( github.com/go-playground/validator/v10 v10.11.2 github.com/gofiber/fiber/v2 v2.42.0 github.com/gofiber/storage/sqlite3 v0.0.0-20230206084615-41a84b36b572 github.com/gofiber/websocket/v2 v2.1.4 gorm.io/driver/sqlite v1.4.4 gorm.io/gorm v1.24.5 ) require ( github.com/andybalholm/brotli v1.0.4 // indirect github.com/fasthttp/websocket v1.5.1 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/google/uuid v1.3.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/klauspost/compress v1.15.9 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/philhofer/fwd v1.1.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect github.com/tinylib/msgp v1.1.6 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.44.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect golang.org/x/crypto v0.5.0 // indirect golang.org/x/sys v0.4.0 // indirect golang.org/x/text v0.6.0 // indirect ) ================================================ FILE: manager/backend/go.sum ================================================ github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/fasthttp/websocket v1.5.1 h1:iZsMv5OtZ1E52hhCnlOm/feLCrPhutlrZgvEGcZa1FM= github.com/fasthttp/websocket v1.5.1/go.mod h1:s+gJkEn38QXLkNfOe/n75Yb8we+VEho1vYqeUYheomw= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= github.com/gofiber/fiber/v2 v2.42.0 h1:Fnp7ybWvS+sjNQsFvkhf4G8OhXswvB6Vee8hM/LyS+8= github.com/gofiber/fiber/v2 v2.42.0/go.mod h1:3+SGNjqMh5VQH5Vz2Wdi43zTIV16ktlFd3x3R6O1Zlc= github.com/gofiber/storage/sqlite3 v0.0.0-20230206084615-41a84b36b572 h1:FHnNfM4q4Z+WtuYoQ5vz2z+JWmsY/sV49IS1nekEko4= github.com/gofiber/storage/sqlite3 v0.0.0-20230206084615-41a84b36b572/go.mod h1:TXYMAnzU/KAYE7RrM5tH9FrFC9Sr0CgMySWpMedmJR8= github.com/gofiber/utils v1.0.1 h1:knct4cXwBipWQqFrOy1Pv6UcgPM+EXo9jDgc66V1Qio= github.com/gofiber/utils v1.0.1/go.mod h1:pacRFtghAE3UoknMOUiXh2Io/nLWSUHtQCi/3QASsOc= github.com/gofiber/websocket/v2 v2.1.4 h1:Ki6L7auleAwgi7iRmtUiWKltlbmtkCJ0COtK1nt8L3g= github.com/gofiber/websocket/v2 v2.1.4/go.mod h1:IC4ZUejlk0kJSaphJ1gjqgKfK9fhw8eoAr3/UdbOzEA= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= 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.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 h1:rmMl4fXJhKMNWl+K+r/fq4FbbKI+Ia2m9hYBLm2h4G4= github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8= github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d h1:Q+gqLBOPkFGHyCJxXMRqtUgUbTjI8/Ze8vu8GGyNFwo= github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.44.0 h1:R+gLUhldIsfg1HokMuQjdQ5bh9nuXHPIfvkYUu9eR5Q= github.com/valyala/fasthttp v1.44.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc= gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.24.5 h1:g6OPREKqqlWq4kh/3MCQbZKImeB9e6Xgc4zD+JgNZGE= gorm.io/gorm v1.24.5/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= ================================================ FILE: manager/backend/main.go ================================================ package main import ( "embed" "io/fs" "log" "net/http" "os" "path/filepath" "time" "github.com/liuquanhao/moyu/controller/page_data_controller" "github.com/liuquanhao/moyu/controller/page_url_controller" "github.com/liuquanhao/moyu/controller/user_controller" "github.com/liuquanhao/moyu/middleware" "github.com/liuquanhao/moyu/model" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/filesystem" "github.com/gofiber/fiber/v2/middleware/session" "github.com/gofiber/storage/sqlite3" "github.com/gofiber/websocket/v2" "gorm.io/driver/sqlite" "gorm.io/gorm" ) func getCurrentPwd() string { exePath, _ := os.Executable() return filepath.Dir(exePath) } func initDatabase() { var err error model.DBConn, err = gorm.Open(sqlite.Open(getCurrentPwd() + "/../db/moyu_manager.db")) if err != nil { log.Fatal("failed to connect database: {}", err) } } func initSession() { storage := sqlite3.New(sqlite3.Config{ Database: getCurrentPwd() + "/../db/moyu_manager.db", Table: "sessions", Reset: false, GCInterval: 10 * time.Second, MaxOpenConns: 100, MaxIdleConns: 100, ConnMaxLifetime: 1 * time.Second, }) model.SessionStore = session.New(session.Config{ Storage: storage, }) } func setupRoutes(app *fiber.App) { app.Use(cors.New(cors.Config{ AllowOrigins: "*", AllowCredentials: true, })) base := app.Group(os.Getenv("BASEURL")) ws := base.Group("/ws") ws.Use("/*", middleware.UpgradeOptions) ws.Get("/page_data", websocket.New(page_data_controller.PushPageData)) api := base.Group("/api") api.Post("/login", user_controller.Login) api.Get("/page_url", page_url_controller.List) logged := app.Group("/api", middleware.Logged) logged.Post("/logout", user_controller.Logout) logged.Get("/account", user_controller.Account) logged.Post("/page_url", page_url_controller.Add) logged.Delete("/page_url/:id", page_url_controller.Delete) stripped, err := fs.Sub(frontend, "dist") if err != nil { log.Fatal(err) } base.Use("/", filesystem.New(filesystem.Config{ Root: http.FS(stripped), Browse: true, })) } //go:embed dist var frontend embed.FS func main() { app := fiber.New() initDatabase() initSession() setupRoutes(app) host := os.Getenv("HOST") port := os.Getenv("PORT") log.Println(host + ":" + port) log.Fatal(app.Listen(host + ":" + port)) } ================================================ FILE: manager/backend/middleware/logged.go ================================================ package middleware import ( "github.com/gofiber/fiber/v2" "github.com/liuquanhao/moyu/model" ) func Logged(c *fiber.Ctx) error { s, _ := model.SessionStore.Get(c) if s.Fresh() { c.Status(fiber.StatusUnauthorized) return nil } return c.Next() } ================================================ FILE: manager/backend/middleware/ws_options.go ================================================ package middleware import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/websocket/v2" ) func UpgradeOptions(c *fiber.Ctx) error { if websocket.IsWebSocketUpgrade(c) { return c.Next() } return fiber.ErrUpgradeRequired } ================================================ FILE: manager/backend/model/db.go ================================================ package model import "gorm.io/gorm" var ( DBConn *gorm.DB ) ================================================ FILE: manager/backend/model/remote_url_model/remote_url_model.go ================================================ package remote_url_model type PageUrl struct { Id uint32 `json:"id"` Title string `json:"title" validate:"required,max=32"` PageUrl string `json:"page_url" validate:"required,max=512"` } ================================================ FILE: manager/backend/model/session.go ================================================ package model import "github.com/gofiber/fiber/v2/middleware/session" var ( SessionStore *session.Store ) ================================================ FILE: manager/backend/model/user_model/user_model.go ================================================ package user_model type User struct { Id uint32 `json:"id"` User string `json:"user" validate:"required,max=16"` Token string `json:"token" validate:"required,max=32"` } ================================================ FILE: manager/frontend/.babelrc ================================================ { "presets": [ ["env", { "modules": false, "targets": { "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] } }], "stage-2" ], "plugins": ["transform-vue-jsx", "transform-runtime"] } ================================================ FILE: manager/frontend/.editorconfig ================================================ root = true [*] charset = utf-8 indent_style = space indent_size = 2 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true ================================================ FILE: manager/frontend/.gitignore ================================================ .DS_Store node_modules/ /dist/ npm-debug.log* yarn-debug.log* yarn-error.log* # Editor directories and files .idea .vscode *.suo *.ntvs* *.njsproj *.sln ================================================ FILE: manager/frontend/.postcssrc.js ================================================ // https://github.com/michael-ciniawsky/postcss-load-config module.exports = { "plugins": { "postcss-import": {}, "postcss-url": {}, // to edit target browsers: use "browserslist" field in package.json "autoprefixer": {} } } ================================================ FILE: manager/frontend/README.md ================================================ # frontend > moyu manager ## Build Setup ``` bash # install dependencies npm install # serve with hot reload at localhost:8080 npm run dev # build for production with minification npm run build # build for production and view the bundle analyzer report npm run build --report ``` For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). ================================================ FILE: manager/frontend/build/build.js ================================================ 'use strict' require('./check-versions')() process.env.NODE_ENV = 'production' const ora = require('ora') const rm = require('rimraf') const path = require('path') const chalk = require('chalk') const webpack = require('webpack') const config = require('../config') const webpackConfig = require('./webpack.prod.conf') const spinner = ora('building for production...') spinner.start() rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { if (err) throw err webpack(webpackConfig, (err, stats) => { spinner.stop() if (err) throw err process.stdout.write(stats.toString({ colors: true, modules: false, children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. chunks: false, chunkModules: false }) + '\n\n') if (stats.hasErrors()) { console.log(chalk.red(' Build failed with errors.\n')) process.exit(1) } console.log(chalk.cyan(' Build complete.\n')) console.log(chalk.yellow( ' Tip: built files are meant to be served over an HTTP server.\n' + ' Opening index.html over file:// won\'t work.\n' )) }) }) ================================================ FILE: manager/frontend/build/check-versions.js ================================================ 'use strict' const chalk = require('chalk') const semver = require('semver') const packageConfig = require('../package.json') const shell = require('shelljs') function exec (cmd) { return require('child_process').execSync(cmd).toString().trim() } const versionRequirements = [ { name: 'node', currentVersion: semver.clean(process.version), versionRequirement: packageConfig.engines.node } ] if (shell.which('npm')) { versionRequirements.push({ name: 'npm', currentVersion: exec('npm --version'), versionRequirement: packageConfig.engines.npm }) } module.exports = function () { const warnings = [] for (let i = 0; i < versionRequirements.length; i++) { const mod = versionRequirements[i] if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { warnings.push(mod.name + ': ' + chalk.red(mod.currentVersion) + ' should be ' + chalk.green(mod.versionRequirement) ) } } if (warnings.length) { console.log('') console.log(chalk.yellow('To use this template, you must update following to modules:')) console.log() for (let i = 0; i < warnings.length; i++) { const warning = warnings[i] console.log(' ' + warning) } console.log() process.exit(1) } } ================================================ FILE: manager/frontend/build/utils.js ================================================ 'use strict' const path = require('path') const config = require('../config') const ExtractTextPlugin = require('extract-text-webpack-plugin') const packageConfig = require('../package.json') exports.assetsPath = function (_path) { const assetsSubDirectory = process.env.NODE_ENV === 'production' ? config.build.assetsSubDirectory : config.dev.assetsSubDirectory return path.posix.join(assetsSubDirectory, _path) } exports.cssLoaders = function (options) { options = options || {} const cssLoader = { loader: 'css-loader', options: { sourceMap: options.sourceMap } } const postcssLoader = { loader: 'postcss-loader', options: { sourceMap: options.sourceMap } } // generate loader string to be used with extract text plugin function generateLoaders (loader, loaderOptions) { const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] if (loader) { loaders.push({ loader: loader + '-loader', options: Object.assign({}, loaderOptions, { sourceMap: options.sourceMap }) }) } // Extract CSS when that option is specified // (which is the case during production build) if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' }) } else { return ['vue-style-loader'].concat(loaders) } } // https://vue-loader.vuejs.org/en/configurations/extract-css.html return { css: generateLoaders(), postcss: generateLoaders(), less: generateLoaders('less'), sass: generateLoaders('sass', { indentedSyntax: true }), scss: generateLoaders('sass'), stylus: generateLoaders('stylus'), styl: generateLoaders('stylus') } } // Generate loaders for standalone style files (outside of .vue) exports.styleLoaders = function (options) { const output = [] const loaders = exports.cssLoaders(options) for (const extension in loaders) { const loader = loaders[extension] output.push({ test: new RegExp('\\.' + extension + '$'), use: loader }) } return output } exports.createNotifierCallback = () => { const notifier = require('node-notifier') return (severity, errors) => { if (severity !== 'error') return const error = errors[0] const filename = error.file && error.file.split('!').pop() notifier.notify({ title: packageConfig.name, message: severity + ': ' + error.name, subtitle: filename || '', icon: path.join(__dirname, 'logo.png') }) } } ================================================ FILE: manager/frontend/build/vue-loader.conf.js ================================================ 'use strict' const utils = require('./utils') const config = require('../config') const isProduction = process.env.NODE_ENV === 'production' const sourceMapEnabled = isProduction ? config.build.productionSourceMap : config.dev.cssSourceMap module.exports = { loaders: utils.cssLoaders({ sourceMap: sourceMapEnabled, extract: isProduction }), cssSourceMap: sourceMapEnabled, cacheBusting: config.dev.cacheBusting, transformToRequire: { video: ['src', 'poster'], source: 'src', img: 'src', image: 'xlink:href' } } ================================================ FILE: manager/frontend/build/webpack.base.conf.js ================================================ 'use strict' const path = require('path') const utils = require('./utils') const config = require('../config') const vueLoaderConfig = require('./vue-loader.conf') function resolve (dir) { return path.join(__dirname, '..', dir) } module.exports = { context: path.resolve(__dirname, '../'), entry: { app: './src/main.js' }, output: { path: config.build.assetsRoot, filename: '[name].js', publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath }, resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, { test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('img/[name].[hash:7].[ext]') } }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('media/[name].[hash:7].[ext]') } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('fonts/[name].[hash:7].[ext]') } } ] }, node: { // prevent webpack from injecting useless setImmediate polyfill because Vue // source contains it (although only uses it if it's native). setImmediate: false, // prevent webpack from injecting mocks to Node native modules // that does not make sense for the client dgram: 'empty', fs: 'empty', net: 'empty', tls: 'empty', child_process: 'empty' } } ================================================ FILE: manager/frontend/build/webpack.dev.conf.js ================================================ 'use strict' const utils = require('./utils') const webpack = require('webpack') const config = require('../config') const merge = require('webpack-merge') const path = require('path') const baseWebpackConfig = require('./webpack.base.conf') const CopyWebpackPlugin = require('copy-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') const portfinder = require('portfinder') const HOST = process.env.HOST const PORT = process.env.PORT && Number(process.env.PORT) const devWebpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) }, // cheap-module-eval-source-map is faster for development devtool: config.dev.devtool, // these devServer options should be customized in /config/index.js devServer: { clientLogLevel: 'warning', historyApiFallback: { rewrites: [ { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, ], }, hot: true, contentBase: false, // since we use CopyWebpackPlugin. compress: true, host: HOST || config.dev.host, port: PORT || config.dev.port, open: config.dev.autoOpenBrowser, overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false, publicPath: config.dev.assetsPublicPath, proxy: config.dev.proxyTable, quiet: true, // necessary for FriendlyErrorsPlugin watchOptions: { poll: config.dev.poll, } }, plugins: [ new webpack.DefinePlugin({ 'process.env': require('../config/dev.env') }), new webpack.HotModuleReplacementPlugin(), new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. new webpack.NoEmitOnErrorsPlugin(), // https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true }), // copy custom static assets new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static'), to: config.dev.assetsSubDirectory, ignore: ['.*'] } ]) ] }) module.exports = new Promise((resolve, reject) => { portfinder.basePort = process.env.PORT || config.dev.port portfinder.getPort((err, port) => { if (err) { reject(err) } else { // publish the new Port, necessary for e2e tests process.env.PORT = port // add port to devServer config devWebpackConfig.devServer.port = port // Add FriendlyErrorsPlugin devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ compilationSuccessInfo: { messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], }, onErrors: config.dev.notifyOnErrors ? utils.createNotifierCallback() : undefined })) resolve(devWebpackConfig) } }) }) ================================================ FILE: manager/frontend/build/webpack.prod.conf.js ================================================ 'use strict' const path = require('path') const utils = require('./utils') const webpack = require('webpack') const config = require('../config') const merge = require('webpack-merge') const baseWebpackConfig = require('./webpack.base.conf') const CopyWebpackPlugin = require('copy-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') const ExtractTextPlugin = require('extract-text-webpack-plugin') const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const env = require('../config/prod.env') const webpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true, usePostCSS: true }) }, devtool: config.build.productionSourceMap ? config.build.devtool : false, output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') }, plugins: [ // http://vuejs.github.io/vue-loader/en/workflow/production.html new webpack.DefinePlugin({ 'process.env': env }), new UglifyJsPlugin({ uglifyOptions: { compress: { warnings: false } }, sourceMap: config.build.productionSourceMap, parallel: true }), // extract css into its own file new ExtractTextPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css'), // Setting the following option to `false` will not extract CSS from codesplit chunks. // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 allChunks: true, }), // Compress extracted CSS. We are using this plugin so that possible // duplicated CSS from different components can be deduped. new OptimizeCSSPlugin({ cssProcessorOptions: config.build.productionSourceMap ? { safe: true, map: { inline: false } } : { safe: true } }), // generate dist index.html with correct asset hash for caching. // you can customize output by editing /index.html // see https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ filename: config.build.index, template: 'index.html', inject: true, minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference }, // necessary to consistently work with multiple chunks via CommonsChunkPlugin chunksSortMode: 'dependency' }), // keep module.id stable when vendor modules does not change new webpack.HashedModuleIdsPlugin(), // enable scope hoisting new webpack.optimize.ModuleConcatenationPlugin(), // split vendor js into its own file new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks (module) { // any required modules inside node_modules are extracted to vendor return ( module.resource && /\.js$/.test(module.resource) && module.resource.indexOf( path.join(__dirname, '../node_modules') ) === 0 ) } }), // extract webpack runtime and module manifest to its own file in order to // prevent vendor hash from being updated whenever app bundle is updated new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', minChunks: Infinity }), // This instance extracts shared chunks from code splitted chunks and bundles them // in a separate chunk, similar to the vendor chunk // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk new webpack.optimize.CommonsChunkPlugin({ name: 'app', async: 'vendor-async', children: true, minChunks: 3 }), // copy custom static assets new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, ignore: ['.*'] } ]) ] }) if (config.build.productionGzip) { const CompressionWebpackPlugin = require('compression-webpack-plugin') webpackConfig.plugins.push( new CompressionWebpackPlugin({ asset: '[path].gz[query]', algorithm: 'gzip', test: new RegExp( '\\.(' + config.build.productionGzipExtensions.join('|') + ')$' ), threshold: 10240, minRatio: 0.8 }) ) } if (config.build.bundleAnalyzerReport) { const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push(new BundleAnalyzerPlugin()) } module.exports = webpackConfig ================================================ FILE: manager/frontend/config/dev.env.js ================================================ 'use strict' const merge = require('webpack-merge') const prodEnv = require('./prod.env') module.exports = merge(prodEnv, { NODE_ENV: '"development"' }) ================================================ FILE: manager/frontend/config/index.js ================================================ 'use strict' // Template version: 1.3.1 // see http://vuejs-templates.github.io/webpack for documentation. const path = require('path') module.exports = { dev: { // Paths assetsSubDirectory: 'static', assetsPublicPath: './', proxyTable: {}, // Various Dev Server settings host: 'localhost', // can be overwritten by process.env.HOST port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined autoOpenBrowser: false, errorOverlay: true, notifyOnErrors: true, poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- /** * Source Maps */ // https://webpack.js.org/configuration/devtool/#development devtool: 'cheap-module-eval-source-map', // If you have problems debugging vue-files in devtools, // set this to false - it *may* help // https://vue-loader.vuejs.org/en/options.html#cachebusting cacheBusting: true, cssSourceMap: true }, build: { // Template for index.html index: path.resolve(__dirname, '../dist/index.html'), // Paths assetsRoot: path.resolve(__dirname, '../dist'), assetsSubDirectory: 'static', assetsPublicPath: './', /** * Source Maps */ productionSourceMap: true, // https://webpack.js.org/configuration/devtool/#production devtool: '#source-map', // Gzip off by default as many popular static hosts such as // Surge or Netlify already gzip all static assets for you. // Before setting to `true`, make sure to: // npm install --save-dev compression-webpack-plugin productionGzip: false, productionGzipExtensions: ['js', 'css'], // Run the build command with an extra argument to // View the bundle analyzer report after build finishes: // `npm run build --report` // Set to `true` or `false` to always turn it on or off bundleAnalyzerReport: process.env.npm_config_report } } ================================================ FILE: manager/frontend/config/prod.env.js ================================================ 'use strict' module.exports = { NODE_ENV: '"production"' } ================================================ FILE: manager/frontend/index.html ================================================
Login
Add Page Url
Basic System Information
CPU
Memory
Disk
Powered By: liuxu