├── icons
├── icon.icns
├── icon.png
└── icon-256.png
├── preview
└── task.png
├── public
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── favicon.png
│ └── favicon-256.png
├── src
│ ├── assets
│ │ └── style
│ │ │ ├── variables.scss
│ │ │ └── style.scss
│ ├── store
│ │ ├── index.js
│ │ └── module
│ │ │ ├── LorcaToJs.js
│ │ │ ├── lorca.js
│ │ │ └── tasks.js
│ ├── components
│ │ ├── base
│ │ │ ├── SelTip.vue
│ │ │ ├── MapEdit.vue
│ │ │ └── ArrMapEdit.vue
│ │ ├── taskModule
│ │ │ ├── UnderDevelopment.vue
│ │ │ ├── Navigate.vue
│ │ │ ├── CaptureScreenshot.vue
│ │ │ ├── AddReqHeaders.vue
│ │ │ ├── Click.vue
│ │ │ ├── WaitVisible.vue
│ │ │ ├── Pdf.vue
│ │ │ ├── Sleep.vue
│ │ │ ├── SetValue.vue
│ │ │ ├── EmulateViewport.vue
│ │ │ ├── Evaluate.vue
│ │ │ ├── Screenshot.vue
│ │ │ └── AddCookies.vue
│ │ ├── AppBar.vue
│ │ ├── taskPanel
│ │ │ ├── AddTaskPanel.vue
│ │ │ ├── TaskCard.vue
│ │ │ ├── EditTask.vue
│ │ │ ├── EditSubTask.vue
│ │ │ └── Tasks.vue
│ │ └── Container.vue
│ ├── main.js
│ ├── App.vue
│ ├── utils
│ │ ├── common.js
│ │ └── validateRules.js
│ └── config
│ │ └── tasks.js
├── vite.config.js
├── index.html
├── package.json
├── README.md
└── yarn.lock
├── .gitattributes
├── config
└── main.go
├── .gitignore
├── go.mod
├── js
├── eval.go
└── bind.go
├── tasks
├── cookies.go
├── request.go
├── evaluate.go
├── parserRunTask.go
├── pdf.go
├── main.go
├── screenshot.go
└── base.go
├── main.go
├── LICENSE
├── helper
└── dir.go
├── README.md
└── go.sum
/icons/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xusenlin/cdp-ui/HEAD/icons/icon.icns
--------------------------------------------------------------------------------
/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xusenlin/cdp-ui/HEAD/icons/icon.png
--------------------------------------------------------------------------------
/preview/task.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xusenlin/cdp-ui/HEAD/preview/task.png
--------------------------------------------------------------------------------
/icons/icon-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xusenlin/cdp-ui/HEAD/icons/icon-256.png
--------------------------------------------------------------------------------
/public/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | *.local
5 | package-lock.json
--------------------------------------------------------------------------------
/public/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xusenlin/cdp-ui/HEAD/public/public/favicon.ico
--------------------------------------------------------------------------------
/public/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xusenlin/cdp-ui/HEAD/public/public/favicon.png
--------------------------------------------------------------------------------
/public/public/favicon-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xusenlin/cdp-ui/HEAD/public/public/favicon-256.png
--------------------------------------------------------------------------------
/public/src/assets/style/variables.scss:
--------------------------------------------------------------------------------
1 | /* 改变主题色变量 */
2 | $--color-primary: #2196f3;
3 |
4 | $--color-success: #67c23a;
5 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.js linguist-language=GoLang
2 | *.css linguist-language=GoLang
3 | *.html linguist-language=GoLang
4 | *.vue linguist-language=GoLang
5 |
--------------------------------------------------------------------------------
/public/vite.config.js:
--------------------------------------------------------------------------------
1 | import vue from "@vitejs/plugin-vue";
2 |
3 | /**
4 | * @type {import('vite').UserConfig}
5 | */
6 | export default {
7 | plugins: [vue()]
8 | };
9 |
--------------------------------------------------------------------------------
/config/main.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import "os"
4 |
5 | var ResourcesDir string
6 | var TaskFile string
7 |
8 | func init() {
9 |
10 | currentDir, err := os.Getwd()
11 | if err != nil {
12 | panic(err)
13 | }
14 | ResourcesDir = currentDir + "/resources"
15 | TaskFile = currentDir + "/Task.json"
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, built with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
14 | .idea
15 |
16 | Task.json
17 |
18 | resources
19 | .DS_Store
20 |
--------------------------------------------------------------------------------
/public/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { createStore } from "vuex";
2 | import tasks from "./module/tasks.js";
3 | import lorca from "./module/lorca.js";
4 | import "./module/LorcaToJs.js";
5 |
6 | // Create a new store instance.
7 | export const store = createStore({
8 | modules: {
9 | tasks,
10 | lorca
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/public/src/components/base/SelTip.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/public/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from "vue";
2 | import App from "./App.vue";
3 | import ElementPlus from "element-plus";
4 | import { store } from "./store/index";
5 | import "./assets/style/style.scss";
6 | createApp(App)
7 | .use(store)
8 | .use(ElementPlus)
9 | .mount("#app");
10 |
11 | store.dispatch("initTaskByJsonFile");
12 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/UnderDevelopment.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 功能正在开发中,此任务不可使用,否则任务无法执行
4 |
5 |
6 |
7 |
20 |
--------------------------------------------------------------------------------
/public/src/store/module/LorcaToJs.js:
--------------------------------------------------------------------------------
1 | import { store } from "../index.js";
2 | import { ElNotification } from "element-plus";
3 | window.Notice = (message, type) => {
4 | ElNotification({ message, type, title: type.toUpperCase(), duration: 4000 });
5 | };
6 |
7 | window.UpdateProgress = (taskIndex, progress) => {
8 | store.commit("updateProgress", { taskIndex, progress });
9 | };
10 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Cdp_Ui
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/public/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cdpui",
3 | "version": "0.0.1",
4 | "scripts": {
5 | "dev": "vite",
6 | "build": "vite build"
7 | },
8 | "dependencies": {
9 | "element-plus": "latest",
10 | "vue": "^3.0.5",
11 | "vuex": "^4.0.0"
12 | },
13 | "devDependencies": {
14 | "@vitejs/plugin-vue": "^1.0.4",
15 | "@vue/compiler-sfc": "^3.0.5",
16 | "sass": "^1.32.8",
17 | "vite": "^2.0.0-beta.12"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/public/README.md:
--------------------------------------------------------------------------------
1 | # element-plus-vite-starter
2 |
3 | > A starter kit for Element Plus with Vite
4 |
5 |
6 |
7 |
8 | ## Project setup
9 | ```
10 | npm install
11 | ```
12 |
13 | ### Compiles and hot-reloads for development
14 | ```
15 | npm run dev
16 | ```
17 |
18 | ### Compiles and minifies for production
19 | ```
20 | npm run build
21 | ```
22 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/Navigate.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
27 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/CaptureScreenshot.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 根据当前浏览器窗口大小截取内容
4 |
9 |
10 |
11 |
12 |
13 |
28 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/AddReqHeaders.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
27 |
--------------------------------------------------------------------------------
/public/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
14 |
15 |
26 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module cdpui
2 |
3 | go 1.16
4 |
5 | require (
6 | github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
7 | github.com/chromedp/cdproto v0.0.0-20210222063305-a3ac505ff0bd // indirect
8 | github.com/chromedp/chromedp v0.6.6 // indirect
9 | github.com/disintegration/imaging v1.6.0 // indirect
10 | github.com/gorilla/websocket v1.4.0 // indirect
11 | github.com/knq/sysutil v0.0.0-20181215143952-f05b59f0f307 // indirect
12 | github.com/mitchellh/mapstructure v1.4.1 // indirect
13 | github.com/zserge/lorca v0.1.9
14 | golang.org/x/image v0.0.0-20190417020941-4e30a6eb7d9a // indirect
15 | )
16 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/Click.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
30 |
--------------------------------------------------------------------------------
/js/eval.go:
--------------------------------------------------------------------------------
1 | package js
2 |
3 |
4 | import "fmt"
5 |
6 | func notice(s string, t string) string {
7 | return fmt.Sprintf("window.Notice(`%s`,`%s`)", s, t)
8 | }
9 |
10 | func notifySuccess(s string) string {
11 | return notice(s, "success")
12 | }
13 | func notifyWarning(s string) string {
14 | return notice(s, "warning")
15 | }
16 | func notifyInfo(s string) string {
17 | return notice(s, "info")
18 | }
19 | func notifyError(s string) string {
20 | return notice(s, "error")
21 | }
22 |
23 | func updateProgress(taskIndex int, progress int) string {
24 | return fmt.Sprintf(`window.UpdateProgress("%v","%v")`, taskIndex, progress)
25 | }
--------------------------------------------------------------------------------
/public/src/components/taskModule/WaitVisible.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
30 |
--------------------------------------------------------------------------------
/public/src/store/module/lorca.js:
--------------------------------------------------------------------------------
1 | import { clone } from "../../utils/common.js";
2 | export default {
3 | state() {
4 | return {};
5 | },
6 | mutations: {
7 | runTask(state, val) {
8 | let { index, task } = val;
9 | let t = clone(task);
10 | t.index = index;
11 | window.RunTask(JSON.stringify(t));
12 | },
13 | stopTask(state, index) {
14 | window.StopTask(JSON.stringify(index));
15 | },
16 | openFile(state, index) {
17 | window.OpenFile(JSON.stringify(index));
18 | },
19 | saveJsonFile(state, tasks) {
20 | window.SaveJsonFile(JSON.stringify(tasks));
21 | }
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/Pdf.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 | 文件名:
11 |
12 |
13 |
14 |
15 |
30 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/Sleep.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
13 | 秒
14 |
15 |
16 |
17 |
18 |
33 |
--------------------------------------------------------------------------------
/tasks/cookies.go:
--------------------------------------------------------------------------------
1 | package tasks
2 |
3 | import (
4 | "errors"
5 | "github.com/asaskevich/govalidator"
6 | "github.com/chromedp/cdproto/network"
7 | "github.com/chromedp/chromedp"
8 | "github.com/mitchellh/mapstructure"
9 | )
10 |
11 | func (t *Task) addCookies(args taskArgs) error {
12 | var expectArgs struct {
13 | Cookies []*network.CookieParam `valid:"-"`
14 | }
15 |
16 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
17 | return errors.New("addCookies子任务出错:" + err.Error())
18 | }
19 |
20 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
21 | return errors.New("addCookies子任务参数出错:" + err.Error())
22 | }
23 | return chromedp.Run(*t.ctx, network.SetCookies(expectArgs.Cookies), )
24 | }
25 |
--------------------------------------------------------------------------------
/tasks/request.go:
--------------------------------------------------------------------------------
1 | package tasks
2 |
3 | import (
4 | "errors"
5 | "github.com/asaskevich/govalidator"
6 | "github.com/chromedp/cdproto/network"
7 | "github.com/chromedp/chromedp"
8 | "github.com/mitchellh/mapstructure"
9 | )
10 |
11 | func (t *Task) addReqHeaders(args taskArgs) error {
12 | var expectArgs struct {
13 | Headers taskArgs `valid:"-"`
14 | }
15 |
16 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
17 | return errors.New("setReqHeaders子任务出错:" + err.Error())
18 | }
19 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
20 | return errors.New("setReqHeaders子任务参数出错:" + err.Error())
21 | }
22 | return chromedp.Run(*t.ctx,
23 | network.Enable(),
24 | network.SetExtraHTTPHeaders(network.Headers(expectArgs.Headers)),
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/SetValue.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
15 |
16 |
17 |
18 |
19 |
37 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/EmulateViewport.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
27 |
34 |
--------------------------------------------------------------------------------
/public/src/assets/style/style.scss:
--------------------------------------------------------------------------------
1 | @import "./variables.scss";
2 |
3 | /* 改变 icon 字体路径变量,必需 */
4 | $--font-path: "element-plus/lib/theme-chalk/fonts";
5 |
6 | @import "element-plus/packages/theme-chalk/src/index";
7 |
8 | * {
9 | padding: 0;
10 | margin: 0;
11 | box-sizing: border-box;
12 | }
13 |
14 | ::-webkit-scrollbar {
15 | width: 6px;
16 | height: 6px;
17 | background-color: #f7f7f7;
18 | }
19 | ::-webkit-scrollbar-thumb {
20 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
21 | background-color: $--color-primary;
22 | }
23 | //
24 | //.terminal {
25 | // max-width: 600px;
26 | // padding: 10px;
27 | // max-height: 60vh;
28 | // overflow-y: auto;
29 | // white-space: pre-wrap;
30 | // &::-webkit-scrollbar {
31 | // display: none;
32 | // }
33 | //}
34 |
35 | .el-progress-bar__outer {
36 | background-color: #dcdfe6;
37 | }
38 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/Evaluate.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
13 |
14 |
21 |
22 |
23 |
24 |
40 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "cdpui/js"
5 | "fmt"
6 | "github.com/zserge/lorca"
7 | "runtime"
8 | )
9 |
10 |
11 |
12 | func main() {
13 | var args []string
14 | if runtime.GOOS == "linux" {
15 | args = append(args, "--class=Lorca")
16 | }
17 |
18 | ui, err := lorca.New("", "", 1376, 900, args...)
19 | if err != nil {
20 | fmt.Println(err)
21 | return
22 | }
23 | defer ui.Close()
24 |
25 | if err := js.Bind(&ui); err != nil {
26 | fmt.Println(err)
27 | return
28 | }
29 |
30 | //ln, err := net.Listen("tcp", "127.0.0.1:0")
31 | //if err != nil {
32 | // fmt.Println(err)
33 | //}
34 | //defer ln.Close()
35 | //
36 | //go http.Serve(ln, http.FileServer(http.Dir("public/dist")))
37 | //err = ui.Load(fmt.Sprintf("http://%s", ln.Addr()))
38 | err = ui.Load("http://192.168.50.171:3000/")
39 | if err != nil {
40 | fmt.Println(err)
41 | }
42 |
43 | <-ui.Done()
44 | }
45 |
--------------------------------------------------------------------------------
/tasks/evaluate.go:
--------------------------------------------------------------------------------
1 | package tasks
2 |
3 | import (
4 | "errors"
5 | "github.com/asaskevich/govalidator"
6 | "github.com/chromedp/chromedp"
7 | "github.com/mitchellh/mapstructure"
8 | "io/ioutil"
9 | )
10 |
11 | func (t *Task) evaluate(args taskArgs) error {
12 | var expectArgs struct {
13 | Script string `valid:"required"`
14 | FileName string `valid:"required"`
15 | }
16 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
17 | return errors.New("evaluate子任务出错:" + err.Error())
18 | }
19 |
20 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
21 | return errors.New("evaluate子任务参数出错:" + err.Error())
22 | }
23 |
24 | var file []byte
25 | err := chromedp.Run(*t.ctx, chromedp.Evaluate(expectArgs.Script, &file))
26 |
27 | if err != nil {
28 | return errors.New("evaluate子任务出错:" + err.Error())
29 | }
30 | if err := ioutil.WriteFile(t.workDir()+"/"+expectArgs.FileName, file, 0666); err != nil {
31 | return err
32 | }
33 |
34 | return nil
35 | }
36 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/Screenshot.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
16 |
17 |
23 |
24 |
25 |
26 |
27 |
46 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 SenLin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/public/src/components/AppBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
27 |
28 |
49 |
--------------------------------------------------------------------------------
/public/src/components/taskPanel/AddTaskPanel.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
23 |
24 |
58 |
--------------------------------------------------------------------------------
/tasks/parserRunTask.go:
--------------------------------------------------------------------------------
1 | package tasks
2 |
3 | import "errors"
4 |
5 | func (t *Task) parserRun() error {
6 | for progress, task := range t.Tasks {
7 | t.progress = progress
8 | t.callBack(progress)
9 | if err := t.selectFunc(task.Name, task.Args); err != nil {
10 | return err
11 | }
12 | }
13 | return nil
14 | }
15 |
16 | func (t *Task) selectFunc(taskName string, taskArgs taskArgs) error {
17 | switch taskName {
18 | case "pdf":
19 | return t.pdf(taskArgs)
20 | case "click":
21 | return t.click(taskArgs)
22 | case "sleep":
23 | return t.sleep(taskArgs)
24 | case "evaluate":
25 | return t.evaluate(taskArgs)
26 | case "navigate":
27 | return t.navigate(taskArgs)
28 | case "setValue":
29 | return t.setValue(taskArgs)
30 | case "screenshot":
31 | return t.screenshot(taskArgs)
32 | case "addCookies":
33 | return t.addCookies(taskArgs)
34 | case "waitVisible":
35 | return t.waitVisible(taskArgs)
36 | case "addReqHeaders":
37 | return t.addReqHeaders(taskArgs)
38 | case "emulateViewport":
39 | return t.emulateViewport(taskArgs)
40 | case "captureScreenshot":
41 | return t.captureScreenshot(taskArgs)
42 | default:
43 | return errors.New("未识别的任务名字" + taskName)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/helper/dir.go:
--------------------------------------------------------------------------------
1 | package helper
2 |
3 | import (
4 | "cdpui/config"
5 | "fmt"
6 | "os"
7 | "os/exec"
8 | "strings"
9 | )
10 |
11 | func IsDir(name string) bool {
12 | if info, err := os.Stat(name); err == nil {
13 | return info.IsDir()
14 | }
15 | return false
16 | }
17 |
18 | func FileIsExisted(filename string) bool {
19 | existed := true
20 | if _, err := os.Stat(filename); os.IsNotExist(err) {
21 | existed = false
22 | }
23 | return existed
24 | }
25 |
26 | func MakeDir(dir string) error {
27 | if !IsDir(dir) {
28 | return os.MkdirAll(dir, os.ModePerm)
29 | }
30 | return nil
31 | }
32 |
33 | func RemoveFile(file string) error {
34 | if FileIsExisted(file) {
35 | return os.Remove(file)
36 | }
37 | return nil
38 | }
39 |
40 | func RemoveDir(dir string) error {
41 | if IsDir(dir) {
42 | return os.RemoveAll(dir)
43 | }
44 | return nil
45 | }
46 |
47 | func GetWorkDir(index int) string {
48 | return fmt.Sprintf("%s/%v_task", config.ResourcesDir, index)
49 | }
50 |
51 | func OpenFileManager(index int) error {
52 | //TODO mac linux OpenFileManager Implement
53 | dir := strings.ReplaceAll(GetWorkDir(index),"/","\\")
54 | cmd := exec.Command(`explorer.exe`, `select,`, dir)
55 | return cmd.Run()
56 | }
57 |
--------------------------------------------------------------------------------
/tasks/pdf.go:
--------------------------------------------------------------------------------
1 | package tasks
2 |
3 | import (
4 | "context"
5 | "errors"
6 | "github.com/asaskevich/govalidator"
7 | "github.com/chromedp/cdproto/page"
8 | "github.com/chromedp/chromedp"
9 | "github.com/mitchellh/mapstructure"
10 | "io/ioutil"
11 | )
12 |
13 | func (t *Task) pdf(args taskArgs) error {
14 |
15 | if t.ShowBrowser {
16 | return errors.New("打印网页PDF只支持在无头浏览器模式下运行")
17 | }
18 |
19 | var expectArgs struct {
20 | FileName string `valid:"required"`
21 | }
22 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
23 | return errors.New("pdf子任务出错:" + err.Error())
24 | }
25 |
26 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
27 | return errors.New("pdf子任务参数出错:" + err.Error())
28 | }
29 |
30 | var res []byte
31 | err := chromedp.Run(*t.ctx,
32 | chromedp.ActionFunc(func(ctx context.Context) error {
33 | buf, _, err := page.PrintToPDF().WithPrintBackground(false).Do(ctx)
34 | if err != nil {
35 | return err
36 | }
37 | res = buf
38 | return nil
39 | }),
40 | )
41 | if err != nil {
42 | return errors.New("pdf子任务出错(必须是无头浏览器才能正常运行):" + err.Error())
43 | }
44 | if err := ioutil.WriteFile(t.workDir()+"/"+expectArgs.FileName, res, 0666); err != nil {
45 | return err
46 | }
47 |
48 | return nil
49 | }
50 |
--------------------------------------------------------------------------------
/public/src/utils/common.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 重置对象参数
3 | * @params -> Object
4 | * @arg = Array => []
5 | * @arg = Boolean => false
6 | * @arg = Number => null
7 | * @arg = String => ''
8 | * */
9 | export function resetArgs(args, def = {}) {
10 | for (let key in args) {
11 | console.log(key);
12 | if (def.hasOwnProperty(key)) {
13 | args[key] = def[key];
14 | } else {
15 | if (Array.isArray(args[key])) {
16 | args[key] = [];
17 | }
18 | if ("string" == typeof args[key]) {
19 | args[key] = "";
20 | }
21 | if ("number" == typeof args[key]) {
22 | args[key] = null;
23 | }
24 | if ("boolean" == typeof args[key]) {
25 | args[key] = false;
26 | }
27 | if (Object.prototype.toString.call(args[key]) === "[object Object]") {
28 | args[key] = {};
29 | }
30 | }
31 | }
32 | }
33 |
34 | /**
35 | * 填充对象属性
36 | * @param obj
37 | * @param row
38 | * row属性赋值到obj
39 | */
40 | export function fillerLeft(obj, row = {}) {
41 | for (let key in obj) {
42 | if (
43 | row.hasOwnProperty(key) &&
44 | row[key] !== null &&
45 | row[key] !== undefined
46 | ) {
47 | obj[key] = row[key];
48 | }
49 | }
50 | }
51 | export function clone(obj) {
52 | return JSON.parse(JSON.stringify(obj));
53 | }
54 |
--------------------------------------------------------------------------------
/public/src/store/module/tasks.js:
--------------------------------------------------------------------------------
1 | import { ElNotification } from "element-plus";
2 |
3 | export default {
4 | state() {
5 | return [];
6 | },
7 | mutations: {
8 | addTask(state, task) {
9 | state.push(task);
10 | },
11 | editTask(state, val) {
12 | let { task, index } = val;
13 | state[index] = task;
14 | },
15 | delTask(state, index) {
16 | state.splice(index, 1);
17 | },
18 | addSubTask(state, val) {
19 | let { task, parentIndex } = val;
20 |
21 | state[parentIndex].tasks.push(task);
22 | },
23 | editSubTask(state, val) {
24 | let { task, parentIndex, index } = val;
25 | state[parentIndex].tasks[index] = task;
26 | },
27 | delSubTask(state, val) {
28 | let { parentIndex, index } = val;
29 | state[parentIndex].tasks.splice(index, 1);
30 | },
31 | updateProgress(state, val) {
32 | let { taskIndex, progress } = val;
33 | state[taskIndex].progress = parseInt(progress);
34 | },
35 | initTask(state, t) {
36 | state.push(...t);
37 | }
38 | },
39 | actions: {
40 | initTaskByJsonFile({ commit }) {
41 | if (!window.hasOwnProperty("GetJsonTask")) {
42 | commit("initTask", []);
43 | return;
44 | }
45 | window
46 | .GetJsonTask()
47 | .then(r => {
48 | let task = JSON.parse(r);
49 |
50 | commit("initTask", task || []);
51 | })
52 | .catch(e => {
53 | ElNotification({
54 | message: JSON.stringify(e),
55 | type: "error",
56 | title: "json 初始化任务出错",
57 | duration: 4000
58 | });
59 | commit("initTask", []);
60 | });
61 | }
62 | }
63 | };
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Cdp_Ui
2 |
3 | #### 介绍
4 | CdpUI 是跨平台的,是一个使用 Golang 创建的本地实验性软件,可以构建一些子任务来控制浏览器做任何事情,
5 | 当然也可以通过少许改造变成一个 web 服务来供用户运行任务。
6 |
7 | 
8 |
9 |
10 | 我希望 CdpUI 最终可以通过构建任务完成一些重复性的工作,例如:
11 |
12 | - 前端页面的自动化测试和性能报告(例如测试网页在不同窗口大小下的响应和适配效果)
13 | - 动态爬虫(任务依赖于浏览器渲染,理论上任何反爬虫措施都是无效的)
14 | - 基于网页的重复性工作自动化(例如重复性的通过网页数据来整理你的文档和表格)
15 | - ...
16 |
17 | 目前一些基本的工作已经完成,但是还有很多很棒的想法需要去完成。
18 |
19 | - [x] pdf || 生成PDF
20 | - [x] click || 点击元素
21 | - [x] sleep || 等待一会
22 | - [x] evaluate || 执行脚本
23 | - [x] navigate || 打开网址
24 | - [x] setValue || 往输入框输入内容
25 | - [x] screenshot || 截取网页内容
26 | - [x] addCookies || 添加Cookies
27 | - [x] waitVisible || 等待元素加载完成
28 | - [x] addReqHeaders || 添加请求头
29 | - [x] emulateViewport || 改变窗口大小
30 | - [x] captureScreenshot || 捕获屏幕
31 | - [ ] collectDataByExcel || 通过表格搜集数据
32 | - [ ] collectDataByWord || 通过文档搜集数据
33 | - [ ] packageFile || 打包目前生成的所有文件
34 | - [ ] ...
35 |
36 |
37 |
38 | #### 运行原理
39 |
40 | 借助第三方库,运行此程序会尝试找到本地安装的 Chrome 并打开一个 Chrome 窗口,通过websocket连接到其dev-tools端点,
41 | 发送要加载的HTML,并提供Go和JS之间的通信。基于此,前端通过 vue3 vite vuex 等提供页面 UI 和交互,通过将构建的任务发送到 Golang。
42 | 此时, Golang 会创建 Chrome 实例上下文,使用 Chrome DevTools 协议驱动无头浏览器(默认情况下无UI,你也可以显示浏览器以便查看任务的运行过程)来运行你组建的任务。
43 |
44 |
45 | #### 一些思考
46 | 通过表格搜集数据和通过文档搜集数据是什么呢??
47 | 我在上一家公司曾经开发过一个功能,公司是一个集团子公司,按照集团要求,每个员工需要在一个月内学习一些东西并写出自己的读后感,
48 | HR需要收集每个人的读后感并整理成规定的word文档(对word的段落文字颜色大小有严格的规定)上交,这对于HR无疑是一个不小的挑战。
49 | 后来我提出在公司的OA办公系统里加入此功能,员工登陆系统提交自己的读后感,通过PHP读取预设的word文档模板,使用正则替换,一篇篇漂亮的文档就被生成了。
50 | 因此,通过文档收集网页数据就是这种思路,由你做好文档模板,精心排版,不过关键的地方需要你使用诸如${#app > div.body > div.main > div.paragraph }的符号表示,
51 | 那么在任务运行的过程中会将定位到的文字嵌入相应的地方,并且不会破坏你的文档格式。
52 |
53 | 虽然上面的这些功能最终都能被实现,但是对于自动化依旧有很大的局限性,除非给任务加入循环判断跳转的逻辑单元,否则它仅仅只能满足一部分场景,灵活度很有限。
54 | 但是,加入这些逻辑单元也会带来一些问题,比如一次运行任务可以简单将各种产生的文件生成,如果存在循环,那么文件名则需要处理以防止被覆盖等,因此此项目还在探索阶段,目前对于小白不是那么友好。
55 |
--------------------------------------------------------------------------------
/public/src/components/base/MapEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
14 | 添加
20 |
21 |
22 | {{ "{" }}
23 | {{ k }}:{{ v }}
29 |
30 | {{ "}" }}
31 |
32 |
33 |
34 |
35 |
73 |
74 |
88 |
--------------------------------------------------------------------------------
/public/src/components/Container.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
62 |
63 |
76 |
--------------------------------------------------------------------------------
/public/src/components/base/ArrMapEdit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
14 | 添加
20 |
21 |
22 | [
23 | {{ v }}
29 |
30 | ]
31 |
32 |
33 |
34 |
35 |
80 |
81 |
95 |
--------------------------------------------------------------------------------
/public/src/config/tasks.js:
--------------------------------------------------------------------------------
1 | import Pdf from "../components/taskModule/Pdf.vue";
2 | import Click from "../components/taskModule/Click.vue";
3 | import Sleep from "../components/taskModule/Sleep.vue";
4 | import Evaluate from "../components/taskModule/Evaluate.vue";
5 | import Navigate from "../components/taskModule/Navigate.vue";
6 | import SetValue from "../components/taskModule/SetValue.vue";
7 | import Screenshot from "../components/taskModule/Screenshot.vue";
8 | import AddCookies from "../components/taskModule/AddCookies.vue";
9 | import WaitVisible from "../components/taskModule/WaitVisible.vue";
10 | import AddReqHeaders from "../components/taskModule/AddReqHeaders.vue";
11 | import EmulateViewport from "../components/taskModule/EmulateViewport.vue";
12 | import CaptureScreenshot from "../components/taskModule/CaptureScreenshot.vue";
13 | import UnderDevelopment from "../components/taskModule/UnderDevelopment.vue";
14 | export default [
15 | {
16 | name: "pdf",
17 | title: "生成PDF",
18 | argsModule: Pdf
19 | },
20 | {
21 | name: "click",
22 | title: "点击元素",
23 | argsModule: Click
24 | },
25 | {
26 | name: "sleep",
27 | title: "等待一会",
28 | argsModule: Sleep
29 | },
30 | {
31 | name: "evaluate",
32 | title: "执行脚本",
33 | argsModule: Evaluate
34 | },
35 | {
36 | name: "navigate",
37 | title: "打开网址",
38 | argsModule: Navigate
39 | },
40 | {
41 | name: "setValue",
42 | title: "往输入框输入内容",
43 | argsModule: SetValue
44 | },
45 | {
46 | name: "screenshot",
47 | title: "截取网页内容",
48 | argsModule: Screenshot
49 | },
50 | {
51 | name: "addCookies",
52 | title: "添加Cookies",
53 | argsModule: AddCookies
54 | },
55 | {
56 | name: "waitVisible",
57 | title: "等待元素加载完成",
58 | argsModule: WaitVisible
59 | },
60 | {
61 | name: "addReqHeaders",
62 | title: "添加请求头",
63 | argsModule: AddReqHeaders
64 | },
65 | {
66 | name: "emulateViewport",
67 | title: "改变窗口大小",
68 | argsModule: EmulateViewport
69 | },
70 | {
71 | name: "captureScreenshot",
72 | title: "捕获屏幕",
73 | argsModule: CaptureScreenshot
74 | },
75 | {
76 | name: "collectDataByExcel",
77 | title: "通过表格搜集数据",
78 | argsModule: UnderDevelopment
79 | },
80 | {
81 | name: "collectDataByWord",
82 | title: "通过文档搜集数据",
83 | argsModule: UnderDevelopment
84 | },
85 | {
86 | name: "packageFile",
87 | title: "打包目前生成的所有文件",
88 | argsModule: UnderDevelopment
89 | }
90 | ];
91 |
--------------------------------------------------------------------------------
/public/src/utils/validateRules.js:
--------------------------------------------------------------------------------
1 | export const Phone = {
2 | pattern: /^1((3[\d])|(4[5,6,7,9])|(5[0-3,5-9])|(6[5-7])|(7[0-8])|(8[\d])|(9[1,8,9]))\d{8}$/,
3 | message: "请输入正确的手机号码",
4 | trigger: "blur"
5 | };
6 |
7 | export const Number = {
8 | type: "number",
9 | message: "只能填写数字",
10 | trigger: "blur"
11 | };
12 |
13 | export const String = {
14 | type: "string",
15 | message: "只能填写字符串",
16 | trigger: "blur"
17 | };
18 |
19 | export const Required = {
20 | required: true,
21 | message: "填写不能为空",
22 | trigger: "blur"
23 | };
24 |
25 | export const Array = {
26 | type: "array",
27 | message: "请选择选项",
28 | trigger: "change"
29 | };
30 |
31 | export const Date = { type: "date", message: "请选择日期", trigger: "change" };
32 |
33 | export const Email = {
34 | type: "email",
35 | message: "请输入正确的邮箱",
36 | trigger: "blur"
37 | };
38 |
39 | export const StrLen3To18 = {
40 | pattern: /^.{3,18}$/,
41 | message: "字符长度限制在2到18个",
42 | trigger: "blur"
43 | };
44 |
45 | export const Float = {
46 | pattern: /^(([1-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/,
47 | message: "只能填写数字并且最多两位小数",
48 | trigger: "blur"
49 | };
50 |
51 | export const FloatAnd0 = {
52 | pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/,
53 | message: "只能填写数字并且最多两位小数",
54 | trigger: "blur"
55 | };
56 |
57 | export const FloatGeq1 = {
58 | pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^[1-9]\.[0-9]([0-9])?$)/,
59 | message: "只能填写数字并且大于等于1,最多两位小数",
60 | trigger: "blur"
61 | };
62 |
63 | export const FloatMax100 = {
64 | pattern: /^\d\.([1-9]{1,2}|[0-9][1-9])$|^[1-9]\d{0,1}(\.\d{1,2}){0,1}$|^100(\.0{1,2}){0,1}$/,
65 | message: "只能填写数字并且最大数是100不能超个两位小数",
66 | trigger: "blur"
67 | };
68 |
69 | export const Url = {
70 | pattern: /(^https?|^nurse):\/\//i,
71 | message: "请输入正确的链接地址",
72 | trigger: "blur"
73 | };
74 |
75 | export const IntMax99 = {
76 | pattern: /^[1-9][0-9]{0,1}$/,
77 | message: "只能填写1-99的整数",
78 | trigger: "blur"
79 | };
80 |
81 | export const FloatMin0Max100 = {
82 | pattern: /^(\d|[1-9]\d|100)(\.\d{1,2})?$/,
83 | message: "只能填写0-100,不能超个两位小数",
84 | trigger: "blur"
85 | };
86 |
87 | export const StrongPassword = {
88 | pattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,18}$/,
89 | message: "大小写+数字组成,字数6-18位",
90 | trigger: "blur"
91 | };
92 |
93 | export const NumberString = {
94 | pattern: /^\d+$/,
95 | message: "只能输入数字",
96 | trigger: "blur"
97 | };
98 |
99 | export const Geq1NumberString = {
100 | pattern: /^[1-9][0-9]*$/,
101 | message: "只能填写大于等于1的整数",
102 | trigger: "blur"
103 | };
104 |
105 | export const PasswordLength = {
106 | pattern: /^[0-9a-zA-Z]{8,20}$/,
107 | message: "数字或字母组成,字数8-20位",
108 | trigger: "blur"
109 | };
110 |
111 | export function FillerFieldRules(fields = [], rules) {
112 | let newRules = {};
113 | fields.forEach(f => {
114 | newRules[f] = rules;
115 | });
116 | return newRules;
117 | }
118 |
--------------------------------------------------------------------------------
/public/src/components/taskModule/AddCookies.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | [
5 | {{ v }}
11 |
12 | ]
13 |
14 |
15 |
16 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
36 | 添加
42 |
43 |
44 |
45 |
46 |
47 |
103 |
120 |
--------------------------------------------------------------------------------
/tasks/main.go:
--------------------------------------------------------------------------------
1 | package tasks
2 |
3 | import (
4 | "cdpui/helper"
5 | "context"
6 | "encoding/json"
7 | "errors"
8 | "github.com/chromedp/chromedp"
9 | "time"
10 | )
11 |
12 | type taskArgs map[string]interface{}
13 | type flagArgs map[string]interface{}
14 |
15 | type Task struct {
16 | Index int `json:"index"`
17 | Title string `json:"title"`
18 | Tasks []taskDesc `json:"tasks"`
19 | Flags []flagArgs `json:"flags"`
20 | Width int `json:"width"`
21 | Height int `json:"height"`
22 | TimeOut time.Duration `json:"timeOut"`
23 | UserAgent string `json:"userAgent"`
24 | ShowBrowser bool `json:"showBrowser"`
25 | //////
26 | progress int
27 | callBack func(int)
28 | ctx *context.Context
29 | cancel context.CancelFunc
30 | }
31 |
32 | type taskDesc struct {
33 | Name string `json:"name"`
34 | Args taskArgs `json:"args"`
35 | }
36 |
37 | func New(tasksDesc []byte) (*Task, error) {
38 | var task Task
39 |
40 | if err := json.Unmarshal(tasksDesc, &task); err != nil {
41 | return nil, errors.New("任务Json解析出错:" + err.Error())
42 | }
43 |
44 | if task.Width == 0 {
45 | task.Width = 1366
46 | }
47 | if task.Height == 0 {
48 | task.Height = 768
49 | }
50 | if task.UserAgent == "" {
51 | task.UserAgent = `Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36`
52 | }
53 |
54 | return &task, nil
55 | }
56 |
57 | //目前还不支持操作打开新的TAB
58 |
59 | func (t *Task) Run() error {
60 |
61 | if err := t.initDir(); err != nil {
62 | return err
63 | }
64 |
65 | options := []chromedp.ExecAllocatorOption{
66 | chromedp.Flag("headless", !t.ShowBrowser),
67 | chromedp.WindowSize(t.Width, t.Width),
68 | chromedp.UserAgent(t.UserAgent),
69 |
70 | }
71 | //chromedp.Flag("hide-scrollbars", false),
72 | //chromedp.Flag("mute-audio", false),
73 | //chromedp.Flag("mute-audio", false),
74 | //chromedp.Flag("ignore-certificate-errors", "1"),
75 | for k, v := range t.Flags {
76 | options = append(options, chromedp.Flag(string(k), v))
77 | }
78 |
79 | options = append(chromedp.DefaultExecAllocatorOptions[:], options...)
80 |
81 | c, cc := chromedp.NewExecAllocator(context.Background(), options...)
82 | defer cc()
83 |
84 | ctx, cancel := chromedp.NewContext(c,chromedp.WithLogf(func(s string, i ...interface{}) {
85 |
86 | }))
87 | defer cancel()
88 |
89 | ctx, cancel = context.WithTimeout(ctx, t.TimeOut*time.Second)
90 | defer cancel()
91 |
92 | t.ctx = &ctx
93 | t.cancel = cc
94 |
95 | return t.parserRun()
96 | }
97 |
98 | func (t *Task) BindCallBack(f func(int)) {
99 | t.callBack = f
100 | }
101 |
102 | func (t *Task) Done() <-chan struct{} {
103 | return (*t.ctx).Done()
104 | }
105 | func (t *Task) Cancel() {
106 | t.cancel()
107 | }
108 | func (t *Task) workDir() string {
109 | return helper.GetWorkDir(t.Index)
110 | }
111 |
112 | func (t *Task) initDir() error {
113 |
114 | dir := t.workDir()
115 |
116 | if err := helper.RemoveDir(dir); err != nil {
117 | return err
118 | }
119 |
120 | if err := helper.MakeDir(dir); err != nil {
121 | return err
122 | }
123 |
124 | return nil
125 | }
126 |
--------------------------------------------------------------------------------
/js/bind.go:
--------------------------------------------------------------------------------
1 | package js
2 |
3 | import (
4 | "cdpui/config"
5 | "cdpui/helper"
6 | "cdpui/tasks"
7 | "github.com/zserge/lorca"
8 | "io/ioutil"
9 | "os"
10 | "strconv"
11 | )
12 | var UI lorca.UI
13 | var Tasks = make(map[int]*tasks.Task) //正在运行的任务
14 |
15 | func Bind(ui *lorca.UI) error {
16 | UI = *ui
17 | if err := UI.Bind("RunTask", runTask); err != nil {
18 | return err
19 | }
20 | if err := UI.Bind("StopTask", stopTask); err != nil {
21 | return err
22 | }
23 | if err := UI.Bind("OpenFile", openFile); err != nil {
24 | return err
25 | }
26 | if err := UI.Bind("SaveJsonFile", saveJsonFile); err != nil {
27 | return err
28 | }
29 | if err := UI.Bind("GetJsonTask", getJsonTask); err != nil {
30 | return err
31 | }
32 | return nil
33 | }
34 |
35 | func runTask(t string) {
36 | task, err := tasks.New([]byte(t))
37 | if err != nil {
38 | UI.Eval(notifyError(err.Error()))
39 | return
40 | }
41 | _, exist := Tasks[task.Index]
42 | if exist {
43 | UI.Eval(notifyError("之前的任务还在运行"))
44 | return
45 | }
46 |
47 | task.BindCallBack(func(progress int) {
48 | UI.Eval(updateProgress(task.Index, progress))
49 | })
50 | Tasks[task.Index] = task
51 |
52 | go func() {
53 | UI.Eval(notifyInfo("开始执行任务" + task.Title))
54 | err = Tasks[task.Index].Run()
55 | if err != nil {
56 | UI.Eval(notifyError(err.Error()))
57 | UI.Eval(updateProgress(task.Index, -1))
58 | delete(Tasks, task.Index)
59 | return
60 | }
61 | UI.Eval(notifySuccess("任务执行完毕"))
62 | UI.Eval(updateProgress(task.Index, -1))
63 | delete(Tasks, task.Index)
64 | }()
65 | }
66 |
67 | func stopTask(i string) {
68 | index, err := strconv.Atoi(i)
69 | if err != nil {
70 | UI.Eval(notifyError(err.Error()))
71 | return
72 | }
73 | task, exist := Tasks[index]
74 |
75 | if !exist {
76 | UI.Eval(notifyError("此任务不存在"))
77 | return
78 | }
79 | select {
80 | case <-task.Done():
81 | UI.Eval(updateProgress(task.Index, -1))
82 | UI.Eval(notifySuccess("此任务已经完成"))
83 | default:
84 | task.Cancel()
85 | UI.Eval(updateProgress(task.Index, -1))
86 | UI.Eval(notifySuccess("此任务已经暂停"))
87 | }
88 | }
89 |
90 | func openFile(i string) {
91 | index, err := strconv.Atoi(i)
92 |
93 | if err != nil {
94 | UI.Eval(notifyError(err.Error()))
95 | return
96 | }
97 |
98 | if !helper.IsDir(helper.GetWorkDir(index)) {
99 | UI.Eval(notifyWarning("此任务还没有产生文件"))
100 | return
101 | }
102 |
103 | if err := helper.OpenFileManager(index); err != nil {
104 | UI.Eval(notifyError(err.Error()))
105 | return
106 | }
107 | }
108 |
109 | func saveJsonFile(t string) {
110 | if err := helper.RemoveFile(config.TaskFile);err != nil {
111 | UI.Eval(notifyError(err.Error()))
112 | return
113 | }
114 | err := ioutil.WriteFile(config.TaskFile, []byte(t), os.ModeAppend)
115 | if err != nil {
116 | UI.Eval(notifyError(err.Error()))
117 | return
118 | }
119 | UI.Eval(notifySuccess("任务保存成功"))
120 | }
121 |
122 | func getJsonTask() string {
123 | if helper.FileIsExisted(config.TaskFile){
124 | b, err := ioutil.ReadFile(config.TaskFile)
125 | if err != nil {
126 | UI.Eval(notifyError(err.Error()))
127 | return "[]"
128 | }
129 | return string(b)
130 | }
131 | return "[]"
132 | }
133 |
134 |
--------------------------------------------------------------------------------
/tasks/screenshot.go:
--------------------------------------------------------------------------------
1 | package tasks
2 |
3 | import (
4 | "context"
5 | "errors"
6 | "github.com/asaskevich/govalidator"
7 | "github.com/chromedp/cdproto/emulation"
8 | "github.com/chromedp/cdproto/page"
9 | "github.com/chromedp/chromedp"
10 | "github.com/mitchellh/mapstructure"
11 | "io/ioutil"
12 | "math"
13 | )
14 |
15 | //截屏,全屏或者截取某个元素
16 | func (t *Task) screenshot(args taskArgs) error {
17 | var expectArgs struct {
18 | Sel string
19 | FullPage bool
20 | FileName string `valid:"required"`
21 | }
22 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
23 | return errors.New("screenshot子任务出错:" + err.Error())
24 | }
25 |
26 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
27 | return errors.New("screenshot子任务参数出错:" + err.Error())
28 | }
29 |
30 | var err error
31 | var file []byte
32 |
33 | if expectArgs.FullPage {
34 | err = chromedp.Run(*t.ctx, fullPage(100, &file))
35 | } else {
36 | err = chromedp.Run(*t.ctx, element(expectArgs.Sel, &file))
37 | }
38 | if err != nil {
39 | return errors.New("screenshot子任务出错:" + err.Error())
40 | }
41 | if err := ioutil.WriteFile(t.workDir()+"/"+expectArgs.FileName, file, 0666); err != nil {
42 | return err
43 | }
44 | return nil
45 | }
46 |
47 | //截取当前视窗
48 | func (t *Task) captureScreenshot(args taskArgs) error {
49 | var expectArgs struct {
50 | FileName string `valid:"required"`
51 | }
52 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
53 | return errors.New("captureScreenshot子任务出错:" + err.Error())
54 | }
55 |
56 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
57 | return errors.New("captureScreenshot子任务参数出错:" + err.Error())
58 | }
59 |
60 | var file []byte
61 | err := chromedp.Run(*t.ctx, chromedp.CaptureScreenshot(&file))
62 |
63 | if err != nil {
64 | return errors.New("captureScreenshot子任务出错:" + err.Error())
65 | }
66 | if err := ioutil.WriteFile(t.workDir()+"/"+expectArgs.FileName, file, 0666); err != nil {
67 | return err
68 | }
69 |
70 | return nil
71 | }
72 |
73 | func element(sel string, res *[]byte) chromedp.Tasks {
74 |
75 | return chromedp.Tasks{
76 | chromedp.WaitVisible(sel),
77 | chromedp.Screenshot(sel, res, chromedp.NodeVisible),
78 | }
79 | }
80 |
81 | func fullPage(quality int64, res *[]byte) chromedp.Tasks {
82 | return chromedp.Tasks{
83 | chromedp.ActionFunc(func(ctx context.Context) error {
84 | _, _, contentSize, err := page.GetLayoutMetrics().Do(ctx)
85 | if err != nil {
86 | return err
87 | }
88 |
89 | width, height := int64(math.Ceil(contentSize.Width)), int64(math.Ceil(contentSize.Height))
90 |
91 | // force viewport emulation
92 | err = emulation.SetDeviceMetricsOverride(width, height, 1, false).
93 | WithScreenOrientation(&emulation.ScreenOrientation{
94 | Type: emulation.OrientationTypePortraitPrimary,
95 | Angle: 0,
96 | }).
97 | Do(ctx)
98 | if err != nil {
99 | return err
100 | }
101 |
102 | *res, err = page.CaptureScreenshot().
103 | WithQuality(quality).
104 | WithClip(&page.Viewport{
105 | X: contentSize.X,
106 | Y: contentSize.Y,
107 | Width: contentSize.Width,
108 | Height: contentSize.Height,
109 | Scale: 1,
110 | }).Do(ctx)
111 | if err != nil {
112 | return err
113 | }
114 | return nil
115 | }),
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/tasks/base.go:
--------------------------------------------------------------------------------
1 | package tasks
2 |
3 | import (
4 | "errors"
5 | "github.com/asaskevich/govalidator"
6 | "github.com/chromedp/chromedp"
7 | "github.com/mitchellh/mapstructure"
8 | "time"
9 | )
10 |
11 | //导航
12 | func (t *Task) navigate(args taskArgs) error {
13 |
14 | var expectArgs struct {
15 | Host string `valid:"requrl"`
16 | }
17 |
18 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
19 | return errors.New("navigate子任务出错:" + err.Error())
20 | }
21 |
22 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
23 | return errors.New("navigate子任务参数出错:" + err.Error())
24 | }
25 | return chromedp.Run(*t.ctx, chromedp.Navigate(expectArgs.Host))
26 | }
27 |
28 | //调整浏览器大小
29 | func (t *Task) emulateViewport(args taskArgs) error {
30 |
31 | var expectArgs struct {
32 | Width int64 `valid:"required"`
33 | Height int64 `valid:"required"`
34 | }
35 |
36 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
37 | return errors.New("emulateViewport子任务出错:" + err.Error())
38 | }
39 |
40 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
41 | return errors.New("emulateViewport子任务参数出错:" + err.Error())
42 | }
43 | return chromedp.Run(*t.ctx, chromedp.EmulateViewport(expectArgs.Width, expectArgs.Height))
44 | }
45 |
46 | //等待元素加载
47 | func (t *Task) waitVisible(args taskArgs) error {
48 | var expectArgs struct {
49 | Sel string `valid:"required"`
50 | }
51 |
52 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
53 | return errors.New("waitVisible子任务出错:" + err.Error())
54 | }
55 |
56 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
57 | return errors.New("waitVisible子任务参数出错:" + err.Error())
58 | }
59 | return chromedp.Run(*t.ctx, chromedp.WaitVisible(expectArgs.Sel))
60 | }
61 |
62 | //输入内容,覆盖之前的
63 | func (t *Task) setValue (args taskArgs) error {
64 | var expectArgs struct {
65 | Sel string `valid:"required"`
66 | Val string `valid:"required"`
67 | }
68 |
69 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
70 | return errors.New("sendKeys子任务出错:" + err.Error())
71 | }
72 |
73 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
74 | return errors.New("sendKeys子任务参数出错:" + err.Error())
75 | }
76 | return chromedp.Run(*t.ctx, chromedp.SetValue(expectArgs.Sel, expectArgs.Val))
77 | }
78 |
79 | //点击元素
80 | func (t *Task) click(args taskArgs) error {
81 | var expectArgs struct {
82 | Sel string `valid:"required"`
83 | }
84 |
85 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
86 | return errors.New("click子任务出错:" + err.Error())
87 | }
88 |
89 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
90 | return errors.New("click子任务参数出错:" + err.Error())
91 | }
92 | return chromedp.Run(*t.ctx, chromedp.Click(expectArgs.Sel, chromedp.NodeVisible))
93 | }
94 | //休眠
95 | func (t *Task) sleep(args taskArgs) error {
96 | var expectArgs struct {
97 | Second time.Duration `valid:"required"`
98 | }
99 |
100 | if err := mapstructure.Decode(args, &expectArgs); err != nil {
101 | return errors.New("sleep子任务出错:" + err.Error())
102 | }
103 |
104 | if _, err := govalidator.ValidateStruct(&expectArgs); err != nil {
105 | return errors.New("sleep子任务参数出错:" + err.Error())
106 | }
107 | return chromedp.Run(*t.ctx, chromedp.Sleep(expectArgs.Second * time.Second))
108 | }
109 |
--------------------------------------------------------------------------------
/public/src/components/taskPanel/TaskCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
{{ task.name }}
9 |
10 |
11 |
12 |
13 |
14 |
{{ task.title }}
15 |
16 |
17 |
18 |
19 |
20 |
{{ task.desc }}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
{{ index + 1 }}
29 |
30 |
31 |
32 |
53 |
54 |
126 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg=
2 | github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
3 | github.com/chromedp/cdproto v0.0.0-20210222063305-a3ac505ff0bd h1:NpLicpTmd1m6SqIR0VjR24IaQXHJe/t11P2d2xKGx90=
4 | github.com/chromedp/cdproto v0.0.0-20210222063305-a3ac505ff0bd/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
5 | github.com/chromedp/chromedp v0.6.6 h1:/cxTTWu097YeUBdFNuwe65crupzNP9CFVotrO1JzAdc=
6 | github.com/chromedp/chromedp v0.6.6/go.mod h1:I+DAskCTsBRt/48EVXbfmIUdMsSIyTR3sdxrCOXlrLY=
7 | github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
8 | github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
9 | github.com/disintegration/imaging v1.6.0/go.mod h1:xuIt+sRxDFrHS0drzXUlCJthkJ8k7lkkUojDSR247MQ=
10 | github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
11 | github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
12 | github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
13 | github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
14 | github.com/gobwas/ws v1.0.4 h1:5eXU1CZhpQdq5kXbKb+sECH5Ia5KiO6CYzIzdlVx6Bs=
15 | github.com/gobwas/ws v1.0.4/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
16 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
17 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
18 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
19 | github.com/knq/sysutil v0.0.0-20181215143952-f05b59f0f307/go.mod h1:BjPj+aVjl9FW/cCGiF3nGh5v+9Gd3VCgBQbod/GlMaQ=
20 | github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
21 | github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
22 | github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
23 | github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
24 | github.com/zserge/lorca v0.1.9 h1:vbDdkqdp2/rmeg8GlyCewY2X8Z+b0s7BqWyIQL/gakc=
25 | github.com/zserge/lorca v0.1.9/go.mod h1:bVmnIbIRlOcoV285KIRSe4bUABKi7R7384Ycuum6e4A=
26 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
27 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
28 | golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
29 | golang.org/x/image v0.0.0-20190417020941-4e30a6eb7d9a/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
30 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0 h1:MsuvTghUPjX762sGLnGsxC3HM0B5r83wEtYcYR8/vRs=
31 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
32 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
33 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
34 | golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 h1:SgQ6LNaYJU0JIuEHv9+s6EbhSCwYeAf5Yvj6lpYlqAE=
35 | golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
36 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
37 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
38 |
--------------------------------------------------------------------------------
/public/src/components/taskPanel/EditTask.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
48 |
49 |
50 |
51 |
52 |
118 |
--------------------------------------------------------------------------------
/public/src/components/taskPanel/EditSubTask.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
18 |
23 |
29 | {{ item.name }}
30 | {{
31 | item.title
32 | }}
33 |
34 |
35 |
36 | 任务标题:{{ form.title ? form.title : "" }}
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
56 |
57 |
58 |
59 |
60 |
131 |
132 |
149 |
--------------------------------------------------------------------------------
/public/src/components/taskPanel/Tasks.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | {{ task.title }}
14 |
15 |
({{ task.tasks.length }})
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
41 |
42 |
57 |
58 | 运行任务
66 | 停止任务({{ task.tasks[task.progress].title }})
74 |
75 |
76 |
77 |
78 |
79 |
144 |
145 |
230 |
--------------------------------------------------------------------------------
/public/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@babel/helper-validator-identifier@^7.12.11":
6 | version "7.12.11"
7 | resolved "https://registry.npm.taobao.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.12.11.tgz?cache=0&sync_timestamp=1608075248751&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-validator-identifier%2Fdownload%2F%40babel%2Fhelper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
8 | integrity sha1-yaHwIZF9y1zPDU5FPjmQIpgfye0=
9 |
10 | "@babel/parser@^7.12.0":
11 | version "7.13.0"
12 | resolved "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.13.0.tgz?cache=0&sync_timestamp=1614034252382&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.13.0.tgz#49b9b6ee213e5634fa80361dae139effef893f78"
13 | integrity sha1-Sbm27iE+VjT6gDYdrhOe/++JP3g=
14 |
15 | "@babel/types@^7.12.0":
16 | version "7.13.0"
17 | resolved "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.13.0.tgz?cache=0&sync_timestamp=1614034253440&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftypes%2Fdownload%2F%40babel%2Ftypes-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80"
18 | integrity sha1-dEJNKBbwFxtBAPCrNOmjdO/ff4A=
19 | dependencies:
20 | "@babel/helper-validator-identifier" "^7.12.11"
21 | lodash "^4.17.19"
22 | to-fast-properties "^2.0.0"
23 |
24 | "@popperjs/core@^2.4.4":
25 | version "2.8.3"
26 | resolved "https://registry.npm.taobao.org/@popperjs/core/download/@popperjs/core-2.8.3.tgz?cache=0&sync_timestamp=1613995241043&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40popperjs%2Fcore%2Fdownload%2F%40popperjs%2Fcore-2.8.3.tgz#8b4eae3d9dd470c022cb9238128db8b1906e7fca"
27 | integrity sha1-i06uPZ3UcMAiy5I4Eo24sZBuf8o=
28 |
29 | "@vitejs/plugin-vue@^1.0.4":
30 | version "1.1.4"
31 | resolved "https://registry.npm.taobao.org/@vitejs/plugin-vue/download/@vitejs/plugin-vue-1.1.4.tgz#1dd388519b75439b7733601b55238ca691864796"
32 | integrity sha1-HdOIUZt1Q5t3M2AbVSOMppGGR5Y=
33 |
34 | "@vue/compiler-core@3.0.5":
35 | version "3.0.5"
36 | resolved "https://registry.npm.taobao.org/@vue/compiler-core/download/@vue/compiler-core-3.0.5.tgz#a6e54cabe9536e74c6513acd2649f311af1d43ac"
37 | integrity sha1-puVMq+lTbnTGUTrNJknzEa8dQ6w=
38 | dependencies:
39 | "@babel/parser" "^7.12.0"
40 | "@babel/types" "^7.12.0"
41 | "@vue/shared" "3.0.5"
42 | estree-walker "^2.0.1"
43 | source-map "^0.6.1"
44 |
45 | "@vue/compiler-dom@3.0.5":
46 | version "3.0.5"
47 | resolved "https://registry.npm.taobao.org/@vue/compiler-dom/download/@vue/compiler-dom-3.0.5.tgz#7885a13e6d18f64dde8ebceec052ed2c102696c2"
48 | integrity sha1-eIWhPm0Y9k3ejrzuwFLtLBAmlsI=
49 | dependencies:
50 | "@vue/compiler-core" "3.0.5"
51 | "@vue/shared" "3.0.5"
52 |
53 | "@vue/compiler-sfc@^3.0.5":
54 | version "3.0.5"
55 | resolved "https://registry.npm.taobao.org/@vue/compiler-sfc/download/@vue/compiler-sfc-3.0.5.tgz#3ae08e60244a72faf9598361874fb7bdb5b1d37c"
56 | integrity sha1-OuCOYCRKcvr5WYNhh0+3vbWx03w=
57 | dependencies:
58 | "@babel/parser" "^7.12.0"
59 | "@babel/types" "^7.12.0"
60 | "@vue/compiler-core" "3.0.5"
61 | "@vue/compiler-dom" "3.0.5"
62 | "@vue/compiler-ssr" "3.0.5"
63 | "@vue/shared" "3.0.5"
64 | consolidate "^0.16.0"
65 | estree-walker "^2.0.1"
66 | hash-sum "^2.0.0"
67 | lru-cache "^5.1.1"
68 | magic-string "^0.25.7"
69 | merge-source-map "^1.1.0"
70 | postcss "^7.0.32"
71 | postcss-modules "^3.2.2"
72 | postcss-selector-parser "^6.0.4"
73 | source-map "^0.6.1"
74 |
75 | "@vue/compiler-ssr@3.0.5":
76 | version "3.0.5"
77 | resolved "https://registry.npm.taobao.org/@vue/compiler-ssr/download/@vue/compiler-ssr-3.0.5.tgz#7661ad891a0be948726c7f7ad1e425253c587b83"
78 | integrity sha1-dmGtiRoL6UhybH960eQlJTxYe4M=
79 | dependencies:
80 | "@vue/compiler-dom" "3.0.5"
81 | "@vue/shared" "3.0.5"
82 |
83 | "@vue/reactivity@3.0.5":
84 | version "3.0.5"
85 | resolved "https://registry.npm.taobao.org/@vue/reactivity/download/@vue/reactivity-3.0.5.tgz#e3789e4d523d845f9ae0b4d770e2b45594742fd2"
86 | integrity sha1-43ieTVI9hF+a4LTXcOK0VZR0L9I=
87 | dependencies:
88 | "@vue/shared" "3.0.5"
89 |
90 | "@vue/runtime-core@3.0.5":
91 | version "3.0.5"
92 | resolved "https://registry.npm.taobao.org/@vue/runtime-core/download/@vue/runtime-core-3.0.5.tgz#da6331d5f300d5794e9e0ebdc8a8bd72a9e19962"
93 | integrity sha1-2mMx1fMA1XlOng69yKi9cqnhmWI=
94 | dependencies:
95 | "@vue/reactivity" "3.0.5"
96 | "@vue/shared" "3.0.5"
97 |
98 | "@vue/runtime-dom@3.0.5":
99 | version "3.0.5"
100 | resolved "https://registry.npm.taobao.org/@vue/runtime-dom/download/@vue/runtime-dom-3.0.5.tgz#1ce2c9c449e26ab06963da0064096e882a7a8935"
101 | integrity sha1-HOLJxEniarBpY9oAZAluiCp6iTU=
102 | dependencies:
103 | "@vue/runtime-core" "3.0.5"
104 | "@vue/shared" "3.0.5"
105 | csstype "^2.6.8"
106 |
107 | "@vue/shared@3.0.5":
108 | version "3.0.5"
109 | resolved "https://registry.npm.taobao.org/@vue/shared/download/@vue/shared-3.0.5.tgz#c131d88bd6713cc4d93b3bb1372edb1983225ff0"
110 | integrity sha1-wTHYi9ZxPMTZOzuxNy7bGYMiX/A=
111 |
112 | ansi-styles@^3.2.1:
113 | version "3.2.1"
114 | resolved "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.1.tgz?cache=0&sync_timestamp=1611326384145&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
115 | integrity sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=
116 | dependencies:
117 | color-convert "^1.9.0"
118 |
119 | anymatch@~3.1.1:
120 | version "3.1.1"
121 | resolved "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
122 | integrity sha1-xV7PAhheJGklk5kxDBc84xIzsUI=
123 | dependencies:
124 | normalize-path "^3.0.0"
125 | picomatch "^2.0.4"
126 |
127 | async-validator@^3.4.0:
128 | version "3.5.1"
129 | resolved "https://registry.npm.taobao.org/async-validator/download/async-validator-3.5.1.tgz?cache=0&sync_timestamp=1605751798748&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fasync-validator%2Fdownload%2Fasync-validator-3.5.1.tgz#cd62b9688b2465f48420e27adb47760ab1b5559f"
130 | integrity sha1-zWK5aIskZfSEIOJ620d2CrG1VZ8=
131 |
132 | big.js@^5.2.2:
133 | version "5.2.2"
134 | resolved "https://registry.npm.taobao.org/big.js/download/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
135 | integrity sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=
136 |
137 | binary-extensions@^2.0.0:
138 | version "2.2.0"
139 | resolved "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
140 | integrity sha1-dfUC7q+f/eQvyYgpZFvk6na9ni0=
141 |
142 | bluebird@^3.7.2:
143 | version "3.7.2"
144 | resolved "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
145 | integrity sha1-nyKcFb4nJFT/qXOs4NvueaGww28=
146 |
147 | braces@~3.0.2:
148 | version "3.0.2"
149 | resolved "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
150 | integrity sha1-NFThpGLujVmeI23zNs2epPiv4Qc=
151 | dependencies:
152 | fill-range "^7.0.1"
153 |
154 | chalk@^2.4.2:
155 | version "2.4.2"
156 | resolved "https://registry.npm.taobao.org/chalk/download/chalk-2.4.2.tgz?cache=0&sync_timestamp=1591687042638&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
157 | integrity sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=
158 | dependencies:
159 | ansi-styles "^3.2.1"
160 | escape-string-regexp "^1.0.5"
161 | supports-color "^5.3.0"
162 |
163 | "chokidar@>=2.0.0 <4.0.0":
164 | version "3.5.1"
165 | resolved "https://registry.npm.taobao.org/chokidar/download/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
166 | integrity sha1-7pznu+vSt59J8wR5nVRo4x4U5oo=
167 | dependencies:
168 | anymatch "~3.1.1"
169 | braces "~3.0.2"
170 | glob-parent "~5.1.0"
171 | is-binary-path "~2.1.0"
172 | is-glob "~4.0.1"
173 | normalize-path "~3.0.0"
174 | readdirp "~3.5.0"
175 | optionalDependencies:
176 | fsevents "~2.3.1"
177 |
178 | color-convert@^1.9.0:
179 | version "1.9.3"
180 | resolved "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
181 | integrity sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=
182 | dependencies:
183 | color-name "1.1.3"
184 |
185 | color-name@1.1.3:
186 | version "1.1.3"
187 | resolved "https://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
188 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
189 |
190 | colorette@^1.2.1:
191 | version "1.2.1"
192 | resolved "https://registry.npm.taobao.org/colorette/download/colorette-1.2.1.tgz?cache=0&sync_timestamp=1593955783467&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcolorette%2Fdownload%2Fcolorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
193 | integrity sha1-TQuSEyXBT6+SYzCGpTbbbolWSxs=
194 |
195 | consolidate@^0.16.0:
196 | version "0.16.0"
197 | resolved "https://registry.npm.taobao.org/consolidate/download/consolidate-0.16.0.tgz?cache=0&sync_timestamp=1599596654038&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconsolidate%2Fdownload%2Fconsolidate-0.16.0.tgz#a11864768930f2f19431660a65906668f5fbdc16"
198 | integrity sha1-oRhkdokw8vGUMWYKZZBmaPX73BY=
199 | dependencies:
200 | bluebird "^3.7.2"
201 |
202 | cssesc@^3.0.0:
203 | version "3.0.0"
204 | resolved "https://registry.npm.taobao.org/cssesc/download/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
205 | integrity sha1-N3QZGZA7hoVl4cCep0dEXNGJg+4=
206 |
207 | csstype@^2.6.8:
208 | version "2.6.15"
209 | resolved "https://registry.npm.taobao.org/csstype/download/csstype-2.6.15.tgz#655901663db1d652f10cb57ac6af5a05972aea1f"
210 | integrity sha1-ZVkBZj2x1lLxDLV6xq9aBZcq6h8=
211 |
212 | dayjs@1.x:
213 | version "1.10.4"
214 | resolved "https://registry.npm.taobao.org/dayjs/download/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2"
215 | integrity sha1-jlRKm4aD9heD9XCYCoqA6vVKseI=
216 |
217 | element-plus@latest:
218 | version "1.0.2-beta.32"
219 | resolved "https://registry.npm.taobao.org/element-plus/download/element-plus-1.0.2-beta.32.tgz#228975cfc2255993ef7ccd90238cea9a707f0742"
220 | integrity sha1-Iol1z8IlWZPvfM2QI4zqmnB/B0I=
221 | dependencies:
222 | "@popperjs/core" "^2.4.4"
223 | async-validator "^3.4.0"
224 | dayjs "1.x"
225 | lodash "^4.17.20"
226 | mitt "^2.1.0"
227 | normalize-wheel "^1.0.1"
228 | resize-observer-polyfill "^1.5.1"
229 |
230 | emojis-list@^3.0.0:
231 | version "3.0.0"
232 | resolved "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
233 | integrity sha1-VXBmIEatKeLpFucariYKvf9Pang=
234 |
235 | esbuild@^0.8.47:
236 | version "0.8.50"
237 | resolved "https://registry.npm.taobao.org/esbuild/download/esbuild-0.8.50.tgz#ebf24fde0cdad1a369789dd6fd7a820b0a01e46c"
238 | integrity sha1-6/JP3gza0aNpeJ3W/XqCCwoB5Gw=
239 |
240 | escape-string-regexp@^1.0.5:
241 | version "1.0.5"
242 | resolved "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
243 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
244 |
245 | estree-walker@^2.0.1:
246 | version "2.0.2"
247 | resolved "https://registry.npm.taobao.org/estree-walker/download/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
248 | integrity sha1-UvAQF4wqTBF6d1fP6UKtt9LaTKw=
249 |
250 | fill-range@^7.0.1:
251 | version "7.0.1"
252 | resolved "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
253 | integrity sha1-GRmmp8df44ssfHflGYU12prN2kA=
254 | dependencies:
255 | to-regex-range "^5.0.1"
256 |
257 | fsevents@~2.3.1:
258 | version "2.3.2"
259 | resolved "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.2.tgz?cache=0&sync_timestamp=1612536546156&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffsevents%2Fdownload%2Ffsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
260 | integrity sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro=
261 |
262 | function-bind@^1.1.1:
263 | version "1.1.1"
264 | resolved "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
265 | integrity sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=
266 |
267 | generic-names@^2.0.1:
268 | version "2.0.1"
269 | resolved "https://registry.npm.taobao.org/generic-names/download/generic-names-2.0.1.tgz#f8a378ead2ccaa7a34f0317b05554832ae41b872"
270 | integrity sha1-+KN46tLMqno08DF7BVVIMq5BuHI=
271 | dependencies:
272 | loader-utils "^1.1.0"
273 |
274 | glob-parent@~5.1.0:
275 | version "5.1.1"
276 | resolved "https://registry.npm.taobao.org/glob-parent/download/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
277 | integrity sha1-tsHvQXxOVmPqSY8cRa+saRa7wik=
278 | dependencies:
279 | is-glob "^4.0.1"
280 |
281 | has-flag@^3.0.0:
282 | version "3.0.0"
283 | resolved "https://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
284 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
285 |
286 | has@^1.0.3:
287 | version "1.0.3"
288 | resolved "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
289 | integrity sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=
290 | dependencies:
291 | function-bind "^1.1.1"
292 |
293 | hash-sum@^2.0.0:
294 | version "2.0.0"
295 | resolved "https://registry.npm.taobao.org/hash-sum/download/hash-sum-2.0.0.tgz#81d01bb5de8ea4a214ad5d6ead1b523460b0b45a"
296 | integrity sha1-gdAbtd6OpKIUrV1urRtSNGCwtFo=
297 |
298 | icss-replace-symbols@^1.1.0:
299 | version "1.1.0"
300 | resolved "https://registry.npm.taobao.org/icss-replace-symbols/download/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
301 | integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=
302 |
303 | icss-utils@^4.0.0, icss-utils@^4.1.1:
304 | version "4.1.1"
305 | resolved "https://registry.npm.taobao.org/icss-utils/download/icss-utils-4.1.1.tgz?cache=0&sync_timestamp=1605801644876&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficss-utils%2Fdownload%2Ficss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467"
306 | integrity sha1-IRcLU3ie4nRHwvR91oMIFAP5pGc=
307 | dependencies:
308 | postcss "^7.0.14"
309 |
310 | indexes-of@^1.0.1:
311 | version "1.0.1"
312 | resolved "https://registry.npm.taobao.org/indexes-of/download/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
313 | integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc=
314 |
315 | is-binary-path@~2.1.0:
316 | version "2.1.0"
317 | resolved "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
318 | integrity sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=
319 | dependencies:
320 | binary-extensions "^2.0.0"
321 |
322 | is-core-module@^2.2.0:
323 | version "2.2.0"
324 | resolved "https://registry.npm.taobao.org/is-core-module/download/is-core-module-2.2.0.tgz?cache=0&sync_timestamp=1606411557629&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-core-module%2Fdownload%2Fis-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
325 | integrity sha1-lwN+89UiJNhRY/VZeytj2a/tmBo=
326 | dependencies:
327 | has "^1.0.3"
328 |
329 | is-extglob@^2.1.1:
330 | version "2.1.1"
331 | resolved "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
332 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
333 |
334 | is-glob@^4.0.1, is-glob@~4.0.1:
335 | version "4.0.1"
336 | resolved "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
337 | integrity sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=
338 | dependencies:
339 | is-extglob "^2.1.1"
340 |
341 | is-number@^7.0.0:
342 | version "7.0.0"
343 | resolved "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
344 | integrity sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=
345 |
346 | json5@^1.0.1:
347 | version "1.0.1"
348 | resolved "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
349 | integrity sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=
350 | dependencies:
351 | minimist "^1.2.0"
352 |
353 | loader-utils@^1.1.0:
354 | version "1.4.0"
355 | resolved "https://registry.npm.taobao.org/loader-utils/download/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
356 | integrity sha1-xXm140yzSxp07cbB+za/o3HVphM=
357 | dependencies:
358 | big.js "^5.2.2"
359 | emojis-list "^3.0.0"
360 | json5 "^1.0.1"
361 |
362 | lodash.camelcase@^4.3.0:
363 | version "4.3.0"
364 | resolved "https://registry.npm.taobao.org/lodash.camelcase/download/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
365 | integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
366 |
367 | lodash@^4.17.19, lodash@^4.17.20:
368 | version "4.17.21"
369 | resolved "https://registry.npm.taobao.org/lodash/download/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
370 | integrity sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw=
371 |
372 | lru-cache@^5.1.1:
373 | version "5.1.1"
374 | resolved "https://registry.npm.taobao.org/lru-cache/download/lru-cache-5.1.1.tgz?cache=0&sync_timestamp=1594427569171&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flru-cache%2Fdownload%2Flru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
375 | integrity sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=
376 | dependencies:
377 | yallist "^3.0.2"
378 |
379 | magic-string@^0.25.7:
380 | version "0.25.7"
381 | resolved "https://registry.npm.taobao.org/magic-string/download/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
382 | integrity sha1-P0l9b9NMZpxnmNy4IfLvMfVEUFE=
383 | dependencies:
384 | sourcemap-codec "^1.4.4"
385 |
386 | merge-source-map@^1.1.0:
387 | version "1.1.0"
388 | resolved "https://registry.npm.taobao.org/merge-source-map/download/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646"
389 | integrity sha1-L93n5gIJOfcJBqaPLXrmheTIxkY=
390 | dependencies:
391 | source-map "^0.6.1"
392 |
393 | minimist@^1.2.0:
394 | version "1.2.5"
395 | resolved "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
396 | integrity sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=
397 |
398 | mitt@^2.1.0:
399 | version "2.1.0"
400 | resolved "https://registry.npm.taobao.org/mitt/download/mitt-2.1.0.tgz?cache=0&sync_timestamp=1594823602623&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmitt%2Fdownload%2Fmitt-2.1.0.tgz#f740577c23176c6205b121b2973514eade1b2230"
401 | integrity sha1-90BXfCMXbGIFsSGylzUU6t4bIjA=
402 |
403 | nanoid@^3.1.20:
404 | version "3.1.20"
405 | resolved "https://registry.npm.taobao.org/nanoid/download/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
406 | integrity sha1-utwmPGsdzxS3HvqoX2q0wdbPx4g=
407 |
408 | normalize-path@^3.0.0, normalize-path@~3.0.0:
409 | version "3.0.0"
410 | resolved "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
411 | integrity sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=
412 |
413 | normalize-wheel@^1.0.1:
414 | version "1.0.1"
415 | resolved "https://registry.npm.taobao.org/normalize-wheel/download/normalize-wheel-1.0.1.tgz#aec886affdb045070d856447df62ecf86146ec45"
416 | integrity sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU=
417 |
418 | path-parse@^1.0.6:
419 | version "1.0.6"
420 | resolved "https://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
421 | integrity sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=
422 |
423 | picomatch@^2.0.4, picomatch@^2.2.1:
424 | version "2.2.2"
425 | resolved "https://registry.npm.taobao.org/picomatch/download/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
426 | integrity sha1-IfMz6ba46v8CRo9RRupAbTRfTa0=
427 |
428 | postcss-modules-extract-imports@^2.0.0:
429 | version "2.0.0"
430 | resolved "https://registry.npm.taobao.org/postcss-modules-extract-imports/download/postcss-modules-extract-imports-2.0.0.tgz?cache=0&sync_timestamp=1602588417522&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-extract-imports%2Fdownload%2Fpostcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e"
431 | integrity sha1-gYcZoa4doyX5gyRGsBE27rSTzX4=
432 | dependencies:
433 | postcss "^7.0.5"
434 |
435 | postcss-modules-local-by-default@^3.0.2:
436 | version "3.0.3"
437 | resolved "https://registry.npm.taobao.org/postcss-modules-local-by-default/download/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0"
438 | integrity sha1-uxTgzHgnnVBNvcv9fgyiiZP/u7A=
439 | dependencies:
440 | icss-utils "^4.1.1"
441 | postcss "^7.0.32"
442 | postcss-selector-parser "^6.0.2"
443 | postcss-value-parser "^4.1.0"
444 |
445 | postcss-modules-scope@^2.2.0:
446 | version "2.2.0"
447 | resolved "https://registry.npm.taobao.org/postcss-modules-scope/download/postcss-modules-scope-2.2.0.tgz?cache=0&sync_timestamp=1602593137586&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules-scope%2Fdownload%2Fpostcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee"
448 | integrity sha1-OFyuATzHdD9afXYC0Qc6iequYu4=
449 | dependencies:
450 | postcss "^7.0.6"
451 | postcss-selector-parser "^6.0.0"
452 |
453 | postcss-modules-values@^3.0.0:
454 | version "3.0.0"
455 | resolved "https://registry.npm.taobao.org/postcss-modules-values/download/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10"
456 | integrity sha1-W1AA1uuuKbQlUwG0o6VFdEI+fxA=
457 | dependencies:
458 | icss-utils "^4.0.0"
459 | postcss "^7.0.6"
460 |
461 | postcss-modules@^3.2.2:
462 | version "3.2.2"
463 | resolved "https://registry.npm.taobao.org/postcss-modules/download/postcss-modules-3.2.2.tgz?cache=0&sync_timestamp=1606644453415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-modules%2Fdownload%2Fpostcss-modules-3.2.2.tgz#ee390de0f9f18e761e1778dfb9be26685c02c51f"
464 | integrity sha1-7jkN4PnxjnYeF3jfub4maFwCxR8=
465 | dependencies:
466 | generic-names "^2.0.1"
467 | icss-replace-symbols "^1.1.0"
468 | lodash.camelcase "^4.3.0"
469 | postcss "^7.0.32"
470 | postcss-modules-extract-imports "^2.0.0"
471 | postcss-modules-local-by-default "^3.0.2"
472 | postcss-modules-scope "^2.2.0"
473 | postcss-modules-values "^3.0.0"
474 | string-hash "^1.1.1"
475 |
476 | postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4:
477 | version "6.0.4"
478 | resolved "https://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-6.0.4.tgz?cache=0&sync_timestamp=1601045323543&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpostcss-selector-parser%2Fdownload%2Fpostcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3"
479 | integrity sha1-VgdaE4CgRgTDiwY+p3Z6Epr1wrM=
480 | dependencies:
481 | cssesc "^3.0.0"
482 | indexes-of "^1.0.1"
483 | uniq "^1.0.1"
484 | util-deprecate "^1.0.2"
485 |
486 | postcss-value-parser@^4.1.0:
487 | version "4.1.0"
488 | resolved "https://registry.npm.taobao.org/postcss-value-parser/download/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
489 | integrity sha1-RD9qIM7WSBor2k+oUypuVdeJoss=
490 |
491 | postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
492 | version "7.0.35"
493 | resolved "https://registry.npm.taobao.org/postcss/download/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24"
494 | integrity sha1-0r4AuZj38hHYonaXQHny6SuXDiQ=
495 | dependencies:
496 | chalk "^2.4.2"
497 | source-map "^0.6.1"
498 | supports-color "^6.1.0"
499 |
500 | postcss@^8.2.1:
501 | version "8.2.6"
502 | resolved "https://registry.npm.taobao.org/postcss/download/postcss-8.2.6.tgz#5d69a974543b45f87e464bc4c3e392a97d6be9fe"
503 | integrity sha1-XWmpdFQ7Rfh+RkvEw+OSqX1r6f4=
504 | dependencies:
505 | colorette "^1.2.1"
506 | nanoid "^3.1.20"
507 | source-map "^0.6.1"
508 |
509 | readdirp@~3.5.0:
510 | version "3.5.0"
511 | resolved "https://registry.npm.taobao.org/readdirp/download/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
512 | integrity sha1-m6dMAZsV02UnjS6Ru4xI17TULJ4=
513 | dependencies:
514 | picomatch "^2.2.1"
515 |
516 | resize-observer-polyfill@^1.5.1:
517 | version "1.5.1"
518 | resolved "https://registry.npm.taobao.org/resize-observer-polyfill/download/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
519 | integrity sha1-DpAg3T0hAkRY1OvSfiPkAmmBBGQ=
520 |
521 | resolve@^1.19.0:
522 | version "1.20.0"
523 | resolved "https://registry.npm.taobao.org/resolve/download/resolve-1.20.0.tgz?cache=0&sync_timestamp=1613054898763&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
524 | integrity sha1-YpoBP7P3B1XW8LeTXMHCxTeLGXU=
525 | dependencies:
526 | is-core-module "^2.2.0"
527 | path-parse "^1.0.6"
528 |
529 | rollup@^2.38.5:
530 | version "2.39.1"
531 | resolved "https://registry.npm.taobao.org/rollup/download/rollup-2.39.1.tgz#7afd4cefd8a332c5102a8063d301fde1f31a9173"
532 | integrity sha1-ev1M79ijMsUQKoBj0wH94fMakXM=
533 | optionalDependencies:
534 | fsevents "~2.3.1"
535 |
536 | sass@^1.32.8:
537 | version "1.32.8"
538 | resolved "https://registry.npm.taobao.org/sass/download/sass-1.32.8.tgz#f16a9abd8dc530add8834e506878a2808c037bdc"
539 | integrity sha1-8WqavY3FMK3Yg05QaHiigIwDe9w=
540 | dependencies:
541 | chokidar ">=2.0.0 <4.0.0"
542 |
543 | source-map@^0.6.1:
544 | version "0.6.1"
545 | resolved "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz?cache=0&sync_timestamp=1604409581245&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map%2Fdownload%2Fsource-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
546 | integrity sha1-dHIq8y6WFOnCh6jQu95IteLxomM=
547 |
548 | sourcemap-codec@^1.4.4:
549 | version "1.4.8"
550 | resolved "https://registry.npm.taobao.org/sourcemap-codec/download/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
551 | integrity sha1-6oBL2UhXQC5pktBaOO8a41qatMQ=
552 |
553 | string-hash@^1.1.1:
554 | version "1.1.3"
555 | resolved "https://registry.npm.taobao.org/string-hash/download/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
556 | integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=
557 |
558 | supports-color@^5.3.0:
559 | version "5.5.0"
560 | resolved "https://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz?cache=0&sync_timestamp=1611394404603&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
561 | integrity sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=
562 | dependencies:
563 | has-flag "^3.0.0"
564 |
565 | supports-color@^6.1.0:
566 | version "6.1.0"
567 | resolved "https://registry.npm.taobao.org/supports-color/download/supports-color-6.1.0.tgz?cache=0&sync_timestamp=1611394404603&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
568 | integrity sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=
569 | dependencies:
570 | has-flag "^3.0.0"
571 |
572 | to-fast-properties@^2.0.0:
573 | version "2.0.0"
574 | resolved "https://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-2.0.0.tgz?cache=0&sync_timestamp=1580550296062&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fto-fast-properties%2Fdownload%2Fto-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
575 | integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
576 |
577 | to-regex-range@^5.0.1:
578 | version "5.0.1"
579 | resolved "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
580 | integrity sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=
581 | dependencies:
582 | is-number "^7.0.0"
583 |
584 | uniq@^1.0.1:
585 | version "1.0.1"
586 | resolved "https://registry.npm.taobao.org/uniq/download/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
587 | integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=
588 |
589 | util-deprecate@^1.0.2:
590 | version "1.0.2"
591 | resolved "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
592 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
593 |
594 | vite@^2.0.0-beta.12:
595 | version "2.0.2"
596 | resolved "https://registry.npm.taobao.org/vite/download/vite-2.0.2.tgz#d984528b5a1c8e725d2804245751769b11d671cf"
597 | integrity sha1-2YRSi1ocjnJdKAQkV1F2mxHWcc8=
598 | dependencies:
599 | esbuild "^0.8.47"
600 | postcss "^8.2.1"
601 | resolve "^1.19.0"
602 | rollup "^2.38.5"
603 | optionalDependencies:
604 | fsevents "~2.3.1"
605 |
606 | vue@^3.0.5:
607 | version "3.0.5"
608 | resolved "https://registry.npm.taobao.org/vue/download/vue-3.0.5.tgz?cache=0&sync_timestamp=1609359858533&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-3.0.5.tgz#de1b82eba24abfe71e0970fc9b8d4b2babdc3fe1"
609 | integrity sha1-3huC66JKv+ceCXD8m41LK6vcP+E=
610 | dependencies:
611 | "@vue/compiler-dom" "3.0.5"
612 | "@vue/runtime-dom" "3.0.5"
613 | "@vue/shared" "3.0.5"
614 |
615 | vuex@^4.0.0:
616 | version "4.0.0"
617 | resolved "https://registry.npm.taobao.org/vuex/download/vuex-4.0.0.tgz?cache=0&sync_timestamp=1612277435391&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvuex%2Fdownload%2Fvuex-4.0.0.tgz#ac877aa76a9c45368c979471e461b520d38e6cf5"
618 | integrity sha1-rId6p2qcRTaMl5Rx5GG1INOObPU=
619 |
620 | yallist@^3.0.2:
621 | version "3.1.1"
622 | resolved "https://registry.npm.taobao.org/yallist/download/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
623 | integrity sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=
624 |
--------------------------------------------------------------------------------