├── .dockerignore
├── .github
└── workflows
│ └── docker-image.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.en-US.md
├── README.md
├── api
├── auth.go
├── clients.go
├── mentu.go
├── node.go
├── sub.go
├── template.go
└── user.go
├── build.sh
├── demo.sh
├── docker-compose.yml
├── go.mod
├── go.sum
├── install.sh
├── main.go
├── menu.sh
├── middlewares
├── ip.go
└── jwt.go
├── models
├── config.go
├── iplogs.go
├── node.go
├── sqlite.go
├── subcription.go
└── user.go
├── node
├── clash.go
├── common.go
├── hy.go
├── hy2.go
├── ss.go
├── ss_test.go
├── ssr.go
├── surge.go
├── trojan.go
├── tuic.go
├── vless.go
└── vmess.go
├── routers
├── clients.go
├── index.go
├── menus.go
├── node.go
├── subcription.go
├── template.go
├── total.go
├── user.go
└── version.go
├── settings
└── user.go
├── static
├── avatar.gif
├── css
│ ├── 401.Vp_sG7yN.css
│ ├── 404.Bs5Vzklw.css
│ ├── BarChart.ulyVC4La.css
│ ├── apifox.CCvSwCIK.css
│ ├── el-alert.B9oGCRyi.css
│ ├── el-card.fwQOLwdi.css
│ ├── el-col.Ds2mGN2S.css
│ ├── el-dialog.DCGCHX2q.css
│ ├── el-form-item.uSAh9oyp.css
│ ├── el-image-viewer.BJ_nFYFt.css
│ ├── el-link.Dkj8bMmD.css
│ ├── el-popper.DG5wR-qi.css
│ ├── el-scrollbar.BWxh-h6K.css
│ ├── el-select.BaQA8IKP.css
│ ├── el-switch.CG96k8Rh.css
│ ├── el-table-column.BfJ1jZWA.css
│ ├── el-tabs.BURcj4qt.css
│ ├── el-tag.DljBBxJR.css
│ ├── icon-selector.CD4iaxzs.css
│ ├── icons.CBhJQ2Ib.css
│ ├── index.B4dlp3f2.css
│ ├── index.Byi5FQj0.css
│ ├── index.CJKN3zBj.css
│ ├── index.DZhVAj3G.css
│ ├── index.Dwigi1cb.css
│ ├── internal-doc.BdNudHKe.css
│ ├── knife4j.DRg4vOS3.css
│ ├── node.wSVBx8Lp.css
│ ├── nodes.DzJW8z5F.css
│ ├── set.BMjHnBvk.css
│ ├── signature.C8sJe9y0.css
│ ├── subs.JwB3fIbV.css
│ ├── swagger.eJ-qo84r.css
│ ├── template.DpE-mm8O.css
│ ├── upload.DT6Y7CcD.css
│ ├── wang-editor.nHDhGvq6.css
│ └── websocket.BZkLAsTH.css
├── favicon.ico
├── img
│ ├── 401.DaBJYOxp.gif
│ ├── 404.D6_y3Jr2.png
│ ├── login-bg-dark.BfPFE40x.jpg
│ ├── login-bg.CKlK6emc.jpg
│ └── logo.D7mmbp4F.png
├── index.html
└── js
│ ├── 401.2cRCE_5G.js
│ ├── 404.DlqBpkU7.js
│ ├── BarChart.BhtXtCgr.js
│ ├── FunnelChart.L2tIbyMX.js
│ ├── PieChart.mgwtBU-p.js
│ ├── RadarChart.TGxAW552.js
│ ├── _initCloneObject.cf8iq1wq.js
│ ├── _plugin-vue_export-helper.BCo6x5W8.js
│ ├── api.B2FJMEEY.js
│ ├── apifox.IXUmMSaC.js
│ ├── captcha.KixZeTLs.js
│ ├── cascader.Bxy7lIuJ.js
│ ├── castArray.BN0gQOTw.js
│ ├── client.fwafuIJ_.js
│ ├── close.3A3CTE27.js
│ ├── close_all.CpAPdWg9.js
│ ├── close_left.FPCWsnfT.js
│ ├── close_other.CtMgS35C.js
│ ├── close_right.WYLOaSAD.js
│ ├── debounce.i1DMUZzi.js
│ ├── dict.B6ktMwQ2.js
│ ├── dict.BlxtrVRf.js
│ ├── document.DqID0E9P.js
│ ├── download.BcBrriOr.js
│ ├── dropdown.CqG_2FXV.js
│ ├── edit.D3u4lddN.js
│ ├── el-alert.IAJrxUBM.js
│ ├── el-card.DWbysKpS.js
│ ├── el-col.DNKSa6YX.js
│ ├── el-dialog.Dis4ipFy.js
│ ├── el-form-item.UpoTeuOf.js
│ ├── el-image-viewer.Ck07Xbtu.js
│ ├── el-link.BTv-HaC_.js
│ ├── el-popper.e9kr8u9Q.js
│ ├── el-scrollbar.DlPh6Z7D.js
│ ├── el-select.dUFpYm6H.js
│ ├── el-switch.zYake_dz.js
│ ├── el-table-column.haX2jq5s.js
│ ├── el-tabs.DDmXOrX8.js
│ ├── el-tag.CLWce1kX.js
│ ├── el-tooltip.l0sNRNKZ.js
│ ├── eye-open.CM4cKp-R.js
│ ├── eye.DqRz4sMZ.js
│ ├── fullscreen-exit.DXwCcaMo.js
│ ├── fullscreen.dczNRBeD.js
│ ├── github.DLO2QQQy.js
│ ├── homepage.BcyYp1IG.js
│ ├── icon-selector.B8xqxj5a.js
│ ├── icons.DgB57Xkx.js
│ ├── indent-decrease.ROHmwAah.js
│ ├── index.9PHSMUIB.js
│ ├── index.9UoVjQ1v.js
│ ├── index.B2Hg7VBR.js
│ ├── index.BBNS_uLM.js
│ ├── index.BfcEpzPY.js
│ ├── index.BrHL87wj.js
│ ├── index.CM09xEA_.js
│ ├── index.D6nSmJHY.js
│ ├── index.D7zGuEZp.js
│ ├── index.DNYq9Wso.js
│ ├── internal-doc.B6eN2GGk.js
│ ├── ip.CWc5zJw-.js
│ ├── isEqual.DDyRMzJ4.js
│ ├── isUndefined.DgmxjSXK.js
│ ├── knife4j.C3XegEf8.js
│ ├── language.k0ZPy50U.js
│ ├── level1.DbJgCAxV.js
│ ├── level2.CXm5yCsd.js
│ ├── level3-1.veb2CjDd.js
│ ├── level3-2.ehpMX2NG.js
│ ├── link.BEFJAS5U.js
│ ├── lock.CY-ba69F.js
│ ├── menu.CSAxtYMZ.js
│ ├── message.DnO64dGf.js
│ ├── money.eznkHcT4.js
│ ├── monitor.Cm5WDh5_.js
│ ├── moon.BACaCO3C.js
│ ├── node.B7CBv-vw.js
│ ├── nodes.BvTKFj9V.js
│ ├── order.BSEhtWEN.js
│ ├── peoples.B_DDm2CM.js
│ ├── position.CopxYfyp.js
│ ├── project.BeKcDOO0.js
│ ├── publish.B4gIpoLD.js
│ ├── refresh.B5ExwFoE.js
│ ├── refs.CNClepWF.js
│ ├── role.DDpGZwDf.js
│ ├── security.CPhpJrut.js
│ ├── set.DCph2DiX.js
│ ├── setting.CfydkD5J.js
│ ├── signature.5Hv-l5jE.js
│ ├── size.C48ZYpz_.js
│ ├── strings.CQ_np2th.js
│ ├── subs.1dXoageE.js
│ ├── sunny.Cx4iEVwd.js
│ ├── swagger.BGskywol.js
│ ├── system.BjyKXCM4.js
│ ├── table.C6Xt0YCE.js
│ ├── temp.gJIG3-Be.js
│ ├── template.iDasYWHy.js
│ ├── todolist.CQls5pqo.js
│ ├── tree.ByH7Oq4A.js
│ ├── upload.DkIgLQ_p.js
│ ├── use-dialog.CybRpRek.js
│ ├── user.m7vGTRps.js
│ ├── visit.BtczcFYa.js
│ ├── wang-editor.CovtB-Ke.js
│ └── websocket.YJwVKVlt.js
├── template
├── clash.yaml
└── surge.conf
├── utils
├── capatcha.go
├── log.go
├── menus.go
└── mkdir.go
└── webs
├── .editorconfig
├── .env.development
├── .env.production
├── .eslintignore
├── .eslintrc-auto-import.json
├── .eslintrc.cjs
├── .gitignore
├── .husky
├── commit-msg
└── pre-commit
├── .prettierignore
├── .prettierrc.cjs
├── .stylelintignore
├── .stylelintrc.cjs
├── .vscode
├── extensions.json
├── settings.json
├── vue3.0.code-snippets
├── vue3.2.code-snippets
└── vue3.3.code-snippets
├── CHANGELOG.md
├── LICENSE
├── commitlint.config.cjs
├── index.html
├── licenses
├── vue-element-admin
│ └── LICENSE
└── vue3-element-admin
│ └── LICENSE
├── mock
├── auth.mock.ts
├── base.ts
├── dept.mock.ts
├── dict.mock.ts
├── menu.mock.ts
├── role.mock.ts
└── user.mock.ts
├── package.json
├── public
├── avatar.gif
└── favicon.ico
├── src
├── App.vue
├── api
│ ├── auth
│ │ ├── index.ts
│ │ └── types.ts
│ ├── dept
│ │ ├── index.ts
│ │ └── types.ts
│ ├── dict
│ │ ├── index.ts
│ │ └── types.ts
│ ├── file
│ │ ├── index.ts
│ │ └── types.ts
│ ├── menu
│ │ ├── index.ts
│ │ └── types.ts
│ ├── role
│ │ ├── index.ts
│ │ └── types.ts
│ ├── subcription
│ │ ├── node.ts
│ │ ├── subs.ts
│ │ └── temp.ts
│ ├── total
│ │ └── index.ts
│ └── user
│ │ ├── index.ts
│ │ └── types.ts
├── assets
│ ├── 1.png
│ ├── 2.png
│ ├── icons
│ │ ├── api.svg
│ │ ├── captcha.svg
│ │ ├── cascader.svg
│ │ ├── client.svg
│ │ ├── close.svg
│ │ ├── close_all.svg
│ │ ├── close_left.svg
│ │ ├── close_other.svg
│ │ ├── close_right.svg
│ │ ├── dict.svg
│ │ ├── document.svg
│ │ ├── download.svg
│ │ ├── edit.svg
│ │ ├── eye-open.svg
│ │ ├── eye.svg
│ │ ├── fullscreen-exit.svg
│ │ ├── fullscreen.svg
│ │ ├── github.svg
│ │ ├── homepage.svg
│ │ ├── indent-decrease.svg
│ │ ├── ip.svg
│ │ ├── language.svg
│ │ ├── link.svg
│ │ ├── lock.svg
│ │ ├── menu.svg
│ │ ├── message.svg
│ │ ├── money.svg
│ │ ├── monitor.svg
│ │ ├── moon.svg
│ │ ├── order.svg
│ │ ├── peoples.svg
│ │ ├── project.svg
│ │ ├── publish.svg
│ │ ├── refresh.svg
│ │ ├── role.svg
│ │ ├── security.svg
│ │ ├── setting.svg
│ │ ├── size.svg
│ │ ├── sunny.svg
│ │ ├── system.svg
│ │ ├── table.svg
│ │ ├── todolist.svg
│ │ ├── tree.svg
│ │ ├── user.svg
│ │ └── visit.svg
│ ├── images
│ │ ├── 401.gif
│ │ ├── 404.png
│ │ ├── 404_cloud.png
│ │ ├── login-bg-dark.jpg
│ │ └── login-bg.jpg
│ └── logo.png
├── components
│ ├── AppLink
│ │ └── index.vue
│ ├── Breadcrumb
│ │ └── index.vue
│ ├── Dictionary
│ │ └── index.vue
│ ├── GithubCorner
│ │ └── index.vue
│ ├── Hamburger
│ │ └── index.vue
│ ├── IconSelect
│ │ └── index.vue
│ ├── LangSelect
│ │ └── index.vue
│ ├── Pagination
│ │ └── index.vue
│ ├── SizeSelect
│ │ └── index.vue
│ ├── SvgIcon
│ │ └── index.vue
│ ├── Upload
│ │ ├── MultiUpload.vue
│ │ └── SingleUpload.vue
│ └── WangEditor
│ │ └── index.vue
├── directive
│ ├── index.ts
│ └── permission
│ │ └── index.ts
├── enums
│ ├── DeviceEnum.ts
│ ├── LanguageEnum.ts
│ ├── LayoutEnum.ts
│ ├── MenuTypeEnum.ts
│ ├── SidebarStatusEnum.ts
│ ├── SizeEnum.ts
│ └── ThemeEnum.ts
├── lang
│ ├── index.ts
│ └── package
│ │ ├── en.ts
│ │ └── zh-cn.ts
├── layout
│ ├── components
│ │ ├── AppMain
│ │ │ └── index.vue
│ │ ├── NavBar
│ │ │ ├── components
│ │ │ │ ├── NavbarLeft.vue
│ │ │ │ └── NavbarRight.vue
│ │ │ └── index.vue
│ │ ├── Settings
│ │ │ ├── components
│ │ │ │ ├── LayoutSelect.vue
│ │ │ │ └── ThemeColorPicker.vue
│ │ │ └── index.vue
│ │ ├── Sidebar
│ │ │ ├── components
│ │ │ │ ├── SidebarLogo.vue
│ │ │ │ ├── SidebarMenu.vue
│ │ │ │ ├── SidebarMenuItem.vue
│ │ │ │ ├── SidebarMenuItemTitle.vue
│ │ │ │ └── SidebarMixTopMenu.vue
│ │ │ └── index.vue
│ │ └── TagsView
│ │ │ └── index.vue
│ └── index.vue
├── main.ts
├── plugins
│ ├── i18n.ts
│ ├── icons.ts
│ ├── index.ts
│ └── permission.ts
├── router
│ └── index.ts
├── settings.ts
├── store
│ ├── index.ts
│ └── modules
│ │ ├── app.ts
│ │ ├── permission.ts
│ │ ├── settings.ts
│ │ ├── tagsView.ts
│ │ └── user.ts
├── styles
│ ├── index.scss
│ ├── reset.scss
│ ├── variables.module.scss
│ └── variables.scss
├── typings
│ ├── auto-imports.d.ts
│ ├── components.d.ts
│ ├── env.d.ts
│ ├── global.d.ts
│ ├── router.d.ts
│ └── shims-vue.d.ts
├── utils
│ ├── color.ts
│ ├── i18n.ts
│ ├── index.ts
│ ├── nprogress.ts
│ └── request.ts
└── views
│ ├── dashboard
│ ├── components
│ │ ├── BarChart.vue
│ │ ├── FunnelChart.vue
│ │ ├── PieChart.vue
│ │ └── RadarChart.vue
│ └── index.vue
│ ├── demo
│ ├── api
│ │ ├── apifox.vue
│ │ ├── knife4j.vue
│ │ └── swagger.vue
│ ├── dict.vue
│ ├── icon-selector.vue
│ ├── icons.vue
│ ├── internal-doc.vue
│ ├── multi-level
│ │ ├── children
│ │ │ ├── children
│ │ │ │ ├── level3-1.vue
│ │ │ │ └── level3-2.vue
│ │ │ └── level2.vue
│ │ └── level1.vue
│ ├── signature.vue
│ ├── upload.vue
│ ├── wang-editor.vue
│ └── websocket.vue
│ ├── error-page
│ ├── 401.vue
│ └── 404.vue
│ ├── login
│ └── index.vue
│ ├── redirect
│ └── index.vue
│ ├── subcription
│ ├── nodes.vue
│ ├── subs.vue
│ └── template.vue
│ └── system
│ └── user
│ └── set.vue
├── tsconfig.json
├── uno.config.ts
└── vite.config.ts
/.dockerignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.DS_Store
3 | db
4 | logs
5 | webs
6 | README.md
7 | README.en-US.md
8 | *.sh
9 | sublink_amd64
10 | sublink_arm64
11 | sublink.exe
12 | install.sh
13 |
--------------------------------------------------------------------------------
/.github/workflows/docker-image.yml:
--------------------------------------------------------------------------------
1 | name: Build and Push Multi-Arch Docker Image
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | # 检出代码
17 | - name: Checkout code
18 | uses: actions/checkout@v2
19 |
20 | # 设置 QEMU 以支持跨架构构建
21 | - name: Set up QEMU
22 | uses: docker/setup-qemu-action@v2
23 |
24 | # 设置 Docker Buildx
25 | - name: Set up Docker Buildx
26 | uses: docker/setup-buildx-action@v2
27 |
28 | # 登录到 Docker Hub
29 | - name: Log in to Docker Hub
30 | uses: docker/login-action@v2
31 | with:
32 | username: ${{ secrets.DOCKER_USERNAME }}
33 | password: ${{ secrets.DOCKER_PASSWORD }}
34 |
35 | # 构建并推送多平台 Docker 镜像
36 | - name: Build and Push Multi-Arch Docker Image
37 | run: |
38 | docker buildx build --platform linux/amd64,linux/arm64 \
39 | -t jaaksi/sublinkx:latest \
40 | --push .
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.DS_Store
3 | db
4 | logs
5 | sublink_amd64
6 | sublink_arm64
7 | sublink.exe
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage
2 | FROM golang:1.22.2-alpine AS builder
3 | WORKDIR /app
4 | COPY . .
5 | RUN go mod download
6 | RUN go build -o sublinkX
7 |
8 | # Final stage
9 | FROM alpine:latest
10 | WORKDIR /app
11 |
12 | # 设置时区为 Asia/Shanghai
13 | ENV TZ=Asia/Shanghai
14 |
15 | # 部分环境需要手动创建目录
16 | RUN mkdir -p /app/db /app/logs /app/template && chmod 777 /app/db /app/logs /app/template
17 |
18 | COPY --from=builder /app/sublinkX /app/sublinkX
19 | EXPOSE 8000
20 | CMD ["/app/sublinkX"]
21 |
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024-SublinkX
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 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o sublink_amd64 main.go
2 | GOOS=linux GOARCH=arm64 go build -ldflags="-w -s" -o sublink_arm64 main.go
--------------------------------------------------------------------------------
/demo.sh:
--------------------------------------------------------------------------------
1 | cd G:\sublinkX\sublinkX
2 | red=$(go run main.go --version)
3 | echo "版本号:$red"
4 | read -p "回车"
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.8' # 使用 Docker Compose 文件的版本
2 |
3 | services:
4 | sublink:
5 | build:
6 | context: . # 指定 Dockerfile 的上下文(当前目录)
7 | dockerfile: Dockerfile # 指定 Dockerfile 的名称,如果是默认的 "Dockerfile",可以省略此行
8 | ports:
9 | - "8000:8000" # 将容器的 8000 端口映射到主机的 8000 端口
10 | volumes:
11 | - .:/app # 将当前目录挂载到容器的 /app 目录,便于开发时实时更新
12 | environment:
13 | - ENV_VAR_NAME=value # 可选,您可以在此处设置其他环境变量
14 | - TZ=Asia/Shanghai # 设置时区为 Asia/Shanghai
15 | restart: unless-stopped # 设置容器重启策略
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 检查用户是否为root
3 | if [ "$(id -u)" != "0" ]; then
4 | echo -e "${RED}该脚本必须以root身份运行。${NC}"
5 | exit 1
6 | fi
7 |
8 | # 创建一个程序目录
9 | INSTALL_DIR="/usr/local/bin/sublink"
10 |
11 | if [ ! -d "$INSTALL_DIR" ]; then
12 | mkdir -p "$INSTALL_DIR"
13 | fi
14 |
15 | # 获取最新的发行版标签
16 | latest_release=$(curl --silent "https://api.github.com/repos/gooaclok819/sublinkX/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
17 | echo "最新版本: $latest_release"
18 |
19 | # 检测机器类型
20 | machine_type=$(uname -m)
21 |
22 | if [ "$machine_type" = "x86_64" ]; then
23 | file_name="sublink_amd64"
24 | elif [ "$machine_type" = "aarch64" ]; then
25 | file_name="sublink_arm64"
26 | else
27 | echo "不支持的机器类型: $machine_type"
28 | exit 1
29 | fi
30 |
31 | # 下载文件
32 | cd ~
33 | curl -LO "https://github.com/gooaclok819/sublinkX/releases/download/$latest_release/$file_name"
34 |
35 | # 设置文件为可执行
36 | chmod +x $file_name
37 |
38 | # 移动文件到指定目录
39 | mv $file_name "$INSTALL_DIR/sublink"
40 |
41 | # 创建systemctl服务
42 | echo "[Unit]
43 | Description=Sublink Service
44 |
45 | [Service]
46 | ExecStart=$INSTALL_DIR/sublink
47 | WorkingDirectory=$INSTALL_DIR
48 | [Install]
49 | WantedBy=multi-user.target" | tee /etc/systemd/system/sublink.service
50 |
51 | # 重新加载systemd守护进程
52 | systemctl daemon-reload
53 |
54 | # 启动并启用服务
55 | systemctl start sublink
56 | systemctl enable sublink
57 | echo "服务已启动并已设置为开机启动"
58 | echo "默认账号admin密码123456 默认端口8000"
59 | echo "安装完成已经启动输入sublink可以呼出菜单"
60 |
61 |
62 | # 下载menu.sh并设置权限
63 | curl -o /usr/bin/sublink -H "Cache-Control: no-cache" -H "Pragma: no-cache" https://raw.githubusercontent.com/gooaclok819/sublinkX/main/menu.sh
64 | chmod 755 "/usr/bin/sublink"
65 |
--------------------------------------------------------------------------------
/middlewares/ip.go:
--------------------------------------------------------------------------------
1 | package middlewares
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "io"
7 | "log"
8 | "net/http"
9 | "sublink/models"
10 | "time"
11 |
12 | "github.com/gin-gonic/gin"
13 | "golang.org/x/text/encoding/simplifiedchinese"
14 | )
15 |
16 | func GetIp(c *gin.Context) {
17 | c.Next()
18 | func() {
19 | subname, _ := c.Get("subname")
20 |
21 | ip := c.ClientIP()
22 | resp, err := http.Get(fmt.Sprintf("https://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true", ip))
23 | if err != nil {
24 | log.Println(err)
25 | return
26 | }
27 | defer resp.Body.Close()
28 | body, _ := io.ReadAll(resp.Body)
29 | utf8Body, _ := simplifiedchinese.GBK.NewDecoder().Bytes(body)
30 | type IpInfo struct {
31 | Addr string `json:"addr"`
32 | Ip string `json:"ip"`
33 | }
34 | ipinfo := IpInfo{}
35 | err = json.Unmarshal(utf8Body, &ipinfo)
36 | if err != nil {
37 | log.Println(err)
38 | return
39 | }
40 | var sub models.Subcription
41 | if subname, ok := subname.(string); ok {
42 | sub.Name = subname
43 | }
44 | err = sub.Find()
45 | if err != nil {
46 | log.Println(err)
47 | return
48 | }
49 | var iplog models.SubLogs
50 | iplog.IP = ip
51 | err = iplog.Find(sub.ID)
52 | // 如果没有找到记录
53 | if err != nil {
54 | iploga := []models.SubLogs{
55 | {IP: ip,
56 | Addr: ipinfo.Addr,
57 | SubcriptionID: sub.ID,
58 | Date: time.Now().Format("2006-01-02 15:04:05"),
59 | Count: 1,
60 | },
61 | }
62 | sub.SubLogs = iploga
63 | err = sub.Update()
64 | if err != nil {
65 | log.Println(err)
66 | return
67 | }
68 | } else {
69 | // 更新访问次数
70 | iplog.Count++
71 | iplog.Date = time.Now().Format("2006-01-02 15:04:05")
72 | err = iplog.Update()
73 | if err != nil {
74 | log.Println(err)
75 | return
76 | }
77 | }
78 | }()
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/middlewares/jwt.go:
--------------------------------------------------------------------------------
1 | package middlewares
2 |
3 | import (
4 | "errors"
5 | "net/http"
6 | "strings"
7 |
8 | "github.com/dgrijalva/jwt-go"
9 | "github.com/gin-gonic/gin"
10 | )
11 |
12 | var Secret = []byte("sublink") // 秘钥
13 |
14 | // JwtClaims jwt声明
15 | type JwtClaims struct {
16 | Username string `json:"username"`
17 | jwt.StandardClaims
18 | }
19 |
20 | // AuthorToken 验证token中间件
21 | func AuthorToken(c *gin.Context) {
22 | // 定义白名单
23 | list := []string{"/static", "/api/v1/auth/login", "/api/v1/auth/captcha", "/c/", "/api/v1/version"}
24 | // 如果是首页直接跳过
25 | if c.Request.URL.Path == "/" {
26 | c.Next()
27 | return
28 | }
29 | // 如果是白名单直接跳过
30 | for _, v := range list {
31 | if strings.HasPrefix(c.Request.URL.Path, v) {
32 | c.Next()
33 | return
34 | }
35 | }
36 | token := c.Request.Header.Get("Authorization")
37 | if token == "" {
38 | c.JSON(400, gin.H{"msg": "请求未携带token"})
39 | c.Abort()
40 | return
41 | }
42 | parts := strings.Split(token, ".")
43 | if len(parts) != 3 {
44 | c.JSON(400, gin.H{"msg": "token格式错误"})
45 | c.Abort()
46 | return
47 | }
48 | // 去掉Bearer前缀
49 | token = strings.Replace(token, "Bearer ", "", -1)
50 | mc, err := ParseToken(token)
51 | if err != nil {
52 | c.JSON(http.StatusUnauthorized, gin.H{
53 | "code": 401,
54 | "msg": err.Error(),
55 | })
56 | c.Abort()
57 | return
58 | }
59 | c.Set("username", mc.Username)
60 | c.Next()
61 | }
62 |
63 | // ParseToken 解析JWT
64 | func ParseToken(tokenString string) (*JwtClaims, error) {
65 | // 解析token
66 | token, err := jwt.ParseWithClaims(tokenString, &JwtClaims{}, func(token *jwt.Token) (i interface{}, err error) {
67 | return Secret, nil
68 | })
69 | if err != nil {
70 | return nil, err
71 | }
72 | if claims, ok := token.Claims.(*JwtClaims); ok && token.Valid { // 校验token
73 | return claims, nil
74 | }
75 | return nil, errors.New("invalid token")
76 | }
77 |
--------------------------------------------------------------------------------
/models/config.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | type Config struct {
4 | ID int
5 | Key string
6 | Value string
7 | }
8 |
--------------------------------------------------------------------------------
/models/iplogs.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | type SubLogs struct {
4 | ID int
5 | IP string
6 | Date string
7 | Addr string
8 | Count int
9 | SubcriptionID int
10 | }
11 |
12 | // Add 添加IP
13 | func (iplog *SubLogs) Add() error {
14 | return DB.Create(iplog).Error
15 | }
16 |
17 | // 查找IP
18 | func (iplog *SubLogs) Find(id int) error {
19 | return DB.Where("ip = ? and subcription_id = ?", iplog.IP, id).First(iplog).Error
20 | }
21 |
22 | // Update 更新IP
23 | func (iplog *SubLogs) Update() error {
24 | return DB.Where("id = ? or ip = ?", iplog.ID, iplog.IP).Updates(iplog).Error
25 | }
26 |
27 | // List 获取IP列表
28 | func (iplog *SubLogs) List() ([]SubLogs, error) {
29 | var iplogs []SubLogs
30 | err := DB.Find(&iplogs).Error
31 | if err != nil {
32 | return nil, err
33 | }
34 | return iplogs, nil
35 | }
36 |
37 | // Del 删除IP
38 | func (iplog *SubLogs) Del() error {
39 | return DB.Delete(iplog).Error
40 | }
41 |
--------------------------------------------------------------------------------
/models/node.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | type Node struct {
4 | ID int
5 | Link string
6 | Name string
7 | CreateDate string
8 | }
9 |
10 | // Add 添加节点
11 | func (node *Node) Add() error {
12 | return DB.Create(node).Error
13 | }
14 |
15 | // 更新节点
16 | func (node *Node) Update() error {
17 | return DB.Model(node).Updates(node).Error
18 | }
19 |
20 | // 查找节点是否重复
21 | func (node *Node) Find() error {
22 | return DB.Where("link = ? or name = ?", node.Link, node.Name).First(node).Error
23 | }
24 |
25 | // 节点列表
26 | func (node *Node) List() ([]Node, error) {
27 | var nodes []Node
28 | err := DB.Find(&nodes).Error
29 | if err != nil {
30 | return nil, err
31 | }
32 | return nodes, nil
33 | }
34 |
35 | // 删除节点
36 | func (node *Node) Del() error {
37 | return DB.Delete(node).Error
38 | }
39 |
--------------------------------------------------------------------------------
/models/sqlite.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | "log"
5 | "os"
6 |
7 | "github.com/glebarez/sqlite"
8 | "gorm.io/gorm"
9 | )
10 |
11 | var DB *gorm.DB
12 | var isInitialized bool
13 |
14 | func InitSqlite() {
15 | // 检查目录是否创建
16 | _, err := os.Stat("./db")
17 | if err != nil {
18 | if os.IsNotExist(err) {
19 | os.Mkdir("./db", os.ModePerm)
20 | }
21 | }
22 | // 连接数据库
23 | db, err := gorm.Open(sqlite.Open("./db/sublink.db"), &gorm.Config{})
24 | if err != nil {
25 | log.Println("连接数据库失败")
26 | }
27 | DB = db
28 | // 检查是否已经初始化
29 | if isInitialized {
30 | log.Println("数据库已经初始化,无需重复初始化")
31 | return
32 | }
33 | err = db.AutoMigrate(&User{}, &Subcription{}, &Node{}, &SubLogs{})
34 | if err != nil {
35 | log.Println("数据表迁移失败")
36 | }
37 | // 初始化用户数据
38 | err = db.First(&User{}).Error
39 | if err == gorm.ErrRecordNotFound {
40 | admin := &User{
41 | Username: "admin",
42 | Password: "123456",
43 | Role: "admin",
44 | Nickname: "管理员",
45 | }
46 | err = admin.Create()
47 | if err != nil {
48 | log.Println("初始化添加用户数据失败")
49 | }
50 | }
51 | // 设置初始化标志为 true
52 | isInitialized = true
53 | log.Println("数据库初始化成功") // 只有在没有任何错误时才会打印这个日志
54 | }
55 |
--------------------------------------------------------------------------------
/models/user.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | type User struct {
4 | ID int
5 | Username string
6 | Password string
7 | Role string
8 | Nickname string
9 | }
10 |
11 | func (user *User) Create() error { // 创建用户
12 | return DB.Create(user).Error
13 | }
14 | func (user *User) Set(UpdateUser *User) error { // 设置用户
15 | return DB.Where("username = ?", user.Username).Updates(UpdateUser).Error
16 | }
17 | func (user *User) Verify() error { // 验证用户
18 | return DB.Where("username = ? AND password = ?", user.Username, user.Password).First(user).Error
19 | }
20 |
21 | func (user *User) Find() error { // 查找用户
22 | return DB.Where("username = ? ", user.Username).First(user).Error
23 | }
24 |
25 | func (user *User) All() ([]User, error) { // 获取所有用户
26 | var users []User
27 | err := DB.Find(&users).Error
28 | return users, err
29 | }
30 |
31 | func (user *User) Del() error { // 删除用户
32 | return DB.Delete(user).Error
33 | }
34 |
--------------------------------------------------------------------------------
/node/ss_test.go:
--------------------------------------------------------------------------------
1 | package node
2 |
3 | import (
4 | "fmt"
5 | "testing"
6 | )
7 |
8 | func TestDecodeSSURL(t *testing.T) {
9 | type args struct {
10 | s string
11 | }
12 | tests := []struct {
13 | name string
14 | args args
15 | want Ss
16 | wantErr bool
17 | }{
18 | {
19 | name: "ss",
20 | args: args{
21 | s: "ss://YWVzLTI1Ni1nY206NEhrdSt0Vk53SnFyblVZR2JycE95YkVhck03QmhxYmdhRTFxRk1JPQ==@127.0.0.1:34020?type=tcp#ocent-ss-ndptvd0p",
22 | },
23 | }, {
24 | name: "ss2",
25 | args: args{
26 | s: "ss://YWVzLTI1Ni1jZmI6S1NYTmhuWnBqd0M2UGM2Q0A1NC4xNjkuMzUuMjI4OjMxNDQ0",
27 | },
28 | }, {
29 | name: "no ss schema",
30 | args: args{
31 | s: "noss://YWVzLTI1Ni1jZmI6S1NYTmhuWnBqd0M2UGM2Q0A1NC4xNjkuMzUuMjI4OjMxNDQ0",
32 | },
33 | wantErr: true,
34 | },
35 | }
36 | for _, tt := range tests {
37 | t.Run(tt.name, func(t *testing.T) {
38 | got, err := DecodeSSURL(tt.args.s)
39 | if (err != nil) != tt.wantErr {
40 | t.Errorf("DecodeSSURL() error = %v, wantErr %v", err, tt.wantErr)
41 | return
42 | }
43 | fmt.Println(got)
44 | })
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/routers/clients.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | import (
4 | "sublink/api"
5 | "sublink/middlewares"
6 |
7 | "github.com/gin-gonic/gin"
8 | )
9 |
10 | func Clients(r *gin.Engine) {
11 | ClientsGroup := r.Group("/c")
12 | ClientsGroup.Use(middlewares.GetIp)
13 | {
14 | // ClientsGroup.GET("/v2ray/:subname", api.GetV2ray)
15 | // ClientsGroup.GET("/clash/:subname", api.GetClash)
16 | // ClientsGroup.GET("/surge/:subname", api.GetSurge)
17 | ClientsGroup.GET("/", api.GetClient)
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/routers/index.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | // // 加载index.html
4 | // func Index(r *gin.Engine) {
5 | // TotalGroup := r.Group("/api/v1/total")
6 | // {
7 | // TotalGroup.GET("/sub", api.SubTotal)
8 | // TotalGroup.GET("/node", api.NodesTotal)
9 | // }
10 |
11 | // }
12 |
--------------------------------------------------------------------------------
/routers/menus.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | import (
4 | "sublink/api"
5 |
6 | "github.com/gin-gonic/gin"
7 | )
8 |
9 | func Mentus(r *gin.Engine) {
10 | MentusGroup := r.Group("/api/v1/menus")
11 | {
12 | // MentusGroup.GET("/menus", api.GetMenus)
13 | MentusGroup.GET("/routes", api.GetMenus)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/routers/node.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | import (
4 | "sublink/api"
5 |
6 | "github.com/gin-gonic/gin"
7 | )
8 |
9 | func Nodes(r *gin.Engine) {
10 | NodesGroup := r.Group("/api/v1/nodes")
11 | {
12 | NodesGroup.POST("/add", api.NodeAdd)
13 | NodesGroup.DELETE("/delete", api.NodeDel)
14 | NodesGroup.GET("/get", api.NodeGet)
15 | NodesGroup.POST("/update", api.NodeUpdadte)
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/routers/subcription.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | import (
4 | "sublink/api"
5 |
6 | "github.com/gin-gonic/gin"
7 | )
8 |
9 | func Subcription(r *gin.Engine) {
10 | SubcriptionGroup := r.Group("/api/v1/subcription")
11 | {
12 | SubcriptionGroup.POST("/add", api.SubAdd)
13 | SubcriptionGroup.DELETE("/delete", api.SubDel)
14 | SubcriptionGroup.GET("/get", api.SubGet)
15 | SubcriptionGroup.POST("/update", api.SubUpdate)
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/routers/template.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | import (
4 | "sublink/api"
5 |
6 | "github.com/gin-gonic/gin"
7 | )
8 |
9 | func Templates(r *gin.Engine) {
10 | TempsGroup := r.Group("/api/v1/template")
11 | {
12 | TempsGroup.POST("/add", api.AddTemp)
13 | TempsGroup.POST("/delete", api.DelTemp)
14 | TempsGroup.GET("/get", api.GetTempS)
15 | TempsGroup.POST("/update", api.UpdateTemp)
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/routers/total.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | import (
4 | "sublink/api"
5 |
6 | "github.com/gin-gonic/gin"
7 | )
8 |
9 | func Total(r *gin.Engine) {
10 | TotalGroup := r.Group("/api/v1/total")
11 | {
12 | TotalGroup.GET("/sub", api.SubTotal)
13 | TotalGroup.GET("/node", api.NodesTotal)
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/routers/user.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | import (
4 | "sublink/api"
5 |
6 | "github.com/gin-gonic/gin"
7 | )
8 |
9 | func User(r *gin.Engine) {
10 | authGroup := r.Group("/api/v1/auth")
11 | {
12 | authGroup.POST("/login", api.UserLogin)
13 | authGroup.DELETE("/logout", api.UserOut)
14 | authGroup.GET("/captcha", api.GetCaptcha)
15 | }
16 | userGroup := r.Group("/api/v1/users")
17 | {
18 | userGroup.GET("/me", api.UserMe)
19 | userGroup.GET("/page", api.UserPages)
20 | userGroup.PATCH(":username/:password", api.UserSet)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/routers/version.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | import "github.com/gin-gonic/gin"
4 |
5 | func Version(r *gin.Engine, version string) {
6 |
7 | r.GET("/api/v1/version", func(c *gin.Context) {
8 |
9 | c.JSON(200, gin.H{
10 | "code": "00000",
11 | "data": version,
12 | })
13 | })
14 | }
15 |
--------------------------------------------------------------------------------
/settings/user.go:
--------------------------------------------------------------------------------
1 | package settings
2 |
3 | import (
4 | "log"
5 | "sublink/models"
6 | )
7 |
8 | // 重置默认用户
9 | func ResetUser(username string, password string) {
10 | // 如果账号或者密码为空
11 | if username == "" || password == "" {
12 | log.Println("账号或者密码不能为空")
13 | return
14 | }
15 | if len(password) < 6 {
16 | log.Println("密码不能小于6位数")
17 | return
18 | }
19 | User := &models.User{}
20 | // 获取所有用户
21 | users, err := User.All()
22 | if err != nil {
23 | log.Printf("用户存在")
24 | }
25 | // 遍历所有用户
26 | for _, user := range users {
27 | // 删除所有用户
28 | user.Del()
29 | }
30 |
31 | //打印输出
32 | log.Printf("账号%s,密码%s", username, password)
33 | User = &models.User{Username: username, Password: password, Role: "admin", Nickname: "管理员"}
34 | User.Create()
35 | }
36 |
--------------------------------------------------------------------------------
/static/avatar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/static/avatar.gif
--------------------------------------------------------------------------------
/static/css/401.Vp_sG7yN.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";[data-v-d53e86c4]:root{--menu-background: #304156;--menu-text: #bfcbd9;--menu-active-text: var(--el-menu-active-color);--menu-hover: #263445;--sidebar-logo-background: #2d3748}html.dark[data-v-d53e86c4]{--menu-background: var(--el-bg-color-overlay);--menu-text: #fff;--menu-active-text: var(--el-menu-active-color);--menu-hover: rgb(0 0 0 / 20%);--sidebar-logo-background: rgb(0 0 0 / 20%)}.errPage-container[data-v-d53e86c4]{width:800px;max-width:100%;margin:100px auto}.errPage-container .pan-back-btn[data-v-d53e86c4]{color:#fff;background:#008489;border:none!important}.errPage-container .pan-gif[data-v-d53e86c4]{display:block;margin:0 auto}.errPage-container .pan-img[data-v-d53e86c4]{display:block;width:100%;margin:0 auto}.errPage-container .text-jumbo[data-v-d53e86c4]{font-size:60px;font-weight:700;color:#484848}.errPage-container .list-unstyled[data-v-d53e86c4]{font-size:14px}.errPage-container .list-unstyled li[data-v-d53e86c4]{padding-bottom:5px}.errPage-container .list-unstyled a[data-v-d53e86c4]{color:#008489;text-decoration:none}.errPage-container .list-unstyled a[data-v-d53e86c4]:hover{text-decoration:underline}
2 |
--------------------------------------------------------------------------------
/static/css/BarChart.ulyVC4La.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";[data-v-0b34e13d]:root{--menu-background: #304156;--menu-text: #bfcbd9;--menu-active-text: var(--el-menu-active-color);--menu-hover: #263445;--sidebar-logo-background: #2d3748}html.dark[data-v-0b34e13d]{--menu-background: var(--el-bg-color-overlay);--menu-text: #fff;--menu-active-text: var(--el-menu-active-color);--menu-hover: rgb(0 0 0 / 20%);--sidebar-logo-background: rgb(0 0 0 / 20%)}.title[data-v-0b34e13d]{display:flex;justify-content:space-between}.title .download[data-v-0b34e13d]{cursor:pointer}.title .download[data-v-0b34e13d]:hover{color:#409eff}
2 |
--------------------------------------------------------------------------------
/static/css/apifox.CCvSwCIK.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";[data-v-4ff6b735]:root{--menu-background: #304156;--menu-text: #bfcbd9;--menu-active-text: var(--el-menu-active-color);--menu-hover: #263445;--sidebar-logo-background: #2d3748}html.dark[data-v-4ff6b735]{--menu-background: var(--el-bg-color-overlay);--menu-text: #fff;--menu-active-text: var(--el-menu-active-color);--menu-hover: rgb(0 0 0 / 20%);--sidebar-logo-background: rgb(0 0 0 / 20%)}.app-container[data-v-4ff6b735]{height:calc(100vh - 50px)}.hasTagsView .app-container[data-v-4ff6b735]{height:calc(100vh - 84px)}
2 |
--------------------------------------------------------------------------------
/static/css/el-card.fwQOLwdi.css:
--------------------------------------------------------------------------------
1 | .el-card{--el-card-border-color:var(--el-border-color-light);--el-card-border-radius:4px;--el-card-padding:20px;--el-card-bg-color:var(--el-fill-color-blank);background-color:var(--el-card-bg-color);border:1px solid var(--el-card-border-color);border-radius:var(--el-card-border-radius);color:var(--el-text-color-primary);overflow:hidden;transition:var(--el-transition-duration)}.el-card.is-always-shadow,.el-card.is-hover-shadow:focus,.el-card.is-hover-shadow:hover{box-shadow:var(--el-box-shadow-light)}.el-card__header{border-bottom:1px solid var(--el-card-border-color);box-sizing:border-box;padding:calc(var(--el-card-padding) - 2px) var(--el-card-padding)}.el-card__body{padding:var(--el-card-padding)}.el-card__footer{border-top:1px solid var(--el-card-border-color);box-sizing:border-box;padding:calc(var(--el-card-padding) - 2px) var(--el-card-padding)}
2 |
--------------------------------------------------------------------------------
/static/css/el-scrollbar.BWxh-h6K.css:
--------------------------------------------------------------------------------
1 | .el-scrollbar{--el-scrollbar-opacity:.3;--el-scrollbar-bg-color:var(--el-text-color-secondary);--el-scrollbar-hover-opacity:.5;--el-scrollbar-hover-bg-color:var(--el-text-color-secondary);height:100%;overflow:hidden;position:relative}.el-scrollbar__wrap{height:100%;overflow:auto}.el-scrollbar__wrap--hidden-default{scrollbar-width:none}.el-scrollbar__wrap--hidden-default::-webkit-scrollbar{display:none}.el-scrollbar__thumb{background-color:var(--el-scrollbar-bg-color,var(--el-text-color-secondary));border-radius:inherit;cursor:pointer;display:block;height:0;opacity:var(--el-scrollbar-opacity,.3);position:relative;transition:var(--el-transition-duration) background-color;width:0}.el-scrollbar__thumb:hover{background-color:var(--el-scrollbar-hover-bg-color,var(--el-text-color-secondary));opacity:var(--el-scrollbar-hover-opacity,.5)}.el-scrollbar__bar{border-radius:4px;bottom:2px;position:absolute;right:2px;z-index:1}.el-scrollbar__bar.is-vertical{top:2px;width:6px}.el-scrollbar__bar.is-vertical>div{width:100%}.el-scrollbar__bar.is-horizontal{height:6px;left:2px}.el-scrollbar__bar.is-horizontal>div{height:100%}.el-scrollbar-fade-enter-active{transition:opacity .34s ease-out}.el-scrollbar-fade-leave-active{transition:opacity .12s ease-out}.el-scrollbar-fade-enter-from,.el-scrollbar-fade-leave-active{opacity:0}
2 |
--------------------------------------------------------------------------------
/static/css/icons.CBhJQ2Ib.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";[data-v-e1dbd652]:root{--menu-background: #304156;--menu-text: #bfcbd9;--menu-active-text: var(--el-menu-active-color);--menu-hover: #263445;--sidebar-logo-background: #2d3748}html.dark[data-v-e1dbd652]{--menu-background: var(--el-bg-color-overlay);--menu-text: #fff;--menu-active-text: var(--el-menu-active-color);--menu-hover: rgb(0 0 0 / 20%);--sidebar-logo-background: rgb(0 0 0 / 20%)}.icons-container[data-v-e1dbd652]{margin:10px 20px 0;overflow:hidden}.icons-container .grid[data-v-e1dbd652]{position:relative;display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr))}.icons-container .icon-item[data-v-e1dbd652]{float:left;width:100px;height:85px;margin:20px;font-size:30px;color:var(--el-text-color-regular);text-align:center;cursor:pointer}.icons-container span[data-v-e1dbd652]{display:block;margin-top:10px;font-size:16px}.icons-container .disabled[data-v-e1dbd652]{pointer-events:none}
2 |
--------------------------------------------------------------------------------
/static/css/index.B4dlp3f2.css:
--------------------------------------------------------------------------------
1 | .svg-icon[data-v-52fbbe93]{display:inline-block;width:1em;height:1em;overflow:hidden;vertical-align:-.15em;outline:none;fill:currentcolor}
2 |
--------------------------------------------------------------------------------
/static/css/index.Dwigi1cb.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";[data-v-ba695567]:root{--menu-background: #304156;--menu-text: #bfcbd9;--menu-active-text: var(--el-menu-active-color);--menu-hover: #263445;--sidebar-logo-background: #2d3748}html.dark[data-v-ba695567]{--menu-background: var(--el-bg-color-overlay);--menu-text: #fff;--menu-active-text: var(--el-menu-active-color);--menu-hover: rgb(0 0 0 / 20%);--sidebar-logo-background: rgb(0 0 0 / 20%)}html.dark .login-container[data-v-ba695567]{background:url(/static/img/login-bg-dark.BfPFE40x.jpg) no-repeat center right}.login-container[data-v-ba695567]{overflow-y:auto;background:url(/static/img/login-bg.CKlK6emc.jpg) no-repeat center right;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.login-container .login-form[data-v-ba695567]{padding:30px 10px}.el-form-item[data-v-ba695567]{background:var(--el-input-bg-color);border:1px solid var(--el-border-color);border-radius:5px}[data-v-ba695567] .el-input .el-input__wrapper{padding:0;background-color:transparent;box-shadow:none}[data-v-ba695567] .el-input .el-input__wrapper.is-focus,[data-v-ba695567] .el-input .el-input__wrapper:hover{box-shadow:none!important}[data-v-ba695567] .el-input .el-input__wrapper input:-webkit-autofill{transition:background-color 1000s ease-in-out 0s}
2 |
--------------------------------------------------------------------------------
/static/css/internal-doc.BdNudHKe.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";[data-v-7df23cf9]:root{--menu-background: #304156;--menu-text: #bfcbd9;--menu-active-text: var(--el-menu-active-color);--menu-hover: #263445;--sidebar-logo-background: #2d3748}html.dark[data-v-7df23cf9]{--menu-background: var(--el-bg-color-overlay);--menu-text: #fff;--menu-active-text: var(--el-menu-active-color);--menu-hover: rgb(0 0 0 / 20%);--sidebar-logo-background: rgb(0 0 0 / 20%)}.app-container[data-v-7df23cf9]{height:calc(100vh - 50px)}.hasTagsView .app-container[data-v-7df23cf9]{height:calc(100vh - 84px)}iframe[data-v-7df23cf9]{width:100%;height:100%}
2 |
--------------------------------------------------------------------------------
/static/css/knife4j.DRg4vOS3.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";[data-v-f4490f0d]:root{--menu-background: #304156;--menu-text: #bfcbd9;--menu-active-text: var(--el-menu-active-color);--menu-hover: #263445;--sidebar-logo-background: #2d3748}html.dark[data-v-f4490f0d]{--menu-background: var(--el-bg-color-overlay);--menu-text: #fff;--menu-active-text: var(--el-menu-active-color);--menu-hover: rgb(0 0 0 / 20%);--sidebar-logo-background: rgb(0 0 0 / 20%)}.app-container[data-v-f4490f0d]{height:calc(100vh - 50px)}.hasTagsView .app-container[data-v-f4490f0d]{height:calc(100vh - 84px)}
2 |
--------------------------------------------------------------------------------
/static/css/nodes.DzJW8z5F.css:
--------------------------------------------------------------------------------
1 | .el-card[data-v-e6fb1451]{margin:10px}.el-input[data-v-e6fb1451]{margin-bottom:10px}
2 |
--------------------------------------------------------------------------------
/static/css/set.BMjHnBvk.css:
--------------------------------------------------------------------------------
1 | .el-col[data-v-38e5adf0]{margin-bottom:10px}
2 |
--------------------------------------------------------------------------------
/static/css/signature.C8sJe9y0.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";[data-v-d1ec2ee9]:root{--menu-background: #304156;--menu-text: #bfcbd9;--menu-active-text: var(--el-menu-active-color);--menu-hover: #263445;--sidebar-logo-background: #2d3748}html.dark[data-v-d1ec2ee9]{--menu-background: var(--el-bg-color-overlay);--menu-text: #fff;--menu-active-text: var(--el-menu-active-color);--menu-hover: rgb(0 0 0 / 20%);--sidebar-logo-background: rgb(0 0 0 / 20%)}.canvas-dom[data-v-d1ec2ee9]{width:100%;height:100%;padding:0 20px;background-color:#fff}.canvas-dom canvas[data-v-d1ec2ee9]{border:1px solid #e6e6e6}.canvas-dom header[data-v-d1ec2ee9]{display:flex;flex-flow:row nowrap;align-items:center;width:100%;margin:8px}.canvas-dom header .eraser-option[data-v-d1ec2ee9]{display:flex}.canvas-dom header .eraser-option label[data-v-d1ec2ee9]{white-space:nowrap}
2 |
--------------------------------------------------------------------------------
/static/css/subs.JwB3fIbV.css:
--------------------------------------------------------------------------------
1 | .el-checkbox-group{font-size:0;line-height:0}.el-card[data-v-42072bec]{margin:10px}.el-input[data-v-42072bec]{margin-bottom:10px}.el-tag[data-v-42072bec]{margin:5px}
2 |
--------------------------------------------------------------------------------
/static/css/swagger.eJ-qo84r.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";[data-v-56050cf3]:root{--menu-background: #304156;--menu-text: #bfcbd9;--menu-active-text: var(--el-menu-active-color);--menu-hover: #263445;--sidebar-logo-background: #2d3748}html.dark[data-v-56050cf3]{--menu-background: var(--el-bg-color-overlay);--menu-text: #fff;--menu-active-text: var(--el-menu-active-color);--menu-hover: rgb(0 0 0 / 20%);--sidebar-logo-background: rgb(0 0 0 / 20%)}.app-container[data-v-56050cf3]{height:calc(100vh - 50px)}.hasTagsView .app-container[data-v-56050cf3]{height:calc(100vh - 84px)}
2 |
--------------------------------------------------------------------------------
/static/css/template.DpE-mm8O.css:
--------------------------------------------------------------------------------
1 | .el-card[data-v-0c7c8c5b]{margin:10px}.el-input[data-v-0c7c8c5b]{margin-bottom:10px}
2 |
--------------------------------------------------------------------------------
/static/css/websocket.BZkLAsTH.css:
--------------------------------------------------------------------------------
1 | .message-container[data-v-8d7ecc11]{display:flex;flex-direction:column}.message[data-v-8d7ecc11]{padding:10px;margin:10px;border-radius:5px}.message--sent[data-v-8d7ecc11]{align-self:flex-end;background-color:#dcf8c6}.message--received[data-v-8d7ecc11]{align-self:flex-start;background-color:#e8e8e8}.message-content[data-v-8d7ecc11]{display:flex;flex-direction:column}.message-sender[data-v-8d7ecc11]{margin-bottom:5px;font-weight:700;text-align:right}.message-receiver[data-v-8d7ecc11]{margin-bottom:5px;font-weight:700;text-align:left}.tip-message[data-v-8d7ecc11]{align-self:center;padding:5px 10px;margin-bottom:5px;font-style:italic;text-align:center;background-color:#f0f0f0;border-radius:5px}
2 |
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/static/favicon.ico
--------------------------------------------------------------------------------
/static/img/401.DaBJYOxp.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/static/img/401.DaBJYOxp.gif
--------------------------------------------------------------------------------
/static/img/404.D6_y3Jr2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/static/img/404.D6_y3Jr2.png
--------------------------------------------------------------------------------
/static/img/login-bg-dark.BfPFE40x.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/static/img/login-bg-dark.BfPFE40x.jpg
--------------------------------------------------------------------------------
/static/img/login-bg.CKlK6emc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/static/img/login-bg.CKlK6emc.jpg
--------------------------------------------------------------------------------
/static/img/logo.D7mmbp4F.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/static/img/logo.D7mmbp4F.png
--------------------------------------------------------------------------------
/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | sublinkX节点订阅管理系统
8 |
9 |
10 |
11 |
12 |
13 |
16 |
17 |
18 |
59 |
60 |
--------------------------------------------------------------------------------
/static/js/FunnelChart.L2tIbyMX.js:
--------------------------------------------------------------------------------
1 | import{i as e}from"./index.DNYq9Wso.js";import{d as t,r as i,o as a,bg as n,bh as l,c as d,e as r,n as s,G as o}from"./index.9PHSMUIB.js";const u=["id"],h=t({__name:"FunnelChart",props:{id:{type:String,default:"funnelChart"},className:{type:String,default:""},width:{type:String,default:"200px",required:!0},height:{type:String,default:"200px",required:!0}},setup(t){const h=t,m={title:{show:!0,text:"订单线索转化漏斗图",x:"center",padding:15,textStyle:{fontSize:18,fontStyle:"normal",fontWeight:"bold",color:"#337ecc"}},grid:{left:"2%",right:"2%",bottom:"10%",containLabel:!0},legend:{x:"center",y:"bottom",data:["Show","Click","Visit","Inquiry","Order"]},series:[{name:"Funnel",type:"funnel",left:"20%",top:60,bottom:60,width:"60%",sort:"descending",gap:2,label:{show:!0,position:"inside"},labelLine:{length:10,lineStyle:{width:1,type:"solid"}},itemStyle:{borderColor:"#fff",borderWidth:1},emphasis:{label:{fontSize:20}},data:[{value:60,name:"Visit"},{value:40,name:"Inquiry"},{value:20,name:"Order"},{value:80,name:"Click"},{value:100,name:"Show"}]}]},p=i("");return a((()=>{p.value=n(e(document.getElementById(h.id))),p.value.setOption(m),window.addEventListener("resize",(()=>{p.value.resize()}))})),l((()=>{p.value&&p.value.resize()})),(e,i)=>(d(),r("div",{id:t.id,class:s(t.className),style:o({height:t.height,width:t.width})},null,14,u))}});export{h as default};
2 |
--------------------------------------------------------------------------------
/static/js/PieChart.mgwtBU-p.js:
--------------------------------------------------------------------------------
1 | import{d as e,r as t,o as a,bg as i,bh as r,c as s,l as d,w as n,a4 as l,k as o,n as u,G as m}from"./index.9PHSMUIB.js";import{E as p}from"./el-card.DWbysKpS.js";import{i as h}from"./index.DNYq9Wso.js";const c=["id"],g=e({__name:"PieChart",props:{id:{type:String,default:"pieChart"},className:{type:String,default:""},width:{type:String,default:"200px",required:!0},height:{type:String,default:"200px",required:!0}},setup(e){const g=e,f={grid:{left:"2%",right:"2%",bottom:"10%",containLabel:!0},legend:{top:"bottom",textStyle:{color:"#999"}},series:[{name:"Nightingale Chart",type:"pie",radius:[50,130],center:["50%","50%"],roseType:"area",itemStyle:{borderRadius:1,color:function(e){return["#409EFF","#67C23A","#E6A23C","#F56C6C"][e.dataIndex]}},data:[{value:26,name:"家用电器"},{value:27,name:"户外运动"},{value:24,name:"汽车用品"},{value:23,name:"手机数码"}]}]},v=t("");return a((()=>{v.value=i(h(document.getElementById(g.id))),v.value.setOption(f),window.addEventListener("resize",(()=>{v.value.resize()}))})),r((()=>{v.value&&v.value.resize()})),(t,a)=>{const i=p;return s(),d(i,null,{header:n((()=>a[0]||(a[0]=[l(" 产品分类饼图 ")]))),default:n((()=>[o("div",{id:e.id,class:u(e.className),style:m({height:e.height,width:e.width})},null,14,c)])),_:1})}}});export{g as default};
2 |
--------------------------------------------------------------------------------
/static/js/RadarChart.TGxAW552.js:
--------------------------------------------------------------------------------
1 | import{d as e,r as a,o as t,bg as r,bh as d,c as n,l as i,w as s,a4 as l,k as o,n as u,G as m}from"./index.9PHSMUIB.js";import{E as p}from"./el-card.DWbysKpS.js";import{i as c}from"./index.DNYq9Wso.js";const g=["id"],h=e({__name:"RadarChart",props:{id:{type:String,default:"radarChart"},className:{type:String,default:""},width:{type:String,default:"200px",required:!0},height:{type:String,default:"200px",required:!0}},setup(e){const h=e,f={grid:{left:"2%",right:"2%",bottom:"10%",containLabel:!0},legend:{x:"center",y:"bottom",data:["预定数量","下单数量","发货数量"],textStyle:{color:"#999"}},radar:{radius:"60%",indicator:[{name:"家用电器"},{name:"服装箱包"},{name:"运动户外"},{name:"手机数码"},{name:"汽车用品"},{name:"家具厨具"}]},series:[{name:"Budget vs spending",type:"radar",itemStyle:{borderRadius:6,color:function(e){return["#409EFF","#67C23A","#E6A23C","#F56C6C"][e.dataIndex]}},data:[{value:[400,400,400,400,400,400],name:"预定数量"},{value:[300,300,300,300,300,300],name:"下单数量"},{value:[200,200,200,200,200,200],name:"发货数量"}]}]},v=a("");return t((()=>{v.value=r(c(document.getElementById(h.id))),v.value.setOption(f),window.addEventListener("resize",(()=>{v.value.resize()}))})),d((()=>{v.value&&v.value.resize()})),(a,t)=>{const r=p;return n(),i(r,null,{header:s((()=>t[0]||(t[0]=[l(" 订单状态雷达图 ")]))),default:s((()=>[o("div",{id:e.id,class:u(e.className),style:m({height:e.height,width:e.width})},null,14,g)])),_:1})}}});export{h as default};
2 |
--------------------------------------------------------------------------------
/static/js/_plugin-vue_export-helper.BCo6x5W8.js:
--------------------------------------------------------------------------------
1 | const o=(o,t)=>{const c=o.__vccOpts||o;for(const[s,n]of t)c[s]=n;return c};export{o as _};
2 |
--------------------------------------------------------------------------------
/static/js/apifox.IXUmMSaC.js:
--------------------------------------------------------------------------------
1 | import{_ as e}from"./_plugin-vue_export-helper.BCo6x5W8.js";import{c as a,e as r,k as s}from"./index.9PHSMUIB.js";const t={class:"app-container"};const o=e({},[["render",function(e,o){return a(),r("div",t,o[0]||(o[0]=[s("iframe",{src:"https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5",width:"100%",height:"100%",frameborder:"0"},null,-1)]))}],["__scopeId","data-v-4ff6b735"]]);export{o as default};
2 |
--------------------------------------------------------------------------------
/static/js/cascader.Bxy7lIuJ.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M832.128%20768c33.195%200%2060.501%2025.173%2063.573%2057.813L896%20832a64%2064%200%200%201-63.872%2064H533.205a63.787%2063.787%200%200%201-63.872-64%2064%2064%200%200%201%2063.872-64h298.923zM213.333%20874.667c-23.722%200-42.666-19.072-42.666-42.624V362.667A42.667%2042.667%200%200%201%20213.333%20320l4.992.299C239.66%20322.73%20256%20340.779%20256%20362.624l-.043%20128.043h128.299c21.248%200%2039.595%2016.469%2042.112%2037.674l.299%204.992-.299%204.992A42.368%2042.368%200%200%201%20384.256%20576H256l.043%20213.333h128.256c22.869%200%2042.41%2019.115%2042.41%2042.667l-.298%204.992a42.368%2042.368%200%200%201-42.112%2037.675zm618.795-405.334c33.195%200%2060.501%2025.174%2063.573%2057.814l.299%206.186a64%2064%200%200%201-63.872%2064H533.205a63.787%2063.787%200%200%201-63.872-64%2064%2064%200%200%201%2063.872-64h298.923zM576.171%20128c33.194%200%2060.458%2025.173%2063.573%2057.813L640%20192c0%2035.328-29.013%2064-63.83%2064H191.83A63.744%2063.744%200%200%201%20128%20192c0-35.328%2029.013-64%2063.83-64h384.34z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/castArray.BN0gQOTw.js:
--------------------------------------------------------------------------------
1 | import{bS as r}from"./index.9PHSMUIB.js";function n(){if(!arguments.length)return[];var n=arguments[0];return r(n)?n:[n]}export{n as c};
2 |
--------------------------------------------------------------------------------
/static/js/client.fwafuIJ_.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M962.184%2055.874H61.818C27.732%2055.874%200%2083.606%200%20117.692v621.64c0%2034.086%2027.732%2061.818%2061.818%2061.818h308.52v44.98c0%2041.234-33.547%2074.782-74.781%2074.782h-67.995c-13.036%200-23.606%2010.568-23.606%2023.606%200%2013.038%2010.57%2023.606%2023.606%2023.606h568.874c13.036%200%2023.606-10.568%2023.606-23.606%200-13.038-10.57-23.606-23.606-23.606h-67.997c-41.234%200-74.782-33.548-74.782-74.782v-44.978h308.52c34.087%200%2061.821-27.732%2061.821-61.819v-621.64c.004-34.087-27.728-61.819-61.814-61.819zM391.84%20920.916c16.092-20.672%2025.714-46.616%2025.714-74.782v-44.98h188.894v44.98c0%2028.166%209.622%2054.112%2025.714%2074.782H391.841zm584.95-181.583c0%208.054-6.552%2014.608-14.608%2014.608H61.818c-8.054%200-14.608-6.552-14.608-14.608V615.267h929.58v124.066zm0-171.28H47.212v-450.36c0-8.055%206.552-14.609%2014.608-14.609h900.362c8.054%200%2014.61%206.552%2014.61%2014.608v450.361z'/%3e%3cpath%20d='M486.531%20684.611a25.476%2025.476%200%201%200%2050.952%200%2025.476%2025.476%200%201%200-50.952%200zm65.946-466.103c-9.22-9.218-24.162-9.218-33.386%200L352.263%20385.337c-9.218%209.218-9.218%2024.166%200%2033.386a23.534%2023.534%200%200%200%2016.694%206.914%2023.526%2023.526%200%200%200%2016.692-6.914l166.828-166.829c9.218-9.218%209.218-24.166%200-33.386zm98.88%2096.679c-9.216-9.218-24.158-9.218-33.384-.002l-66.46%2066.456c-9.218%209.22-9.218%2024.168%200%2033.386a23.53%2023.53%200%200%200%2016.692%206.914c6.04%200%2012.082-2.304%2016.692-6.914l66.46-66.456c9.218-9.218%209.218-24.166%200-33.384z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/close.3A3CTE27.js:
--------------------------------------------------------------------------------
1 | const e="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20aria-hidden='true'%20width='1em'%20height='1em'%20viewBox='0%200%2036%2036'%3e%3cpath%20d='m19.41%2018%208.29-8.29a1%201%200%200%200-1.41-1.41L18%2016.59l-8.29-8.3a1%201%200%200%200-1.42%201.42l8.3%208.29-8.3%208.29A1%201%200%201%200%209.7%2027.7l8.3-8.29%208.29%208.29a1%201%200%200%200%201.41-1.41z'%20fill='currentColor'/%3e%3c/svg%3e";export{e as default};
2 |
--------------------------------------------------------------------------------
/static/js/close_all.CpAPdWg9.js:
--------------------------------------------------------------------------------
1 | const e="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20aria-hidden='true'%20width='1em'%20height='1em'%20viewBox='0%200%2036%2036'%3e%3cpath%20d='M26%2017H10a1%201%200%200%200%200%202h16a1%201%200%200%200%200-2z'%20fill='currentColor'/%3e%3c/svg%3e";export{e as default};
2 |
--------------------------------------------------------------------------------
/static/js/close_left.FPCWsnfT.js:
--------------------------------------------------------------------------------
1 | const e="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20aria-hidden='true'%20width='1em'%20height='1em'%20viewBox='0%200%2024%2024'%3e%3cg%20fill='none'%20stroke='currentColor'%20stroke-width='2'%20stroke-linecap='round'%3e%3cpath%20d='m7%2012%207%207m-7-7%207-7'%20stroke-linejoin='round'/%3e%3cpath%20d='M21%2012H7.5'/%3e%3cpath%20d='M3%203v18'%20stroke-linejoin='round'/%3e%3c/g%3e%3c/svg%3e";export{e as default};
2 |
--------------------------------------------------------------------------------
/static/js/close_other.CtMgS35C.js:
--------------------------------------------------------------------------------
1 | const e="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20aria-hidden='true'%20width='1em'%20height='1em'%20viewBox='0%200%2020%2020'%3e%3cpath%20d='M3%205h14V3H3v2zm12%208V7H5v6h10zM3%2017h14v-2H3v2z'%20fill='currentColor'/%3e%3c/svg%3e";export{e as default};
2 |
--------------------------------------------------------------------------------
/static/js/close_right.WYLOaSAD.js:
--------------------------------------------------------------------------------
1 | const e="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20aria-hidden='true'%20width='1em'%20height='1em'%20viewBox='0%200%2024%2024'%3e%3cg%20fill='none'%20stroke='currentColor'%20stroke-width='2'%20stroke-linecap='round'%3e%3cpath%20d='m17%2012-7%207m7-7-7-7'%20stroke-linejoin='round'/%3e%3cpath%20d='M3%2012h13.5'/%3e%3cpath%20d='M21%203v18'%20stroke-linejoin='round'/%3e%3c/g%3e%3c/svg%3e";export{e as default};
2 |
--------------------------------------------------------------------------------
/static/js/debounce.i1DMUZzi.js:
--------------------------------------------------------------------------------
1 | import{db as t,bR as n,cV as r}from"./index.9PHSMUIB.js";var i=/\s/;var e=/^\s+/;function u(t){return t?t.slice(0,function(t){for(var n=t.length;n--&&i.test(t.charAt(n)););return n}(t)+1).replace(e,""):t}var o=/^[-+]0x[0-9a-f]+$/i,a=/^0b[01]+$/i,f=/^0o[0-7]+$/i,c=parseInt;function v(r){if("number"==typeof r)return r;if(t(r))return NaN;if(n(r)){var i="function"==typeof r.valueOf?r.valueOf():r;r=n(i)?i+"":i}if("string"!=typeof r)return 0===r?r:+r;r=u(r);var e=a.test(r);return e||f.test(r)?c(r.slice(2),e?2:8):o.test(r)?NaN:+r}var s=function(){return r.Date.now()},d=Math.max,l=Math.min;function m(t,r,i){var e,u,o,a,f,c,m=0,p=!1,h=!1,x=!0;if("function"!=typeof t)throw new TypeError("Expected a function");function T(n){var r=e,i=u;return e=u=void 0,m=n,a=t.apply(i,r)}function y(t){var n=t-c;return void 0===c||n>=r||n<0||h&&t-m>=o}function g(){var t=s();if(y(t))return b(t);f=setTimeout(g,function(t){var n=r-(t-c);return h?l(n,o-(t-m)):n}(t))}function b(t){return f=void 0,x&&e?T(t):(e=u=void 0,a)}function N(){var t=s(),n=y(t);if(e=arguments,u=this,c=t,n){if(void 0===f)return function(t){return m=t,f=setTimeout(g,r),p?T(t):a}(c);if(h)return clearTimeout(f),f=setTimeout(g,r),T(c)}return void 0===f&&(f=setTimeout(g,r)),a}return r=v(r)||0,n(i)&&(p=!!i.leading,o=(h="maxWait"in i)?d(v(i.maxWait)||0,r):o,x="trailing"in i?!!i.trailing:x),N.cancel=function(){void 0!==f&&clearTimeout(f),m=0,e=c=u=f=void 0},N.flush=function(){return void 0===f?a:b(s())},N}export{m as d};
2 |
--------------------------------------------------------------------------------
/static/js/document.DqID0E9P.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M832.1%20185.1H609.4l-17.1-62c-9.6-34.6-40.5-58.8-75.3-58.8H196c-43.2%200-78.3%2036.4-78.3%2081.1V897c0%2035.3%2028.7%2064%2064%2064H832c35.3%200%2064-28.7%2064-64V249c.1-35.2-28.6-63.9-63.9-63.9zm-644.4-39.7c0-6.6%204.4-11.1%208.3-11.1h321c3.4%200%206.6%203.1%207.8%207.4l12%2043.4H187.7v-39.7zm638.4%20745.8H187.7V255.1h638.4v636.1z'/%3e%3cpath%20d='M311.1%20415.1a35%2035%200%201%200%2070%200%2035%2035%200%201%200-70%200zm151.2-35h257.8v70H462.3zM311.1%20582.3a35%2035%200%201%200%2070%200%2035%2035%200%201%200-70%200zm151.2-35h257.8v70H462.3zM311.1%20749.5a35%2035%200%201%200%2070%200%2035%2035%200%201%200-70%200zm151.2-35h257.8v70H462.3z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/download.BcBrriOr.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M624%20706.3h-74.1V464c0-4.4-3.6-8-8-8h-60c-4.4%200-8%203.6-8%208v242.3H400c-6.7%200-10.4%207.7-6.3%2012.9l112%20141.7c3.2%204.1%209.4%204.1%2012.6%200l112-141.7c4.1-5.2.4-12.9-6.3-12.9z'/%3e%3cpath%20d='M811.4%20366.7C765.6%20245.9%20648.9%20160%20512.2%20160S258.8%20245.8%20213%20366.6C127.3%20389.1%2064%20467.2%2064%20560c0%20110.5%2089.5%20200%20199.9%20200H304c4.4%200%208-3.6%208-8v-60c0-4.4-3.6-8-8-8h-40.1c-33.7%200-65.4-13.4-89-37.7-23.5-24.2-36-56.8-34.9-90.6.9-26.4%209.9-51.2%2026.2-72.1%2016.7-21.3%2040.1-36.8%2066.1-43.7l37.9-9.9%2013.9-36.6c8.6-22.8%2020.6-44.1%2035.7-63.4%2014.9-19.2%2032.6-35.9%2052.4-49.9%2041.1-28.9%2089.5-44.2%20140-44.2s98.9%2015.3%20140%2044.2c19.9%2014%2037.5%2030.8%2052.4%2049.9%2015.1%2019.3%2027.1%2040.7%2035.7%2063.4l13.8%2036.5%2037.8%2010C846.1%20454.5%20884%20503.8%20884%20560c0%2033.1-12.9%2064.3-36.3%2087.7-23.4%2023.4-54.5%2036.3-87.6%2036.3H720c-4.4%200-8%203.6-8%208v60c0%204.4%203.6%208%208%208h40.1C870.5%20760%20960%20670.5%20960%20560c0-92.7-63.1-170.7-148.6-193.3z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/edit.D3u4lddN.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20width='128'%20height='128'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M106.133%2067.2a4.797%204.797%200%200%200-4.8%204.8c0%20.187.014.36.027.533h-.027V118.4H9.6V26.667h50.133c2.654%200%204.8-2.147%204.8-4.8%200-2.654-2.146-4.8-4.8-4.8H9.6a9.594%209.594%200%200%200-9.6%209.6V118.4c0%205.307%204.293%209.6%209.6%209.6h91.733c5.307%200%209.6-4.293%209.6-9.6V72.533h-.026c.013-.173.026-.346.026-.533%200-2.653-2.146-4.8-4.8-4.8z'/%3e%3cpath%20d='M125.16%2013.373%20114.587%202.8c-3.747-3.747-9.854-3.72-13.6.027l-52.96%2052.96a4.264%204.264%200%200%200-.907%201.36L33.813%2088.533c-.746%201.76-.226%203.534.907%204.68%201.133%201.147%202.92%201.667%204.693.92l31.4-13.293c.507-.213.96-.52%201.36-.907l52.96-52.96c3.747-3.746%203.774-9.853.027-13.6zM66.107%2072.4l-18.32%207.76%207.76-18.32L92.72%2024.667l10.56%2010.56L66.107%2072.4zm52.226-52.227-8.266%208.267-10.56-10.56%208.266-8.267.027-.026%2010.56%2010.56-.027.026z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/el-alert.IAJrxUBM.js:
--------------------------------------------------------------------------------
1 | import{b as e,bw as s,bx as t,d as a,a9 as l,a as i,r as o,B as c,c as n,l as d,w as r,Z as f,k as p,n as u,g as y,E as v,m as b,a1 as k,e as m,f as g,a4 as x,t as _,O as h,a0 as w,a6 as S,T as B,_ as E,by as T,s as $}from"./index.9PHSMUIB.js";const C=e({title:{type:String,default:""},description:{type:String,default:""},type:{type:String,values:s(t),default:"info"},closable:{type:Boolean,default:!0},closeText:{type:String,default:""},showIcon:Boolean,center:Boolean,effect:{type:String,values:["light","dark"],default:"light"}}),I={close:e=>e instanceof MouseEvent},j=a({name:"ElAlert"});const A=$(E(a({...j,props:C,emits:I,setup(e,{emit:s}){const a=e,{Close:E}=T,$=l(),C=i("alert"),I=o(!0),j=c((()=>t[a.type])),A=c((()=>[C.e("icon"),{[C.is("big")]:!!a.description||!!$.default}])),M=c((()=>({"with-description":a.description||$.default}))),O=e=>{I.value=!1,s("close",e)};return(e,s)=>(n(),d(B,{name:y(C).b("fade"),persisted:""},{default:r((()=>[f(p("div",{class:u([y(C).b(),y(C).m(e.type),y(C).is("center",e.center),y(C).is(e.effect)]),role:"alert"},[e.showIcon&&y(j)?(n(),d(y(v),{key:0,class:u(y(A))},{default:r((()=>[(n(),d(b(y(j))))])),_:1},8,["class"])):k("v-if",!0),p("div",{class:u(y(C).e("content"))},[e.title||e.$slots.title?(n(),m("span",{key:0,class:u([y(C).e("title"),y(M)])},[g(e.$slots,"title",{},(()=>[x(_(e.title),1)]))],2)):k("v-if",!0),e.$slots.default||e.description?(n(),m("p",{key:1,class:u(y(C).e("description"))},[g(e.$slots,"default",{},(()=>[x(_(e.description),1)]))],2)):k("v-if",!0),e.closable?(n(),m(h,{key:2},[e.closeText?(n(),m("div",{key:0,class:u([y(C).e("close-btn"),y(C).is("customed")]),onClick:O},_(e.closeText),3)):(n(),d(y(v),{key:1,class:u(y(C).e("close-btn")),onClick:O},{default:r((()=>[w(y(E))])),_:1},8,["class"]))],64)):k("v-if",!0)],2)],2),[[S,I.value]])])),_:3},8,["name"]))}}),[["__file","alert.vue"]]));export{A as E};
2 |
--------------------------------------------------------------------------------
/static/js/el-card.DWbysKpS.js:
--------------------------------------------------------------------------------
1 | import{b as s,h as a,d as e,a as t,c as o,e as r,n as d,g as l,f as y,a1 as f,k as i,G as n,a4 as c,t as h,_ as v,s as p}from"./index.9PHSMUIB.js";const u=s({header:{type:String,default:""},footer:{type:String,default:""},bodyStyle:{type:a([String,Object,Array]),default:""},bodyClass:String,shadow:{type:String,values:["always","hover","never"],default:"always"}}),b=e({name:"ElCard"});const S=p(v(e({...b,props:u,setup(s){const a=t("card");return(s,e)=>(o(),r("div",{class:d([l(a).b(),l(a).is(`${s.shadow}-shadow`)])},[s.$slots.header||s.header?(o(),r("div",{key:0,class:d(l(a).e("header"))},[y(s.$slots,"header",{},(()=>[c(h(s.header),1)]))],2)):f("v-if",!0),i("div",{class:d([l(a).e("body"),s.bodyClass]),style:n(s.bodyStyle)},[y(s.$slots,"default")],6),s.$slots.footer||s.footer?(o(),r("div",{key:1,class:d(l(a).e("footer"))},[y(s.$slots,"footer",{},(()=>[c(h(s.footer),1)]))],2)):f("v-if",!0)],2))}}),[["__file","card.vue"]]));export{S as E};
2 |
--------------------------------------------------------------------------------
/static/js/el-link.BTv-HaC_.js:
--------------------------------------------------------------------------------
1 | import{b as e,i as s,d as a,a as i,B as t,c as n,e as l,l as d,w as o,m as r,g as f,E as c,a1 as u,n as p,f as y,_ as g,s as b}from"./index.9PHSMUIB.js";const k=e({type:{type:String,values:["primary","success","warning","info","danger","default"],default:"default"},underline:{type:Boolean,default:!0},disabled:Boolean,href:{type:String,default:""},target:{type:String,default:"_self"},icon:{type:s}}),m={click:e=>e instanceof MouseEvent},v=a({name:"ElLink"});const h=b(g(a({...v,props:k,emits:m,setup(e,{emit:s}){const a=e,g=i("link"),b=t((()=>[g.b(),g.m(a.type),g.is("disabled",a.disabled),g.is("underline",a.underline&&!a.disabled)]));function k(e){a.disabled||s("click",e)}return(e,s)=>(n(),l("a",{class:p(f(b)),href:e.disabled||!e.href?void 0:e.href,target:e.disabled||!e.href?void 0:e.target,onClick:k},[e.icon?(n(),d(f(c),{key:0},{default:o((()=>[(n(),d(r(e.icon)))])),_:1})):u("v-if",!0),e.$slots.default?(n(),l("span",{key:1,class:p(f(g).e("inner"))},[y(e.$slots,"default")],2)):u("v-if",!0),e.$slots.icon?y(e.$slots,"icon",{key:2}):u("v-if",!0)],10,["href","target"]))}}),[["__file","link.vue"]]));export{h as E};
2 |
--------------------------------------------------------------------------------
/static/js/el-tag.CLWce1kX.js:
--------------------------------------------------------------------------------
1 | import{b as s,bU as a,d as e,R as o,a as l,B as n,c as t,e as c,k as i,f as r,n as u,g as p,l as d,w as f,a0 as m,a7 as k,ad as b,E as g,a1 as y,G as v,T as C,_,s as h}from"./index.9PHSMUIB.js";const B=s({type:{type:String,values:["primary","success","info","warning","danger"],default:"primary"},closable:Boolean,disableTransitions:Boolean,hit:Boolean,color:String,size:{type:String,values:a},effect:{type:String,values:["dark","light","plain"],default:"light"},round:Boolean}),E={close:s=>s instanceof MouseEvent,click:s=>s instanceof MouseEvent},T=e({name:"ElTag"});const S=h(_(e({...T,props:B,emits:E,setup(s,{emit:a}){const e=s,_=o(),h=l("tag"),B=n((()=>{const{type:s,hit:a,effect:o,closable:l,round:n}=e;return[h.b(),h.is("closable",l),h.m(s||"primary"),h.m(_.value),h.m(o),h.is("hit",a),h.is("round",n)]})),E=s=>{a("close",s)},T=s=>{a("click",s)},S=s=>{s.component.subTree.component.bum=null};return(s,a)=>s.disableTransitions?(t(),c("span",{key:0,class:u(p(B)),style:v({backgroundColor:s.color}),onClick:T},[i("span",{class:u(p(h).e("content"))},[r(s.$slots,"default")],2),s.closable?(t(),d(p(g),{key:0,class:u(p(h).e("close")),onClick:b(E,["stop"])},{default:f((()=>[m(p(k))])),_:1},8,["class","onClick"])):y("v-if",!0)],6)):(t(),d(C,{key:1,name:`${p(h).namespace.value}-zoom-in-center`,appear:"",onVnodeMounted:S},{default:f((()=>[i("span",{class:u(p(B)),style:v({backgroundColor:s.color}),onClick:T},[i("span",{class:u(p(h).e("content"))},[r(s.$slots,"default")],2),s.closable?(t(),d(p(g),{key:0,class:u(p(h).e("close")),onClick:b(E,["stop"])},{default:f((()=>[m(p(k))])),_:1},8,["class","onClick"])):y("v-if",!0)],6)])),_:3},8,["name"]))}}),[["__file","tag.vue"]]));export{S as E,B as t};
2 |
--------------------------------------------------------------------------------
/static/js/el-tooltip.l0sNRNKZ.js:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/static/js/eye-open.CM4cKp-R.js:
--------------------------------------------------------------------------------
1 | const t="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='128'%20height='128'%3e%3cpath%20d='M512%20128q69.675%200%20135.51%2021.163t115.498%2054.997%2093.483%2074.837%2073.685%2082.006%2051.67%2074.837%2032.17%2054.827L1024%20512q-2.347%204.992-6.315%2013.483T998.87%20560.17t-31.658%2051.669-44.331%2059.99-56.832%2064.34-69.504%2060.16-82.347%2051.5-94.848%2034.687T512%20896q-69.675%200-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0%20513.707q2.347-4.992%206.315-13.483t18.816-34.816%2031.658-51.84%2044.331-60.33%2056.832-64.683%2069.504-60.331%2082.347-51.84%2094.848-34.816T512%20128.085zm0%2085.333q-46.677%200-91.648%2012.331t-81.152%2031.83-70.656%2047.146-59.648%2054.485-48.853%2057.686-37.675%2052.821-26.325%2043.99q12.33%2021.674%2026.325%2043.52t37.675%2052.351%2048.853%2057.003%2059.648%2053.845T339.2%20767.02t81.152%2031.488T512%20810.667t91.648-12.331%2081.152-31.659%2070.656-46.848%2059.648-54.186%2048.853-57.344%2037.675-52.651T927.957%20512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512%20213.334zm0%20128q70.656%200%20120.661%2050.006T682.667%20512%20632.66%20632.661%20512%20682.667%20391.339%20632.66%20341.333%20512t50.006-120.661T512%20341.333zm0%2085.334q-35.328%200-60.33%2025.002T426.666%20512t25.002%2060.33T512%20597.334t60.33-25.002T597.334%20512t-25.002-60.33T512%20426.666z'/%3e%3c/svg%3e";export{t as default};
2 |
--------------------------------------------------------------------------------
/static/js/eye.DqRz4sMZ.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20width='128'%20height='64'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M127.072%207.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586%2032.382-55.74%2032.382-29.24%200-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17%203.086-.399%206.275%201.2%208.238c.457.736%205.94%207.36%2014.62%2014.72L4.17%2035.96c-1.828%201.963-1.6%205.152.228%206.87.457.98%201.6%201.471%202.742%201.471s2.284-.49%203.198-1.472l12.564-13.983c5.94%204.416%2013.021%208.587%2020.788%2011.53l-4.797%2017.418c-.685%202.699.686%205.397%203.198%206.133h1.37c2.057%200%203.884-1.472%204.341-3.68L52.6%2042.83c3.655.736%207.538%201.227%2011.422%201.227%203.883%200%207.767-.49%2011.422-1.227l4.797%2017.173c.457%202.208%202.513%203.68%204.34%203.68.457%200%20.914%200%201.143-.246%202.513-.736%203.883-3.434%203.198-6.133l-4.797-17.172c7.767-2.944%2014.848-7.114%2020.788-11.53l12.336%2013.738c.913.981%202.056%201.472%203.198%201.472s2.284-.49%203.198-1.472c1.828-1.963%201.828-4.906.228-6.87l-11.65-13.001c9.366-7.36%2014.849-14.474%2014.849-14.474z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/fullscreen-exit.DXwCcaMo.js:
--------------------------------------------------------------------------------
1 | const v="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='currentColor'%3e%3cpath%20d='M18%207h4v2h-6V3h2v4zM8%209H2V7h4V3h2v6zm10%208v4h-2v-6h6v2h-4zM8%2015v6H6v-4H2v-2h6z'/%3e%3c/svg%3e";export{v as default};
2 |
--------------------------------------------------------------------------------
/static/js/fullscreen.dczNRBeD.js:
--------------------------------------------------------------------------------
1 | const v="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='currentColor'%3e%3cpath%20d='M8%203v2H4v4H2V3h6zM2%2021v-6h2v4h4v2H2zm20%200h-6v-2h4v-4h2v6zm0-12h-2V5h-4V3h6v6z'/%3e%3c/svg%3e";export{v as default};
2 |
--------------------------------------------------------------------------------
/static/js/github.DLO2QQQy.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M511.543%2014.057C228.914%2013.943%200%20242.743%200%20525.143%200%20748.457%20143.2%20938.286%20342.629%201008c26.857%206.743%2022.742-12.343%2022.742-25.371v-88.572C210.286%20912.23%20204%20809.6%20193.6%20792.457c-21.029-35.886-70.743-45.028-55.886-62.171%2035.315-18.172%2071.315%204.571%20113.029%2066.171%2030.171%2044.686%2089.028%2037.143%20118.857%2029.714%206.514-26.857%2020.457-50.857%2039.657-69.485C248.571%20727.886%20181.6%20629.829%20181.6%20513.257c0-56.571%2018.629-108.571%2055.2-150.514-23.314-69.143%202.171-128.343%205.6-137.143%2066.4-5.943%20135.429%2047.543%20140.8%2051.771C420.914%20267.2%20464%20261.83%20512.229%20261.83c48.457%200%2091.657%205.6%20129.714%2015.885%2012.914-9.828%2076.914-55.771%20138.628-50.171%203.315%208.8%2028.229%2066.628%206.286%20134.857%2037.029%2042.057%2055.886%2094.514%2055.886%20151.2%200%20116.8-67.429%20214.971-228.572%20243.314a145.714%20145.714%200%200%201%2043.543%20104v128.572c.915%2010.285%200%2020.457%2017.143%2020.457%20202.4-68.229%20348.114-259.429%20348.114-484.686%200-282.514-229.028-511.2-511.428-511.2z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/homepage.BcyYp1IG.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M958.401%20451.55a20.01%2020.01%200%200%200-6.966-14.972L524.345%2069.511c-7.499-6.446-18.581-6.446-26.08%200L309.583%20231.676V129.657c0-11.05-8.902-19.533-19.952-19.533h-88.034c-11.048%200-19.928%208.482-19.928%2019.533v211.954L71.176%20436.578a20.003%2020.003%200%200%200-6.968%2015.174v105.5a20.007%2020.007%200%200%200%2033.052%2015.172l53.298-45.826V850.7c0%2060.678%2049.364%20110.042%20110.042%20110.042h504.192c60.678%200%20110.043-49.364%20110.043-110.042V527.026l51.586%2044.336a20.001%2020.001%200%200%200%2021.48%202.966%2020.006%2020.006%200%200%200%2011.566-18.343l-1.066-104.436zM221.579%20150.033h48.095v115.942l-48.095%2041.336V150.034zm349.14%20770.692H436.665V700.642c0-11.03%208.977-20.007%2020.008-20.007h94.036c11.03%200%2020.007%208.976%2020.007%2020.007v220.084zm264.1-424.83v354.803c0%2038.612-31.415%2070.027-70.028%2070.027H610.733V700.642c0-33.096-26.927-60.023-60.023-60.023h-94.036c-33.097%200-60.023%2026.927-60.023%2060.023v220.085H260.599c-38.612%200-70.027-31.415-70.027-70.027V495.895a20.07%2020.07%200%200%200-.315-3.432L512.37%20215.504l322.703%20277.349a20.158%2020.158%200%200%200-.255%203.042zM525.41%20173.947c-7.502-6.446-18.587-6.447-26.086.003l-395.1%20339.714v-52.727l407.081-349.87%20407.177%20349.952.522%2051.205L525.41%20173.948z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/indent-decrease.ROHmwAah.js:
--------------------------------------------------------------------------------
1 | const v="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='currentColor'%3e%3cpath%20d='M3%204h18v2H3V4zm0%2015h18v2H3v-2zm8-5h10v2H11v-2zm0-5h10v2H11V9zm-8%203.5L7%209v7l-4-3.5z'/%3e%3c/svg%3e";export{v as default};
2 |
--------------------------------------------------------------------------------
/static/js/index.B2Hg7VBR.js:
--------------------------------------------------------------------------------
1 | import{d as e,B as s,c as i,e as t,k as r,g as a,G as l}from"./index.9PHSMUIB.js";import{_ as n}from"./_plugin-vue_export-helper.BCo6x5W8.js";const o=["xlink:href","fill"],p=n(e({__name:"index",props:{prefix:{type:String,default:"icon"},iconClass:{type:String,required:!1,default:""},color:{type:String,default:""},size:{type:String,default:"1em"}},setup(e){const n=e,p=s((()=>`#${n.prefix}-${n.iconClass}`));return(s,n)=>(i(),t("svg",{"aria-hidden":"true",class:"svg-icon",style:l("width:"+e.size+";height:"+e.size)},[r("use",{"xlink:href":a(p),fill:e.color},null,8,o)],4))}}),[["__scopeId","data-v-52fbbe93"]]);export{p as S};
2 |
--------------------------------------------------------------------------------
/static/js/index.BrHL87wj.js:
--------------------------------------------------------------------------------
1 | import{d as a,aD as e,aE as s,e as r,c as t}from"./index.9PHSMUIB.js";const p=a({__name:"index",setup(a){const p=e(),n=s(),{params:d,query:o}=p,{path:u}=d;return n.replace({path:"/"+u,query:o}),(a,e)=>(t(),r("div"))}});export{p as default};
2 |
--------------------------------------------------------------------------------
/static/js/index.CM09xEA_.js:
--------------------------------------------------------------------------------
1 | import{bd as e}from"./index.9PHSMUIB.js";function t(t){const a=new FormData;return a.append("file",t),e({url:"/api/v1/files",method:"post",data:a,headers:{"Content-Type":"multipart/form-data"}})}function a(t){return e({url:"/api/v1/files",method:"delete",params:{filePath:t}})}export{a as d,t as u};
2 |
--------------------------------------------------------------------------------
/static/js/index.D6nSmJHY.js:
--------------------------------------------------------------------------------
1 | import{b as e,h as s,_ as t,d as a,f as o,c as l,l as d,dc as r,s as p}from"./index.9PHSMUIB.js";const i=p(t(a({__name:"teleport",props:e({to:{type:s([String,Object]),required:!0},disabled:Boolean}),setup:e=>(e,s)=>e.disabled?o(e.$slots,"default",{key:0}):(l(),d(r,{key:1,to:e.to},[o(e.$slots,"default")],8,["to"]))}),[["__file","teleport.vue"]]));export{i as E};
2 |
--------------------------------------------------------------------------------
/static/js/index.D7zGuEZp.js:
--------------------------------------------------------------------------------
1 | import{z as n,at as e,ck as t}from"./index.9PHSMUIB.js";const o=new Map;if(n){let n;document.addEventListener("mousedown",(e=>n=e)),document.addEventListener("mouseup",(e=>{if(n){for(const t of o.values())for(const{documentHandler:o}of t)o(e,n);n=void 0}}))}function s(n,o){let s=[];return e(o.arg)?s=o.arg:t(o.arg)&&s.push(o.arg),function(e,t){const a=o.instance.popperRef,d=e.target,i=null==t?void 0:t.target,u=!o||!o.instance,c=!d||!i,l=n.contains(d)||n.contains(i),r=n===d,g=s.length&&s.some((n=>null==n?void 0:n.contains(d)))||s.length&&s.includes(i),f=a&&(a.contains(d)||a.contains(i));u||c||l||r||g||f||o.value(e,t)}}const a={beforeMount(n,e){o.has(n)||o.set(n,[]),o.get(n).push({documentHandler:s(n,e),bindingFn:e.value})},updated(n,e){o.has(n)||o.set(n,[]);const t=o.get(n),a=t.findIndex((n=>n.bindingFn===e.oldValue)),d={documentHandler:s(n,e),bindingFn:e.value};a>=0?t.splice(a,1,d):t.push(d)},unmounted(n){o.delete(n)}};export{a as C};
2 |
--------------------------------------------------------------------------------
/static/js/internal-doc.B6eN2GGk.js:
--------------------------------------------------------------------------------
1 | import{_ as e}from"./_plugin-vue_export-helper.BCo6x5W8.js";import{c as r,e as s,k as t}from"./index.9PHSMUIB.js";const a={class:"app-container"};const n=e({},[["render",function(e,n){return r(),s("div",a,n[0]||(n[0]=[t("iframe",{src:"https://juejin.cn/post/7228990409909108793",frameborder:"0"},null,-1)]))}],["__scopeId","data-v-7df23cf9"]]);export{n as default};
2 |
--------------------------------------------------------------------------------
/static/js/ip.CWc5zJw-.js:
--------------------------------------------------------------------------------
1 | const h="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M0%20512a512%20512%200%201%200%201024%200A512%20512%200%201%200%200%20512z'%20fill='%23FD8E66'/%3e%3cpath%20d='M377.745%20354.306h63.05l-78.638%20315.388h-63.05l78.638-315.388zm140.642%200h103.519c69.926%200%20117.527%2024.3%2098.942%2098.896-17.958%2072.017-80.148%20104.401-147.89%20104.401H530.77L502.8%20669.694h-63.05l78.637-315.388zm62.702%20153.443c43.489%200%2068.927-18.329%2077.964-54.547%209.153-36.659-10.779-49.018-54.222-49.018h-35.823l-25.833%20103.565h37.914z'%20fill='%23FFF'/%3e%3c/svg%3e";export{h as default};
2 |
--------------------------------------------------------------------------------
/static/js/isUndefined.DgmxjSXK.js:
--------------------------------------------------------------------------------
1 | function i(i){return void 0===i}export{i};
2 |
--------------------------------------------------------------------------------
/static/js/knife4j.C3XegEf8.js:
--------------------------------------------------------------------------------
1 | import{_ as e}from"./_plugin-vue_export-helper.BCo6x5W8.js";import{c as r,e as t,k as a}from"./index.9PHSMUIB.js";const o={class:"app-container"};const s=e({},[["render",function(e,s){return r(),t("div",o,s[0]||(s[0]=[a("iframe",{src:"http://vapi.youlai.tech/doc.html",width:"100%",height:"100%",frameborder:"0"},null,-1)]))}],["__scopeId","data-v-f4490f0d"]]);export{s as default};
2 |
--------------------------------------------------------------------------------
/static/js/language.k0ZPy50U.js:
--------------------------------------------------------------------------------
1 | const h="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='currentColor'%3e%3cpath%20d='m18.5%2010%204.4%2011h-2.155l-1.201-3h-4.09l-1.199%203h-2.154L16.5%2010h2zM10%202v2h6v2h-1.968a18.221%2018.221%200%200%201-3.62%206.301%2014.865%2014.865%200%200%200%202.335%201.707l-.75%201.878A17.016%2017.016%200%200%201%209%2013.725a16.677%2016.677%200%200%201-6.201%203.548l-.536-1.929a14.7%2014.7%200%200%200%205.327-3.042A18.078%2018.078%200%200%201%204.767%208h2.24A16.031%2016.031%200%200%200%209%2010.877a16.165%2016.165%200%200%200%202.91-4.876L2%206V4h6V2h2zm7.5%2010.885L16.253%2016h2.492L17.5%2012.885z'/%3e%3c/svg%3e";export{h as default};
2 |
--------------------------------------------------------------------------------
/static/js/level1.DbJgCAxV.js:
--------------------------------------------------------------------------------
1 | import{av as e,c as t,e as a,a0 as r,w as s,a4 as l}from"./index.9PHSMUIB.js";import{E as o}from"./el-alert.IAJrxUBM.js";import{E as i}from"./el-link.BTv-HaC_.js";import{_ as m}from"./_plugin-vue_export-helper.BCo6x5W8.js";const n={style:{padding:"30px"}};const p=m({},[["render",function(m,p){const u=i,d=e("router-view"),c=o;return t(),a("div",n,[r(u,{href:"https://gitee.com/youlaiorg/vue3-element-admin/blob/master/src/views/demo/multi-level/level1.vue",type:"primary",target:"_blank",class:"mb-10"},{default:s((()=>p[0]||(p[0]=[l("示例源码 请点击>>>>")]))),_:1}),r(c,{closable:!1,title:"菜单一级"},{default:s((()=>[r(d)])),_:1})])}]]);export{p as default};
2 |
--------------------------------------------------------------------------------
/static/js/level2.CXm5yCsd.js:
--------------------------------------------------------------------------------
1 | import{av as e,c as s,e as t,a0 as r,w as a}from"./index.9PHSMUIB.js";import{E as o}from"./el-alert.IAJrxUBM.js";import{_ as i}from"./_plugin-vue_export-helper.BCo6x5W8.js";const l={style:{padding:"30px"}};const n=i({},[["render",function(i,n){const p=e("router-view"),c=o;return s(),t("div",l,[r(c,{closable:!1,title:"菜单二级",type:"success"},{default:a((()=>[r(p)])),_:1})])}]]);export{n as default};
2 |
--------------------------------------------------------------------------------
/static/js/level3-1.veb2CjDd.js:
--------------------------------------------------------------------------------
1 | import{c as e,e as r,a0 as t}from"./index.9PHSMUIB.js";import{E as o}from"./el-alert.IAJrxUBM.js";import{_ as s}from"./_plugin-vue_export-helper.BCo6x5W8.js";const a={style:{padding:"30px"}};const n=s({},[["render",function(s,n){const p=o;return e(),r("div",a,[t(p,{closable:!1,title:"菜单三级-1",type:"error"})])}]]);export{n as default};
2 |
--------------------------------------------------------------------------------
/static/js/level3-2.ehpMX2NG.js:
--------------------------------------------------------------------------------
1 | import{c as e,e as t,a0 as r}from"./index.9PHSMUIB.js";import{E as s}from"./el-alert.IAJrxUBM.js";import{_ as o}from"./_plugin-vue_export-helper.BCo6x5W8.js";const a={style:{padding:"30px"}};const n=o({},[["render",function(o,n){const i=s;return e(),t("div",a,[r(i,{closable:!1,title:"菜单三级-2",type:"warning"})])}]]);export{n as default};
2 |
--------------------------------------------------------------------------------
/static/js/link.BEFJAS5U.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M611.2%20368%20316.8%20662.4c-6.4%206.4-9.6%2016-9.6%2022.4s3.2%2016%209.6%2022.4%2016%209.6%2022.4%209.6%2016-3.2%2022.4-9.6L656%20412.8c6.4-6.4%209.6-16%209.6-22.4s-3.2-16-9.6-22.4c-12.8-12.8-32-12.8-44.8%200z'/%3e%3cpath%20d='m608%20755.2-99.2%2099.2c-96%2096-249.6%2096-342.4%203.2-92.8-92.8-92.8-246.4%203.2-342.4l99.2-99.2c12.8-12.8%2012.8-32%200-44.8s-32-12.8-44.8%200l-99.2%2099.2C3.2%20592%203.2%20784%20121.6%20902.4%20179.2%20960%20259.2%20992%20336%20992c80%200%20156.8-28.8%20217.6-89.6l99.2-99.2c12.8-12.8%2012.8-32%200-44.8s-32-16-44.8-3.2zm294.4-633.6C844.8%2064%20771.2%2035.2%20688%2035.2h-3.2c-83.2%200-160%2035.2-217.6%2092.8l-96%2096c-12.8%2012.8-12.8%2032%200%2044.8s32%2012.8%2044.8%200l96-96c48-48%20108.8-73.6%20172.8-73.6h3.2c64%200%20121.6%2025.6%20166.4%2070.4%2092.8%2092.8%2092.8%20246.4-3.2%20345.6l-96%2096c-12.8%2012.8-12.8%2032%200%2044.8%206.4%206.4%2016%209.6%2022.4%209.6s16-3.2%2022.4-9.6l96-96c121.6-124.8%20124.8-320%206.4-438.4z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/lock.CY-ba69F.js:
--------------------------------------------------------------------------------
1 | const a="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1em'%20height='1em'%20viewBox='0%200%201024%201024'%3e%3cpath%20fill='currentColor'%20d='M224%20448a32%2032%200%200%200-32%2032v384a32%2032%200%200%200%2032%2032h576a32%2032%200%200%200%2032-32V480a32%2032%200%200%200-32-32zm0-64h576a96%2096%200%200%201%2096%2096v384a96%2096%200%200%201-96%2096H224a96%2096%200%200%201-96-96V480a96%2096%200%200%201%2096-96'/%3e%3cpath%20fill='currentColor'%20d='M512%20544a32%2032%200%200%201%2032%2032v192a32%2032%200%201%201-64%200V576a32%2032%200%200%201%2032-32m192-160v-64a192%20192%200%201%200-384%200v64zM512%2064a256%20256%200%200%201%20256%20256v128H256V320A256%20256%200%200%201%20512%2064'/%3e%3c/svg%3e";export{a as default};
2 |
--------------------------------------------------------------------------------
/static/js/menu.CSAxtYMZ.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M374.272%20440.832H127.488c-33.792%200-61.44-27.648-61.44-61.44V132.608c0-33.792%2027.648-61.44%2061.44-61.44h247.296c33.792%200%2061.44%2027.648%2061.44%2061.44v247.296c-.512%2033.792-27.648%2060.928-61.952%2060.928zM127.488%20132.608v247.296h247.296V132.608H127.488zM762.88%20492.032c-16.384%200-31.744-6.144-43.52-17.92L544.768%20299.52c-11.776-11.776-17.92-27.136-17.92-43.52s6.144-31.744%2017.92-43.52L719.36%2037.888c11.776-11.776%2027.136-17.92%2043.52-17.92s31.744%206.144%2043.52%2017.92L980.992%20212.48c11.776%2011.776%2017.92%2027.136%2017.92%2043.52s-6.144%2031.744-17.92%2043.52L806.4%20474.112c-11.776%2011.776-27.136%2017.92-43.52%2017.92zm0-410.624L588.288%20256%20762.88%20430.592%20937.472%20256%20762.88%2081.408zM374.272%20952.832H127.488c-33.792%200-61.44-27.648-61.44-61.44V644.096c0-33.792%2027.648-61.44%2061.44-61.44h247.296c33.792%200%2061.44%2027.648%2061.44%2061.44v247.296c-.512%2034.304-27.648%2061.44-61.952%2061.44zM127.488%20644.608v247.296h247.296V644.608H127.488zm758.784%20308.224H638.976c-33.792%200-61.44-27.648-61.44-61.44V644.096c0-33.792%2027.648-61.44%2061.44-61.44h247.296c33.792%200%2061.44%2027.648%2061.44%2061.44v247.296c0%2034.304-27.136%2061.44-61.44%2061.44zM639.488%20644.608v247.296h247.296V644.608H639.488z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/message.DnO64dGf.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M0%20512a512%20512%200%201%200%201024%200A512%20512%200%201%200%200%20512z'%20fill='%2350DCB6'/%3e%3cpath%20d='M790.148%20502.822c0-30.856-25.013-55.87-55.869-55.87H483.666c-30.855%200-55.869%2025.014-55.869%2055.87v158.432c0%2030.856%2025.014%2055.87%2055.87%2055.87h229.557a47.894%2047.894%200%200%201%2026.28%207.854l35.81%2023.508c6.37%204.18%2014.834-.388%2014.834-8.007V502.822z'%20fill='%23FFF'%20fill-opacity='.4'/%3e%3cpath%20d='M233.852%20320.848c0-30.856%2025.013-55.869%2055.869-55.869h366.341c30.856%200%2055.87%2025.013%2055.87%2055.869v245.026c0%2030.855-25.014%2055.869-55.87%2055.869h-325.28a47.894%2047.894%200%200%200-26.295%207.865l-55.799%2036.66c-6.369%204.185-14.836-.384-14.836-8.004V320.848z'%20fill='%23FFF'/%3e%3cpath%20d='M323.242%20446.952a34.32%2034.32%200%201%200%2068.64%200%2034.32%2034.32%200%201%200-68.64%200zm115.729%200a34.32%2034.32%200%201%200%2068.64%200%2034.32%2034.32%200%201%200-68.64%200zm115.729%200a34.32%2034.32%200%201%200%2068.639%200%2034.32%2034.32%200%201%200-68.64%200z'%20fill='%2346D7B0'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/monitor.Cm5WDh5_.js:
--------------------------------------------------------------------------------
1 | const e="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cdefs%3e%3cstyle%3e@font-face{font-family:rbicon;src:url(chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2)%20format("woff2");font-weight:400;font-style:normal}%3c/style%3e%3c/defs%3e%3cpath%20d='M64%2064v576h832V64H64zM0%200h960v704H0V0z'/%3e%3cpath%20d='M192%20896h576v64H192zm256-256h64v256h-64zm31.232-78.396%20309.99-348.33-47.803-42.548-259.567%20291.67-177.895-222.387L163.21%20438.605l52.224%2037.009%2091.622-129.28z'/%3e%3c/svg%3e";export{e as default};
2 |
--------------------------------------------------------------------------------
/static/js/moon.BACaCO3C.js:
--------------------------------------------------------------------------------
1 | const a="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='currentColor'%3e%3cpath%20d='M10%207a7%207%200%200%200%2012%204.9v.1c0%205.523-4.477%2010-10%2010S2%2017.523%202%2012%206.477%202%2012%202h.1A6.98%206.98%200%200%200%2010%207zm-6%205a8%208%200%200%200%2015.062%203.762A9%209%200%200%201%208.238%204.938%207.999%207.999%200%200%200%204%2012z'/%3e%3c/svg%3e";export{a as default};
2 |
--------------------------------------------------------------------------------
/static/js/order.BSEhtWEN.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M0%20512a512%20512%200%201%200%201024%200A512%20512%200%201%200%200%20512z'%20fill='%23F15BB5'/%3e%3cpath%20d='m772%20432.8-7.9-63.3v-.2c-.1-1-.4-2.1-.7-3.1v-.3l-.2-.4-25.7-72.1c-.3-.7-.6-1.5-1-2.2-7-14.4-21.5-23.7-37.5-24h-24.1c-10%200-18.6%207.8-18.9%2017.8-.4%2010.5%208%2019.1%2018.4%2019.1H699c1.9.3%203.4%201.4%204.2%203.1l13.5%2037.9c.7%201.9.4%203.9-.7%205.6-1.1%201.6-3%202.6-5%202.6h-67.3c-3.5%200-6.2-2.8-6.2-6.2v-24.5c0-67.9-55.1-123-123-123s-123%2055.1-123%20123v24.5c0%203.5-2.8%206.2-6.2%206.2h-69.8c-3.4%200-6.2-2.8-6.2-6.2%200-.8.2-1.6.5-2.3l15.5-36.8c.7-2.1%202.5-3.5%204.7-3.9h24.1c10%200%2018.6-7.8%2018.9-17.8.4-10.5-8-19.1-18.4-19.1H330c-16.5.5-31.3%2010.2-38.1%2025.3l-30.6%2072.1v.2c-.2.4-.3.8-.5%201.2v.4c-.3%201-.6%202.1-.7%203.1l-39%20310.8c-6.4%2050.5%2029.5%2096.7%2080.1%20103%203.8.5%207.7.7%2011.5.7h94.5C514.8%20718.5%20680.7%20597.9%20772%20432.8zM440.7%20322.5c0-41%2033.3-74.1%2074.3-73.8%2040.7.3%2073.3%2034.1%2073.3%2074.8V347c0%203.5-2.8%206.2-6.2%206.2H446.9c-3.5%200-6.2-2.8-6.2-6.2v-24.5zm152.7%20257L514%20662.4c-2.3%202.4-6.3%202.5-8.7.2l-.2-.2-79.4-82.9c-15.1-15.1-18.8-38.2-9.3-57.3%2013.4-26.8%2047.7-36.1%2073.3-18.2%202.3%201.6%204.4%203.5%206.4%205.5l9.2%209.2c2.4%202.4%206.3%202.4%208.7%200l9.4-9.4c19.4-19.4%2050.8-19.4%2070.2%200%2019.3%2019.4%2019.3%2050.8-.2%2070.2z'%20fill='%23FFFDF3'/%3e%3cpath%20d='M803.7%20691.6c0-3.8-.3-7.7-.7-11.4l-31-247.4c-91.3%20165.1-257.2%20285.7-364.8%20351h304.1c51%200%2092.4-41.2%2092.4-92.2z'%20fill='%23FFF'%20opacity='.9'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/peoples.B_DDm2CM.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M520.235%20504.577c51.305-33.512%2085.254-91.477%2085.254-157.301%200-103.485-84.273-187.757-187.758-187.757S229.974%20243.79%20229.974%20347.275c0%2065.715%2033.95%20123.68%2085.255%20157.301-47.266%2015.72-90.603%2042.245-126.845%2078.486-61.24%2061.24-94.97%20142.675-94.97%20229.239%200%2013.318%2010.698%2024.016%2024.015%2024.016s24.015-10.699%2024.015-24.016c0-152.28%20123.899-276.177%20276.178-276.177S693.801%20660.02%20693.801%20812.302c0%2013.318%2010.697%2024.016%2024.014%2024.016s24.016-10.699%2024.016-24.016c0-86.564-33.73-168-94.97-229.237-36.024-36.134-79.36-62.768-126.627-78.488zm-242.23-157.192c0-77.067%2062.658-139.726%20139.726-139.726s139.727%2062.658%20139.727%20139.726-62.66%20139.726-139.727%20139.726c-76.958%200-139.726-62.659-139.726-139.726z'/%3e%3cpath%20d='M871.406%20599.002a323.731%20323.731%200%200%200-150.643-119.86c27.072-40.28%2041.481-87.765%2041.045-136.778-.437-59.602-22.706-116.694-62.55-160.795-8.95-9.824-24.124-10.589-33.95-1.637-9.823%208.951-10.587%2024.125-1.637%2033.949%2066.7%2073.575%2067.135%20185.138.983%20259.477-1.528%201.746-2.837%203.71-3.712%205.675-1.2%201.856-2.074%203.93-2.729%206.222-3.492%2012.773%204.15%2025.981%2016.92%2029.474C807.11%20550.097%20892.366%20674.323%20878.065%20809.9c-1.419%2013.208%208.188%2024.998%2021.396%2026.417.873.109%201.746.109%202.51.109%2012.117%200%2022.597-9.17%2023.907-21.504%207.968-75.868-11.353-152.608-54.471-215.921z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/position.CopxYfyp.js:
--------------------------------------------------------------------------------
1 | import{z as t}from"./index.9PHSMUIB.js";const e=(e,n)=>{if(!t||!e||!n)return!1;const i=e.getBoundingClientRect();let o;return o=n instanceof Element?n.getBoundingClientRect():{top:0,right:window.innerWidth,bottom:window.innerHeight,left:0},i.topo.top&&i.right>o.left&&i.left{let e,n;return"touchend"===t.type?(n=t.changedTouches[0].clientY,e=t.changedTouches[0].clientX):t.type.startsWith("touch")?(n=t.touches[0].clientY,e=t.touches[0].clientX):(n=t.clientY,e=t.clientX),{clientX:e,clientY:n}};export{n as g,e as i};
2 |
--------------------------------------------------------------------------------
/static/js/project.BeKcDOO0.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M0%20512a512%20512%200%201%200%201024%200A512%20512%200%201%200%200%20512z'%20fill='%2369ADF4'/%3e%3cpath%20d='m562.058%20278.412%2042.198-12.096q35.292-10.117%2045.409%2025.176l117.221%20408.934q10.117%2035.292-25.176%2045.409l-42.197%2012.096q-35.293%2010.117-45.41-25.176l-117.22-408.934q-10.118-35.292%2025.175-45.41z'%20fill='%23FFF'%20opacity='.4'/%3e%3cpath%20d='M284.134%20263.383c-20.276%200-36.714%2016.437-36.714%2036.714v43.897a7.981%207.981%200%200%200%207.981%207.981h55.47c13.444%200%2024.343%2010.899%2024.343%2024.343s-10.899%2024.343-24.343%2024.343h-55.47a7.981%207.981%200%200%200-7.98%207.981V725.5c0%2020.276%2016.437%2036.714%2036.713%2036.714h43.897c20.276%200%2036.714-16.438%2036.714-36.714V300.097c0-20.277-16.438-36.714-36.714-36.714h-43.897zm152.443%200c-20.276%200-36.714%2016.437-36.714%2036.714v122.912a7.981%207.981%200%200%200%207.981%207.98h49.085c13.444%200%2024.343%2010.9%2024.343%2024.344s-10.9%2024.343-24.343%2024.343h-49.085a7.981%207.981%200%200%200-7.981%207.981V725.5c0%2020.276%2016.438%2036.714%2036.714%2036.714h43.897c20.276%200%2036.714-16.438%2036.714-36.714V300.097c0-20.277-16.438-36.714-36.714-36.714h-43.897z'%20fill='%23FFF'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/publish.B4gIpoLD.js:
--------------------------------------------------------------------------------
1 | const l="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M924.146%20233.09v-3.216l-.643-.642v-2.572l-.642-.642v-.643l-.643-.643h-.643l-.642-.642v-.643l-1.93-1.929v-.642l-.642-.643v-1.286h-1.929l-.643-.643h-1.286l-.642-.643v-.642h-.643v-.643h-.643l-.642-.643h-.643v-.642h-2.572v-.643h-5.144l-.642.643h-.643v.642h-1.286l-.643.643h-1.286L112.708%20516c-10.287%203.858-15.431%2014.789-11.574%2025.719%202.572%205.787%207.073%209.644%2012.217%2011.573l235.972%2094.518%2024.433%20135.668c1.93%2010.931%2012.217%2017.36%2022.505%2016.074%204.5-.643%208.358-3.215%2010.931-6.43l87.445-87.444%20178.104%2071.37c10.287%203.858%2021.218-.642%2025.719-10.287l223.756-523.383.642-.643v-7.073l1.288-2.571zM364.113%20610.517%20173.79%20534.646l604.399-230.83-414.077%20306.7zm41.15%20127.952-12.86-74.586%2062.369%2025.076-49.509%2049.51zm264.906-5.143L406.55%20627.877%20858.562%20293.53%20670.17%20733.326z'/%3e%3c/svg%3e";export{l as default};
2 |
--------------------------------------------------------------------------------
/static/js/refresh.B5ExwFoE.js:
--------------------------------------------------------------------------------
1 | const e="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20aria-hidden='true'%20width='1em'%20height='1em'%20viewBox='0%200%20512%20512'%3e%3cpath%20d='m400%20148-21.12-24.57A191.43%20191.43%200%200%200%20240%2064C134%2064%2048%20150%2048%20256s86%20192%20192%20192a192.09%20192.09%200%200%200%20181.07-128'%20fill='none'%20stroke='currentColor'%20stroke-linecap='square'%20stroke-miterlimit='10'%20stroke-width='32'/%3e%3cpath%20d='M464%2068.45V220a4%204%200%200%201-4%204H308.45a4%204%200%200%201-2.83-6.83L457.17%2065.62a4%204%200%200%201%206.83%202.83z'%20fill='currentColor'/%3e%3c/svg%3e";export{e as default};
2 |
--------------------------------------------------------------------------------
/static/js/refs.CNClepWF.js:
--------------------------------------------------------------------------------
1 | import{bc as o}from"./index.9PHSMUIB.js";const a=(...a)=>c=>{a.forEach((a=>{o(a)?a(c):a.value=c}))};export{a as c};
2 |
--------------------------------------------------------------------------------
/static/js/role.DDpGZwDf.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='256'%20height='256'%3e%3cpath%20d='M79.238%20961.896v-25.442c0-109.28%2028.835-214.892%2081.139-297.416%2048.427-76.396%20115.304-131.573%20195.508-161.896A240.785%20240.785%200%200%201%20279.488%20300.5c0-131.538%20104.331-238.535%20232.547-238.535S744.546%20168.962%20744.546%20300.5a240.854%20240.854%200%200%201-76.742%20176.988c190.87%2073.004%20276.992%20277.131%20276.992%20458.966v25.442H79.238zM694.908%20300.5c0-103.43-82.039-187.615-182.873-187.615-100.835%200-182.873%2084.184-182.873%20187.615%200%20103.465%2082.038%20187.65%20182.873%20187.65%20100.834%200%20182.873-84.185%20182.873-187.65zm-79.166%20213.508a226.454%20226.454%200%200%201-103.707%2025.096A225.935%20225.935%200%200%201%20407.912%20513.8C212.888%20564.927%20136.804%20752.854%20129.5%20910.977h765.035c-7.997-167.4-95.227-347.746-278.793-396.97zm-143.411%2037.246h79.407l39.739-8.48-45.242%2065.664%2030.6%20227.527-64.8%2056.908-69.197-56.908%2040.535-227.527-50.78-65.665%2039.738%208.48z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/setting.CfydkD5J.js:
--------------------------------------------------------------------------------
1 | const a="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='currentColor'%3e%3cpath%20d='m12%201%209.5%205.5v11L12%2023l-9.5-5.5v-11L12%201zm0%202.311L4.5%207.653v8.694l7.5%204.342%207.5-4.342V7.653L12%203.311zM12%2016a4%204%200%201%201%200-8%204%204%200%200%201%200%208zm0-2a2%202%200%201%200%200-4%202%202%200%200%200%200%204z'/%3e%3c/svg%3e";export{a as default};
2 |
--------------------------------------------------------------------------------
/static/js/size.C48ZYpz_.js:
--------------------------------------------------------------------------------
1 | const v="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='currentColor'%3e%3cpath%20d='M10%206v15H8V6H2V4h14v2h-6zm8%208v7h-2v-7h-3v-2h8v2h-3z'/%3e%3c/svg%3e";export{v as default};
2 |
--------------------------------------------------------------------------------
/static/js/strings.CQ_np2th.js:
--------------------------------------------------------------------------------
1 | import{cA as e}from"./index.9PHSMUIB.js";const a=(e="")=>e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d"),c=a=>e(a);export{c,a as e};
2 |
--------------------------------------------------------------------------------
/static/js/sunny.Cx4iEVwd.js:
--------------------------------------------------------------------------------
1 | const v="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='currentColor'%3e%3cpath%20d='M12%2018a6%206%200%201%201%200-12%206%206%200%200%201%200%2012zm0-2a4%204%200%201%200%200-8%204%204%200%200%200%200%208zM11%201h2v3h-2V1zm0%2019h2v3h-2v-3zM3.515%204.929l1.414-1.414L7.05%205.636%205.636%207.05%203.515%204.93zM16.95%2018.364l1.414-1.414%202.121%202.121-1.414%201.414-2.121-2.121zm2.121-14.85%201.414%201.415-2.121%202.121-1.414-1.414%202.121-2.121zM5.636%2016.95l1.414%201.414-2.121%202.121-1.414-1.414%202.121-2.121zM23%2011v2h-3v-2h3zM4%2011v2H1v-2h3z'/%3e%3c/svg%3e";export{v as default};
2 |
--------------------------------------------------------------------------------
/static/js/swagger.BGskywol.js:
--------------------------------------------------------------------------------
1 | import{_ as e}from"./_plugin-vue_export-helper.BCo6x5W8.js";import{c as r,e as t,k as a}from"./index.9PHSMUIB.js";const s={class:"app-container"};const i=e({},[["render",function(e,i){return r(),t("div",s,i[0]||(i[0]=[a("iframe",{src:"http://vapi.youlai.tech/swagger-ui.html",width:"100%",height:"100%",frameborder:"0"},null,-1)]))}],["__scopeId","data-v-56050cf3"]]);export{i as default};
2 |
--------------------------------------------------------------------------------
/static/js/system.BjyKXCM4.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M139%20669.6V164.3c0-12.7%2010.3-23.1%2023.1-23.1h694.4c12.7%200%2023.1%2010.4%2023.1%2023.1v248.5h70V164.3c0-51.3-41.8-93.1-93.1-93.1H162c-51.3.1-93%2041.8-93%2093.1v505.3c0%2051.3%2041.8%2093.1%2093.1%2093.1h224.7v-70H162c-12.7%200-23-10.4-23-23.1zm-34.3%20131h282v70h-282z'/%3e%3cpath%20d='m954.9%20599.4-5.1-15c-11.5-33.9-29.4-64.9-53.2-91.9l-10.5-11.9h-83.2l-41.7-72.2-15.6-3.1c-34.8-6.9-71.3-6.9-106.1%200l-15.6%203.1-41.7%2072.2H499l-10.5%2011.9c-23.8%2027.1-41.7%2058-53.2%2091.9l-5.1%2015%2041.7%2072.2-41.7%2072.2%205.1%2015c11.5%2033.9%2029.4%2064.9%2053.2%2091.9l10.5%2011.9h83.2l41.7%2072.2%2015.6%203.1c17.4%203.5%2035.3%205.2%2053.1%205.2s35.6-1.8%2053.1-5.2l15.6-3.1%2041.7-72.2h83.2l10.5-11.9c23.8-27.1%2041.7-58%2053.2-91.9l5.1-15-41.7-72.2%2041.6-72.2zm-76.8%20151.2c-6.4%2014.9-14.5%2029-24.3%2042h-91.2l-45.6%2079c-16.1%201.9-32.4%201.9-48.5%200l-45.6-79h-91.2c-9.8-13-17.9-27-24.3-42l45.6-79.1-45.6-79.1c6.4-14.9%2014.5-29%2024.3-42h91.2l45.6-79c16.1-1.9%2032.4-1.9%2048.5%200l45.6%2079h91.2c9.8%2013%2017.9%2027%2024.3%2042l-45.6%2079.1%2045.6%2079.1z'/%3e%3cpath%20d='M692.7%20560.2c-61.4%200-111.3%2049.9-111.3%20111.3s49.9%20111.3%20111.3%20111.3S804%20732.9%20804%20671.5c0-61.3-49.9-111.3-111.3-111.3zm0%20152.7c-22.8%200-41.3-18.5-41.3-41.3s18.5-41.3%2041.3-41.3%2041.3%2018.5%2041.3%2041.3-18.5%2041.3-41.3%2041.3z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/table.C6Xt0YCE.js:
--------------------------------------------------------------------------------
1 | const h="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M0%2064v896h1024V64H0zm384%20576V448h256v192H384zm256%2064v192H384V704h256zm0-512v192H384V192h256zm-320%200v192H64V192h256zM64%20448h256v192H64V448zm640%200h256v192H704V448zm0-64V192h256v192H704zM64%20704h256v192H64V704zm640%20192V704h256v192H704z'/%3e%3c/svg%3e";export{h as default};
2 |
--------------------------------------------------------------------------------
/static/js/temp.gJIG3-Be.js:
--------------------------------------------------------------------------------
1 | import{bd as t}from"./index.9PHSMUIB.js";function e(){return t({url:"/api/v1/template/get",method:"get"})}function a(e){return t({url:"/api/v1/template/add",method:"post",data:e,headers:{"Content-Type":"multipart/form-data"}})}function r(e){return t({url:"/api/v1/template/update",method:"post",data:e,headers:{"Content-Type":"multipart/form-data"}})}function o(e){return t({url:"/api/v1/template/delete",method:"post",data:e,headers:{"Content-Type":"multipart/form-data"}})}export{a as A,o as D,r as U,e as g};
2 |
--------------------------------------------------------------------------------
/static/js/todolist.CQls5pqo.js:
--------------------------------------------------------------------------------
1 | const l="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M0%20512a512%20512%200%201%200%201024%200A512%20512%200%201%200%200%20512z'%20fill='%23FF8F41'/%3e%3cpath%20d='M466.107%20217.091h93.382q29.53%200%2029.53%2029.531v51.08q0%2029.531-29.53%2029.531h-93.381q-29.531%200-29.531-29.53v-51.081q0-29.53%2029.53-29.53zm253.476%20125.01%2040.039-17.701c3.508-1.55%204.021-6.316.924-8.579l-55.735-40.715c-3.096-2.263-7.481-.325-7.89%203.488l-4.477%2041.544-58.874%2080.592%2028.157%2020.568%2057.856-79.197z'%20fill='%23FFF'%20opacity='.4'/%3e%3cpath%20d='M263.383%20521.178a249.016%20249.016%200%201%200%20498.032%200%20249.016%20249.016%200%201%200-498.032%200z'%20fill='%23FFF'/%3e%3cpath%20d='M512.4%20348.383c9.917%200%2017.957%208.04%2017.957%2017.958v143.565l97.432%2055.102c8.634%204.882%2011.674%2015.839%206.792%2024.471-4.882%208.634-15.84%2011.674-24.472%206.791l-106.55-60.258a17.958%2017.958%200%200%201-9.118-15.632V366.341c0-9.917%208.04-17.958%2017.958-17.958z'%20fill='%23FF8F41'/%3e%3cpath%20d='M472.493%20524.371a40.705%2040.705%200%201%200%2081.409%200%2040.705%2040.705%200%201%200-81.41%200z'%20fill='%23FF8338'/%3e%3c/svg%3e";export{l as default};
2 |
--------------------------------------------------------------------------------
/static/js/tree.ByH7Oq4A.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M977.455%20558.545h-34.91V453.818c0-44.218-37.236-81.454-81.454-81.454H546.909v-93.091h197.818c25.6%200%2046.546-20.946%2046.546-46.546V93.091c0-25.6-20.946-46.546-46.546-46.546H279.273c-25.6%200-46.546%2020.946-46.546%2046.546v139.636c0%2025.6%2020.946%2046.546%2046.546%2046.546H477.09v93.09H162.909c-44.218%200-81.454%2037.237-81.454%2081.455v104.727h-34.91C20.945%20558.545%200%20579.491%200%20605.091v325.818c0%2025.6%2020.945%2046.546%2046.545%2046.546h139.637c25.6%200%2046.545-20.946%2046.545-46.546V605.091c0-25.6-20.945-46.546-46.545-46.546h-34.91V453.818c0-6.982%204.655-11.636%2011.637-11.636h314.182v116.363h-34.91c-25.6%200-46.545%2020.946-46.545%2046.546v325.818c0%2025.6%2020.946%2046.546%2046.546%2046.546h139.636c25.6%200%2046.546-20.946%2046.546-46.546V605.091c0-25.6-20.946-46.546-46.546-46.546H546.91V442.182h314.182c6.982%200%2011.636%204.654%2011.636%2011.636v104.727h-34.909c-25.6%200-46.545%2020.946-46.545%2046.546v325.818c0%2025.6%2020.945%2046.546%2046.545%2046.546h139.637c25.6%200%2046.545-20.946%2046.545-46.546V605.091c0-25.6-20.945-46.546-46.545-46.546zm-814.546%2069.819v279.272H69.82V628.364h93.09zm395.636%200v279.272h-93.09V628.364h93.09zm-256-418.91v-93.09h418.91v93.09h-418.91zm651.637%20698.182H861.09V628.364h93.09v279.272z'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/user.m7vGTRps.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M599.378%20958.454H424.62c-165.805%200-296.769%200-296.769-86.024v-17.178c0-161.188%20133.115-292.258%20296.77-292.258h174.756c163.619%200%20296.769%20131.102%20296.769%20292.258v17.178c0%2086.024-137.557%2086.024-296.768%2086.024zm-176.39-346.981c-137.625%200-249.608%20109.935-249.608%20245.098v17.491c0%2035.046%20144.255%2035.046%20249.608%2035.046h177.985c87.207%200%20249.645%200%20249.645-35.046v-17.491c0-135.163-112.018-245.098-249.645-245.098H422.988zm80.266-83.526c-129.923%200-235.555-104.14-235.555-232.12%200-128.015%20105.632-232.119%20235.555-232.119s235.554%20104.104%20235.554%20232.12c0%20127.978-105.7%20232.12-235.554%20232.12zM316.246%20295.098c0%20101.224%2083.91%20183.572%20187.008%20183.572%20103.133%200%20187.042-82.348%20187.042-183.572%200-101.19-83.909-183.502-187.042-183.502-103.134%200-187.008%2082.311-187.008%20183.502zm0%2017.767'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/static/js/visit.BtczcFYa.js:
--------------------------------------------------------------------------------
1 | const c="data:image/svg+xml,%3csvg%20class='icon'%20viewBox='0%200%201024%201024'%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3e%3cpath%20d='M6.536%20518.536a501.106%20501.106%200%201%200%201002.213%200%20501.106%20501.106%200%201%200-1002.213%200z'%20fill='%23FA6B6D'/%3e%3cpath%20d='M513.09%20262.536c68.63%200%20125.276%2055.558%20125.276%20123.098%200%2067.54-55.557%20123.098-125.277%20123.098-68.63%200-125.276-55.558-125.276-123.098%201.09-68.63%2056.647-123.098%20125.276-123.098zm0%200c68.63%200%20125.276%2055.558%20125.276%20123.098%200%2067.54-55.557%20123.098-125.277%20123.098-68.63%200-125.276-55.558-125.276-123.098%201.09-68.63%2056.647-123.098%20125.276-123.098zm-46.843%20286.502h104.579c89.327%200%20161.225%2070.809%20161.225%20159.047v9.804c0%2034.86-71.898%2035.95-161.225%2035.95h-104.58c-89.327%200-161.225%200-161.225-35.95v-9.804c0-88.238%2072.988-159.047%20161.226-159.047z'%20fill='%23FFF'/%3e%3c/svg%3e";export{c as default};
2 |
--------------------------------------------------------------------------------
/utils/capatcha.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "image/color"
5 |
6 | "github.com/mojocn/base64Captcha"
7 | )
8 |
9 | var store = base64Captcha.DefaultMemStore
10 |
11 | // GetCaptcha 获取验证码
12 | func GetCaptcha() (string, string, string, error) {
13 | driver := base64Captcha.NewDriverMath(60, 180, 80, 0, &color.RGBA{255, 255, 255, 255}, nil, nil)
14 | return base64Captcha.NewCaptcha(driver, store).Generate()
15 | }
16 |
17 | // VerifyCaptcha 验证验证码
18 | func VerifyCaptcha(id string, answer string) bool {
19 | return store.Verify(id, answer, true)
20 | }
21 |
--------------------------------------------------------------------------------
/utils/log.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "io"
5 | "log"
6 | "os"
7 | "time"
8 | )
9 |
10 | func Loginit() {
11 | t := time.Now().Format("2006-01-02") + ".log"
12 | // 检查目录是否创建
13 | _, err := os.Stat("./logs")
14 | if err != nil {
15 | if os.IsNotExist(err) {
16 | os.Mkdir("./logs", os.ModePerm)
17 | }
18 | }
19 | // 创建一个文件
20 | file, err := os.OpenFile("./logs/"+t, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
21 | if err != nil {
22 | log.Fatal(err)
23 | }
24 | // 设置log输出到控制台
25 | mw := io.MultiWriter(os.Stdout, file)
26 | // 设置log的输出位置为这个文件
27 | log.SetFlags(log.LstdFlags | log.Lshortfile)
28 | log.SetOutput(mw)
29 | }
30 |
--------------------------------------------------------------------------------
/utils/menus.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import "encoding/json"
4 |
5 | type Meta struct {
6 | Title string `json:"title"`
7 | Icon string `json:"icon"`
8 | Hidden bool `json:"hidden"`
9 | Roles []string `json:"roles"`
10 | KeepAlive bool `json:"keepAlive,omitempty"`
11 | }
12 |
13 | type Child struct {
14 | Path string `json:"path"`
15 | Component string `json:"component"`
16 | Name string `json:"name"`
17 | Meta Meta `json:"meta"`
18 | }
19 |
20 | type Menu struct {
21 | Path string `json:"path"`
22 | Component string `json:"component"`
23 | Redirect string `json:"redirect"`
24 | Name string `json:"name"`
25 | Meta Meta `json:"meta"`
26 | Children []Child `json:"children"`
27 | }
28 |
29 | func GetMenus() []byte {
30 | menus := []Menu{
31 | {
32 | Path: "/system",
33 | Component: "Layout",
34 | Redirect: "/system/user",
35 | Name: "/system",
36 | Meta: Meta{
37 | Title: "系统管理",
38 | Icon: "system",
39 | Hidden: false,
40 | Roles: []string{"admin"},
41 | },
42 | Children: []Child{
43 | {
44 | Path: "user",
45 | Component: "system/user/index",
46 | Name: "User",
47 | Meta: Meta{
48 | Title: "用户管理",
49 | Icon: "user",
50 | Hidden: false,
51 | Roles: []string{"admin"},
52 | KeepAlive: true,
53 | },
54 | },
55 | },
56 | },
57 | }
58 | jsonMenus, _ := json.Marshal(menus)
59 | return jsonMenus
60 | }
61 |
--------------------------------------------------------------------------------
/utils/mkdir.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import "os"
4 |
5 | func isMkdir(filename string) error {
6 | // 检查目录是否创建
7 | _, err := os.Stat(filename)
8 | if err != nil {
9 | if os.IsNotExist(err) {
10 | return os.MkdirAll(filename, os.ModePerm)
11 | }
12 | }
13 | return nil
14 | }
15 |
--------------------------------------------------------------------------------
/webs/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | # 表示所有文件适用
5 | [*]
6 | charset = utf-8 # 设置文件字符集为 utf-8
7 | end_of_line = lf # 控制换行类型(lf | cr | crlf)
8 | indent_style = space # 缩进风格(tab | space)
9 | indent_size = 2 # 缩进大小
10 | insert_final_newline = true # 始终在文件末尾插入一个新行
11 |
12 | # 表示仅 md 文件适用以下规则
13 | [*.md]
14 | max_line_length = off # 关闭最大行长度限制
15 | trim_trailing_whitespace = false # 关闭末尾空格修剪
16 |
--------------------------------------------------------------------------------
/webs/.env.development:
--------------------------------------------------------------------------------
1 | ## 开发环境
2 | NODE_ENV='development'
3 |
4 | # 应用端口
5 | VITE_APP_PORT = 8081
6 |
7 | # 代理前缀
8 | VITE_APP_BASE_API = '/dev-api'
9 |
10 | # 线上接口地址
11 | # VITE_APP_API_URL = http://vapi.youlai.tech
12 | # 开发接口地址
13 | VITE_APP_API_URL = http://localhost:8000
14 |
15 | # 是否启用 Mock 服务
16 | VITE_MOCK_DEV_SERVER = false
17 |
--------------------------------------------------------------------------------
/webs/.env.production:
--------------------------------------------------------------------------------
1 | ## 生产环境
2 | NODE_ENV='production'
3 |
4 | # 代理前缀
5 | # VITE_APP_BASE_API = '/prod-api'
6 |
7 | VITE_APP_API_URL = ''
8 |
--------------------------------------------------------------------------------
/webs/.eslintignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 | public
4 | .husky
5 | .vscode
6 | .idea
7 | *.sh
8 | *.md
9 |
10 | src/assets
11 |
12 | .eslintrc.cjs
13 | .prettierrc.cjs
14 | .stylelintrc.cjs
15 |
--------------------------------------------------------------------------------
/webs/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | dist-ssr
5 | *.local
6 | .history
7 |
8 | # Editor directories and files
9 | .idea
10 | *.suo
11 | *.ntvs*
12 | *.njsproj
13 | *.sln
14 | *.local
15 |
16 | package-lock.json
17 | pnpm-lock.yaml
18 | stats.html
--------------------------------------------------------------------------------
/webs/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | npx --no-install commitlint --edit $1
2 |
--------------------------------------------------------------------------------
/webs/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | npm run lint:lint-staged
2 |
--------------------------------------------------------------------------------
/webs/.prettierignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 | public
4 | .husky
5 | .vscode
6 | .idea
7 | *.sh
8 | *.md
9 |
10 | src/assets
11 | stats.html
12 |
--------------------------------------------------------------------------------
/webs/.prettierrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // (x)=>{},单个参数箭头函数是否显示小括号。(always:始终显示;avoid:省略括号。默认:always)
3 | arrowParens: "always",
4 | // 开始标签的右尖括号是否跟随在最后一行属性末尾,默认false
5 | bracketSameLine: false,
6 | // 对象字面量的括号之间打印空格 (true - Example: { foo: bar } ; false - Example: {foo:bar})
7 | bracketSpacing: true,
8 | // 是否格式化一些文件中被嵌入的代码片段的风格(auto|off;默认auto)
9 | embeddedLanguageFormatting: "auto",
10 | // 指定 HTML 文件的空格敏感度 (css|strict|ignore;默认css)
11 | htmlWhitespaceSensitivity: "css",
12 | // 当文件已经被 Prettier 格式化之后,是否会在文件顶部插入一个特殊的 @format 标记,默认false
13 | insertPragma: false,
14 | // 在 JSX 中使用单引号替代双引号,默认false
15 | jsxSingleQuote: false,
16 | // 每行最多字符数量,超出换行(默认80)
17 | printWidth: 80,
18 | // 超出打印宽度 (always | never | preserve )
19 | proseWrap: "preserve",
20 | // 对象属性是否使用引号(as-needed | consistent | preserve;默认as-needed:对象的属性需要加引号才添加;)
21 | quoteProps: "as-needed",
22 | // 是否只格式化在文件顶部包含特定注释(@prettier| @format)的文件,默认false
23 | requirePragma: false,
24 | // 结尾添加分号
25 | semi: true,
26 | // 使用单引号 (true:单引号;false:双引号)
27 | singleQuote: false,
28 | // 缩进空格数,默认2个空格
29 | tabWidth: 2,
30 | // 元素末尾是否加逗号,默认es5: ES5中的 objects, arrays 等会添加逗号,TypeScript 中的 type 后不加逗号
31 | trailingComma: "es5",
32 | // 指定缩进方式,空格或tab,默认false,即使用空格
33 | useTabs: false,
34 | // vue 文件中是否缩进 ",
19 | ""
20 | ],
21 | "description": "Vue3.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/webs/.vscode/vue3.2.code-snippets:
--------------------------------------------------------------------------------
1 | {
2 | "Vue3.2+快速生成模板": {
3 | "scope": "vue",
4 | "prefix": "Vue3.2+",
5 | "body": [
6 | "",
7 | "",
8 | "",
9 | " ${1:test}
",
10 | " ",
11 | "",
12 | "",
13 | ""
14 | ],
15 | "description": "Vue3.2+"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/webs/.vscode/vue3.3.code-snippets:
--------------------------------------------------------------------------------
1 | {
2 | "Vue3.3+defineOptions快速生成模板": {
3 | "scope": "vue",
4 | "prefix": "Vue3.3+",
5 | "body": [
6 | "",
11 | "",
12 | "",
13 | " ${1:test}
",
14 | " ",
15 | "",
16 | "",
17 | ""
18 | ],
19 | "description": "Vue3.3+defineOptions快速生成模板"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/webs/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021-present 有来开源组织
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 |
--------------------------------------------------------------------------------
/webs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | sublinkX节点订阅管理系统
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
58 |
59 |
--------------------------------------------------------------------------------
/webs/licenses/vue-element-admin/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017-present PanJiaChen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/webs/licenses/vue3-element-admin/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021-present 有来开源组织
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 |
--------------------------------------------------------------------------------
/webs/mock/base.ts:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import { createDefineMock } from "vite-plugin-mock-dev-server";
3 |
4 | export const defineMock = createDefineMock((mock) => {
5 | // 拼接url
6 | mock.url = path.join(
7 | import.meta.env.VITE_APP_BASE_API + "/api/v1/",
8 | mock.url
9 | );
10 | });
11 |
--------------------------------------------------------------------------------
/webs/public/avatar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/webs/public/avatar.gif
--------------------------------------------------------------------------------
/webs/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/webs/public/favicon.ico
--------------------------------------------------------------------------------
/webs/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
37 |
--------------------------------------------------------------------------------
/webs/src/api/auth/index.ts:
--------------------------------------------------------------------------------
1 | import request from "@/utils/request";
2 | import { AxiosPromise } from "axios";
3 | import { CaptchaResult, LoginData, LoginResult , VersionResult } from "./types";
4 |
5 | /**
6 | * 登录API
7 | *
8 | * @param data {LoginData}
9 | * @returns
10 | */
11 | export function loginApi(data: LoginData): AxiosPromise {
12 | const formData = new FormData();
13 | formData.append("username", data.username);
14 | formData.append("password", data.password);
15 | formData.append("captchaKey", data.captchaKey || "");
16 | formData.append("captchaCode", data.captchaCode || "");
17 | return request({
18 | url: "/api/v1/auth/login",
19 | method: "post",
20 | data: formData,
21 | headers: {
22 | "Content-Type": "multipart/form-data",
23 | },
24 | });
25 | }
26 |
27 | /**
28 | * 注销API
29 | */
30 | export function logoutApi() {
31 | return request({
32 | url: "/api/v1/auth/logout",
33 | method: "delete",
34 | });
35 | }
36 |
37 | /**
38 | * 获取验证码
39 | */
40 | export function getCaptchaApi(): AxiosPromise {
41 | return request({
42 | url: "/api/v1/auth/captcha",
43 | method: "get",
44 | });
45 | }
46 |
47 | // // 获取版本号
48 | // export function GetVersion():AxiosPromise{
49 | // return request({
50 | // url: "/api/v1/version",
51 | // method: "get",
52 | // });
53 | // }
54 |
55 | // 获取版本号
56 | export function GetVersion(): AxiosPromise {
57 | return request({
58 | url: "/api/v1/version",
59 | method: "get",
60 | });
61 | }
62 |
--------------------------------------------------------------------------------
/webs/src/api/auth/types.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 登录请求参数
3 | */
4 | export interface LoginData {
5 | /**
6 | * 用户名
7 | */
8 | username: string;
9 | /**
10 | * 密码
11 | */
12 | password: string;
13 |
14 | /**
15 | * 验证码缓存key
16 | */
17 | captchaKey?: string;
18 |
19 | /**
20 | * 验证码
21 | */
22 | captchaCode?: string;
23 | }
24 |
25 | /**
26 | * 登录响应
27 | */
28 | export interface LoginResult {
29 | /**
30 | * 访问token
31 | */
32 | accessToken?: string;
33 | /**
34 | * 过期时间(单位:毫秒)
35 | */
36 | expires?: number;
37 | /**
38 | * 刷新token
39 | */
40 | refreshToken?: string;
41 | /**
42 | * token 类型
43 | */
44 | tokenType?: string;
45 | }
46 |
47 | /**
48 | * 验证码响应
49 | */
50 | export interface CaptchaResult {
51 | /**
52 | * 验证码缓存key
53 | */
54 | captchaKey: string;
55 | /**
56 | * 验证码图片Base64字符串
57 | */
58 | captchaBase64: string;
59 | }
60 |
61 | export interface VersionResult {
62 | /**
63 | * 版本号
64 | */
65 | version: string;
66 | }
--------------------------------------------------------------------------------
/webs/src/api/dept/index.ts:
--------------------------------------------------------------------------------
1 | import request from "@/utils/request";
2 | import { AxiosPromise } from "axios";
3 | import { DeptForm, DeptQuery, DeptVO } from "./types";
4 |
5 | /**
6 | * 部门树形表格
7 | *
8 | * @param queryParams
9 | */
10 | export function listDepts(queryParams?: DeptQuery): AxiosPromise {
11 | return request({
12 | url: "/api/v1/dept",
13 | method: "get",
14 | params: queryParams,
15 | });
16 | }
17 |
18 | /**
19 | * 部门下拉列表
20 | */
21 | export function getDeptOptions(): AxiosPromise {
22 | return request({
23 | url: "/api/v1/dept/options",
24 | method: "get",
25 | });
26 | }
27 |
28 | /**
29 | * 获取部门详情
30 | *
31 | * @param id
32 | */
33 | export function getDeptForm(id: number): AxiosPromise {
34 | return request({
35 | url: "/api/v1/dept/" + id + "/form",
36 | method: "get",
37 | });
38 | }
39 |
40 | /**
41 | * 新增部门
42 | *
43 | * @param data
44 | */
45 | export function addDept(data: DeptForm) {
46 | return request({
47 | url: "/api/v1/dept",
48 | method: "post",
49 | data: data,
50 | });
51 | }
52 |
53 | /**
54 | * 修改部门
55 | *
56 | * @param id
57 | * @param data
58 | */
59 | export function updateDept(id: number, data: DeptForm) {
60 | return request({
61 | url: "/api/v1/dept/" + id,
62 | method: "put",
63 | data: data,
64 | });
65 | }
66 |
67 | /**
68 | * 删除部门
69 | *
70 | * @param ids
71 | */
72 | export function deleteDept(ids: string) {
73 | return request({
74 | url: "/api/v1/dept/" + ids,
75 | method: "delete",
76 | });
77 | }
78 |
--------------------------------------------------------------------------------
/webs/src/api/dept/types.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 部门查询参数
3 | */
4 | export interface DeptQuery {
5 | keywords?: string;
6 | status?: number;
7 | }
8 |
9 | /**
10 | * 部门类型
11 | */
12 | export interface DeptVO {
13 | /**
14 | * 子部门
15 | */
16 | children?: DeptVO[];
17 | /**
18 | * 创建时间
19 | */
20 | createTime?: Date;
21 | /**
22 | * 部门ID
23 | */
24 | id?: number;
25 | /**
26 | * 部门名称
27 | */
28 | name?: string;
29 | /**
30 | * 父部门ID
31 | */
32 | parentId?: number;
33 | /**
34 | * 排序
35 | */
36 | sort?: number;
37 | /**
38 | * 状态(1:启用;0:禁用)
39 | */
40 | status?: number;
41 | /**
42 | * 修改时间
43 | */
44 | updateTime?: Date;
45 | }
46 |
47 | /**
48 | * 部门表单类型
49 | */
50 | export interface DeptForm {
51 | /**
52 | * 部门ID(新增不填)
53 | */
54 | id?: number;
55 | /**
56 | * 部门名称
57 | */
58 | name?: string;
59 | /**
60 | * 父部门ID
61 | */
62 | parentId: number;
63 | /**
64 | * 排序
65 | */
66 | sort?: number;
67 | /**
68 | * 状态(1:启用;0:禁用)
69 | */
70 | status?: number;
71 | }
72 |
--------------------------------------------------------------------------------
/webs/src/api/file/index.ts:
--------------------------------------------------------------------------------
1 | import request from "@/utils/request";
2 | import { AxiosPromise } from "axios";
3 | import { FileInfo } from "./types";
4 |
5 | /**
6 | * 上传文件
7 | *
8 | * @param file
9 | */
10 | export function uploadFileApi(file: File): AxiosPromise {
11 | const formData = new FormData();
12 | formData.append("file", file);
13 | return request({
14 | url: "/api/v1/files",
15 | method: "post",
16 | data: formData,
17 | headers: {
18 | "Content-Type": "multipart/form-data",
19 | },
20 | });
21 | }
22 |
23 | /**
24 | * 删除文件
25 | *
26 | * @param filePath 文件完整路径
27 | */
28 | export function deleteFileApi(filePath?: string) {
29 | return request({
30 | url: "/api/v1/files",
31 | method: "delete",
32 | params: { filePath: filePath },
33 | });
34 | }
35 |
--------------------------------------------------------------------------------
/webs/src/api/file/types.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 文件API类型声明
3 | */
4 | export interface FileInfo {
5 | name: string;
6 | url: string;
7 | }
8 |
--------------------------------------------------------------------------------
/webs/src/api/menu/index.ts:
--------------------------------------------------------------------------------
1 | import request from "@/utils/request";
2 | import { AxiosPromise } from "axios";
3 | import { MenuQuery, MenuVO, MenuForm } from "./types";
4 |
5 | /**
6 | * 获取路由列表
7 | */
8 | export function listRoutes() {
9 | return request({
10 | url: "/api/v1/menus/routes",
11 | method: "get",
12 | });
13 | }
14 |
15 | /**
16 | * 获取菜单树形列表
17 | *
18 | * @param queryParams
19 | */
20 | export function listMenus(queryParams: MenuQuery): AxiosPromise {
21 | return request({
22 | url: "/api/v1/menus",
23 | method: "get",
24 | params: queryParams,
25 | });
26 | }
27 |
28 | /**
29 | * 获取菜单下拉树形列表
30 | */
31 | export function getMenuOptions(): AxiosPromise {
32 | return request({
33 | url: "/api/v1/menus/options",
34 | method: "get",
35 | });
36 | }
37 |
38 | /**
39 | * 获取菜单表单数据
40 | *
41 | * @param id
42 | */
43 | export function getMenuForm(id: number): AxiosPromise {
44 | return request({
45 | url: "/api/v1/menus/" + id + "/form",
46 | method: "get",
47 | });
48 | }
49 |
50 | /**
51 | * 添加菜单
52 | *
53 | * @param data
54 | */
55 | export function addMenu(data: MenuForm) {
56 | return request({
57 | url: "/api/v1/menus",
58 | method: "post",
59 | data: data,
60 | });
61 | }
62 |
63 | /**
64 | * 修改菜单
65 | *
66 | * @param id
67 | * @param data
68 | */
69 | export function updateMenu(id: string, data: MenuForm) {
70 | return request({
71 | url: "/api/v1/menus/" + id,
72 | method: "put",
73 | data: data,
74 | });
75 | }
76 |
77 | /**
78 | * 删除菜单
79 | *
80 | * @param id 菜单ID
81 | */
82 | export function deleteMenu(id: number) {
83 | return request({
84 | url: "/api/v1/menus/" + id,
85 | method: "delete",
86 | });
87 | }
88 |
--------------------------------------------------------------------------------
/webs/src/api/role/types.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 角色查询参数
3 | */
4 | export interface RoleQuery extends PageQuery {
5 | keywords?: string;
6 | }
7 |
8 | /**
9 | * 角色分页对象
10 | */
11 | export interface RolePageVO {
12 | /**
13 | * 角色编码
14 | */
15 | code?: string;
16 |
17 | /**
18 | * 角色ID
19 | */
20 | id?: number;
21 | /**
22 | * 角色名称
23 | */
24 | name?: string;
25 | /**
26 | * 排序
27 | */
28 | sort?: number;
29 | /**
30 | * 角色状态
31 | */
32 | status?: number;
33 | /**
34 | * 创建时间
35 | */
36 | createTime?: Date;
37 | /**
38 | * 修改时间
39 | */
40 | updateTime?: Date;
41 | }
42 |
43 | /**
44 | * 角色分页
45 | */
46 | export type RolePageResult = PageResult;
47 |
48 | /**
49 | * 角色表单对象
50 | */
51 | export interface RoleForm {
52 | /**
53 | * 角色ID
54 | */
55 | id?: number;
56 |
57 | /**
58 | * 角色编码
59 | */
60 | code: string;
61 | /**
62 | * 数据权限
63 | */
64 | dataScope?: number;
65 |
66 | /**
67 | * 角色名称
68 | */
69 | name: string;
70 | /**
71 | * 排序
72 | */
73 | sort?: number;
74 | /**
75 | * 角色状态(1-正常;0-停用)
76 | */
77 | status?: number;
78 | }
79 |
--------------------------------------------------------------------------------
/webs/src/api/subcription/node.ts:
--------------------------------------------------------------------------------
1 | import request from "@/utils/request";
2 | export function getNodes(){
3 | return request({
4 | url: "/api/v1/nodes/get",
5 | method: "get",
6 | });
7 | }
8 |
9 | export function AddNodes(data: any){
10 | return request({
11 | url: "/api/v1/nodes/add",
12 | method: "post",
13 | data,
14 | headers: {
15 | "Content-Type": "multipart/form-data",
16 | },
17 | });
18 | }
19 | export function UpdateNode(data: any){
20 | return request({
21 | url: "/api/v1/nodes/update",
22 | method: "post",
23 | data,
24 | headers: {
25 | "Content-Type": "multipart/form-data",
26 | },
27 | });
28 | }
29 | export function DelNode(data: any){
30 | return request({
31 | url: "/api/v1/nodes/delete",
32 | method: "delete",
33 | params: data,
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/webs/src/api/subcription/subs.ts:
--------------------------------------------------------------------------------
1 | import request from "@/utils/request";
2 | export function getSubs(){
3 | return request({
4 | url: "/api/v1/subcription/get",
5 | method: "get",
6 | });
7 | }
8 |
9 | export function AddSub(data: any){
10 | return request({
11 | url: "/api/v1/subcription/add",
12 | method: "post",
13 | data,
14 | headers: {
15 | "Content-Type": "multipart/form-data",
16 | },
17 | });
18 | }
19 | export function DelSub(data: any){
20 | return request({
21 | url: "/api/v1/subcription/delete",
22 | method: "delete",
23 | params: data,
24 | });
25 | }
26 |
27 | export function UpdateSub(data: any){
28 | return request({
29 | url: "/api/v1/subcription/update",
30 | method: "post",
31 | data,
32 | headers: {
33 | "Content-Type": "multipart/form-data",
34 | },
35 | });
36 | }
--------------------------------------------------------------------------------
/webs/src/api/subcription/temp.ts:
--------------------------------------------------------------------------------
1 | import request from "@/utils/request";
2 |
3 | export function getTemp(){
4 | return request({
5 | url: "/api/v1/template/get",
6 | method: "get",
7 | });
8 | }
9 |
10 | export function AddTemp(data: any){
11 | return request({
12 | url: "/api/v1/template/add",
13 | method: "post",
14 | data,
15 | headers: {
16 | "Content-Type": "multipart/form-data",
17 | },
18 | });
19 | }
20 | export function UpdateTemp(data: any){
21 | return request({
22 | url: "/api/v1/template/update",
23 | method: "post",
24 | data,
25 | headers: {
26 | "Content-Type": "multipart/form-data",
27 | },
28 | });
29 | }
30 | export function DelTemp(data: any){
31 | return request({
32 | url: "/api/v1/template/delete",
33 | method: "post",
34 | data,
35 | headers: {
36 | "Content-Type": "multipart/form-data",
37 | },
38 | });
39 | }
40 |
--------------------------------------------------------------------------------
/webs/src/api/total/index.ts:
--------------------------------------------------------------------------------
1 | import request from "@/utils/request";
2 | export function getSubTotal(){
3 | return request({
4 | url: "/api/v1/total/sub",
5 | method: "get",
6 | });
7 | }
8 | export function getNodeTotal(){
9 | return request({
10 | url: "/api/v1/total/node",
11 | method: "get",
12 | });
13 | }
--------------------------------------------------------------------------------
/webs/src/assets/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/webs/src/assets/1.png
--------------------------------------------------------------------------------
/webs/src/assets/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/webs/src/assets/2.png
--------------------------------------------------------------------------------
/webs/src/assets/icons/cascader.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/client.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/close_all.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/close_left.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/close_other.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/close_right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/dict.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/document.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/download.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/eye-open.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/eye.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/fullscreen-exit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/fullscreen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/github.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/homepage.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/indent-decrease.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/ip.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/language.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/lock.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/menu.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/message.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/monitor.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/moon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/order.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/peoples.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/project.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/publish.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/role.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/security.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/setting.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/size.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/sunny.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/system.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/table.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/todolist.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/tree.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/icons/visit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/webs/src/assets/images/401.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/webs/src/assets/images/401.gif
--------------------------------------------------------------------------------
/webs/src/assets/images/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/webs/src/assets/images/404.png
--------------------------------------------------------------------------------
/webs/src/assets/images/404_cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/webs/src/assets/images/404_cloud.png
--------------------------------------------------------------------------------
/webs/src/assets/images/login-bg-dark.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/webs/src/assets/images/login-bg-dark.jpg
--------------------------------------------------------------------------------
/webs/src/assets/images/login-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/webs/src/assets/images/login-bg.jpg
--------------------------------------------------------------------------------
/webs/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gooaclok819/sublinkX/263ff739e245e01e1803783f7226ab33693f57fb/webs/src/assets/logo.png
--------------------------------------------------------------------------------
/webs/src/components/AppLink/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
34 |
--------------------------------------------------------------------------------
/webs/src/components/Hamburger/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
12 |
13 |
28 |
29 |
40 |
--------------------------------------------------------------------------------
/webs/src/components/LangSelect/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
14 | {{ item.label }}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
48 |
--------------------------------------------------------------------------------
/webs/src/components/Pagination/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
70 |
71 |
80 |
--------------------------------------------------------------------------------
/webs/src/components/SizeSelect/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
14 | {{ item.label }}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
40 |
--------------------------------------------------------------------------------
/webs/src/components/SvgIcon/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
34 |
35 |
46 |
--------------------------------------------------------------------------------
/webs/src/components/Upload/SingleUpload.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
51 |
52 |
78 |
--------------------------------------------------------------------------------
/webs/src/directive/index.ts:
--------------------------------------------------------------------------------
1 | import type { App } from "vue";
2 |
3 | import { hasPerm } from "./permission";
4 |
5 | // 全局注册 directive
6 | export function setupDirective(app: App) {
7 | // 使 v-hasPerm 在所有组件中都可用
8 | app.directive("hasPerm", hasPerm);
9 | }
10 |
--------------------------------------------------------------------------------
/webs/src/directive/permission/index.ts:
--------------------------------------------------------------------------------
1 | import { useUserStoreHook } from "@/store/modules/user";
2 | import { Directive, DirectiveBinding } from "vue";
3 |
4 | /**
5 | * 按钮权限
6 | */
7 | export const hasPerm: Directive = {
8 | mounted(el: HTMLElement, binding: DirectiveBinding) {
9 | // 「超级管理员」拥有所有的按钮权限
10 | const { roles, perms } = useUserStoreHook().user;
11 | if (roles.includes("ROOT")) {
12 | return true;
13 | }
14 | // 「其他角色」按钮权限校验
15 | const { value } = binding;
16 | if (value) {
17 | const requiredPerms = value; // DOM绑定需要的按钮权限标识
18 |
19 | const hasPerm = perms?.some((perm) => {
20 | return requiredPerms.includes(perm);
21 | });
22 |
23 | if (!hasPerm) {
24 | el.parentNode && el.parentNode.removeChild(el);
25 | }
26 | } else {
27 | throw new Error(
28 | "need perms! Like v-has-perm=\"['sys:user:add','sys:user:edit']\""
29 | );
30 | }
31 | },
32 | };
33 |
34 | /**
35 | * 角色权限
36 | */
37 | export const hasRole: Directive = {
38 | mounted(el: HTMLElement, binding: DirectiveBinding) {
39 | const { value } = binding;
40 |
41 | if (value) {
42 | const requiredRoles = value; // DOM绑定需要的角色编码
43 | const { roles } = useUserStoreHook().user;
44 | const hasRole = roles.some((perm) => {
45 | return requiredRoles.includes(perm);
46 | });
47 |
48 | if (!hasRole) {
49 | el.parentNode && el.parentNode.removeChild(el);
50 | }
51 | } else {
52 | throw new Error("need roles! Like v-has-role=\"['admin','test']\"");
53 | }
54 | },
55 | };
56 |
--------------------------------------------------------------------------------
/webs/src/enums/DeviceEnum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 设备枚举
3 | */
4 | export const enum DeviceEnum {
5 | /**
6 | * 宽屏设备
7 | */
8 | DESKTOP = "desktop",
9 |
10 | /**
11 | * 窄屏设备
12 | */
13 | MOBILE = "mobile",
14 | }
15 |
--------------------------------------------------------------------------------
/webs/src/enums/LanguageEnum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 语言枚举
3 | */
4 | export const enum LanguageEnum {
5 | /**
6 | * 中文
7 | */
8 | ZH_CN = "zh-cn",
9 |
10 | /**
11 | * 英文
12 | */
13 | EN = "en",
14 | }
15 |
--------------------------------------------------------------------------------
/webs/src/enums/LayoutEnum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 菜单布局枚举
3 | */
4 | export const enum LayoutEnum {
5 | /**
6 | * 左侧菜单布局
7 | */
8 | LEFT = "left",
9 | /**
10 | * 顶部菜单布局
11 | */
12 | TOP = "top",
13 |
14 | /**
15 | * 混合菜单布局
16 | */
17 | MIX = "mix",
18 | }
19 |
--------------------------------------------------------------------------------
/webs/src/enums/MenuTypeEnum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 菜单类型枚举
3 | */
4 | export const enum MenuTypeEnum {
5 | /**
6 | * 目录
7 | */
8 | CATALOG = "CATALOG",
9 | /**
10 | * 菜单
11 | */
12 | MENU = "MENU",
13 |
14 | /**
15 | * 按钮
16 | */
17 | BUTTON = "BUTTON",
18 | /**
19 | * 外链
20 | */
21 | EXTLINK = "EXTLINK",
22 | }
23 |
--------------------------------------------------------------------------------
/webs/src/enums/SidebarStatusEnum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 侧边栏状态枚举
3 | */
4 | export const enum SidebarStatusEnum {
5 | /**
6 | * 展开
7 | */
8 | OPENED = "opened",
9 |
10 | /**
11 | * 关闭
12 | */
13 | CLOSED = "closed",
14 | }
15 |
--------------------------------------------------------------------------------
/webs/src/enums/SizeEnum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 布局大小枚举
3 | */
4 | export const enum SizeEnum {
5 | /**
6 | * 默认
7 | */
8 | DEFAULT = "default",
9 |
10 | /**
11 | * 大型
12 | */
13 | LARGE = "large",
14 |
15 | /**
16 | * 小型
17 | */
18 | SMALL = "small",
19 | }
20 |
--------------------------------------------------------------------------------
/webs/src/enums/ThemeEnum.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 主题枚举
3 | */
4 | export const enum ThemeEnum {
5 | /**
6 | * 明亮主题
7 | */
8 | LIGHT = "light",
9 | /**
10 | * 暗黑主题
11 | */
12 | DARK = "dark",
13 |
14 | /**
15 | * 系统自动
16 | */
17 | AUTO = "auto",
18 | }
19 |
--------------------------------------------------------------------------------
/webs/src/lang/index.ts:
--------------------------------------------------------------------------------
1 | import { createI18n } from "vue-i18n";
2 | import { useAppStoreHook } from "@/store/modules/app";
3 | // 本地语言包
4 | import enLocale from "./package/en";
5 | import zhCnLocale from "./package/zh-cn";
6 |
7 | const appStore = useAppStoreHook();
8 |
9 | const messages = {
10 | "zh-cn": {
11 | ...zhCnLocale,
12 | },
13 | en: {
14 | ...enLocale,
15 | },
16 | };
17 |
18 | const i18n = createI18n({
19 | legacy: false,
20 | locale: appStore.language,
21 | messages: messages,
22 | globalInjection: true,
23 | });
24 |
25 | export default i18n;
26 |
--------------------------------------------------------------------------------
/webs/src/lang/package/zh-cn.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | // 路由国际化
3 | route: {
4 | dashboard: "首页",
5 | document: "项目文档",
6 | userset: "修改密码",
7 | system:"系统管理",
8 | nodelist:"节点列表",
9 | sublist:"订阅列表",
10 | subcription:"订阅管理",
11 | templatelist:"模板列表",
12 | },
13 | // 登录页面国际化
14 | login: {
15 | username: "用户名",
16 | password: "密码",
17 | login: "登 录",
18 | captchaCode: "验证码",
19 | capsLock: "大写锁定已打开",
20 | message: {
21 | username: {
22 | required: "请输入用户名",
23 | },
24 | password: {
25 | required: "请输入密码",
26 | min: "密码不能少于6位",
27 | },
28 | captchaCode: {
29 | required: "请输入验证码",
30 | },
31 | },
32 | },
33 | // 重置密码页面国际化
34 | userset:{
35 | title: "修改密码",
36 | newUsername: "新账号",
37 | newPassword: "新密码",
38 | message: {
39 | title:"提示",
40 | xx1:"账号或密码不能为空",
41 | xx2: "密码长度不能小于6位",
42 | xx3:"你确定要重置密码吗",
43 | xx4:"密码重置成功,新密码是:",
44 | },
45 | },
46 | // 导航栏国际化
47 | navbar: {
48 | dashboard: "首页",
49 | logout: "注销登出",
50 | userset: "修改密码",
51 | },
52 | sizeSelect: {
53 | tooltip: "布局大小",
54 | default: "默认",
55 | large: "大型",
56 | small: "小型",
57 | message: {
58 | success: "切换布局大小成功!",
59 | },
60 | },
61 | langSelect: {
62 | message: {
63 | success: "切换语言成功!",
64 | },
65 | },
66 | settings: {
67 | project: "项目配置",
68 | theme: "主题设置",
69 | interface: "界面设置",
70 | navigation: "导航设置",
71 | themeColor: "主题颜色",
72 | tagsView: "开启 Tags-View",
73 | fixedHeader: "固定 Header",
74 | sidebarLogo: "侧边栏 Logo",
75 | watermark: "开启水印",
76 | },
77 | };
78 |
--------------------------------------------------------------------------------
/webs/src/layout/components/NavBar/components/NavbarLeft.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
20 |
--------------------------------------------------------------------------------
/webs/src/layout/components/NavBar/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
19 |
--------------------------------------------------------------------------------
/webs/src/layout/components/Settings/components/ThemeColorPicker.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
36 |
37 |
42 |
--------------------------------------------------------------------------------
/webs/src/layout/components/Sidebar/components/SidebarLogo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {{ defaultSettings.title }}
11 |
12 |
13 |
14 |
15 |
16 |
31 |
32 |
65 |
--------------------------------------------------------------------------------
/webs/src/layout/components/Sidebar/components/SidebarMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
20 |
21 |
22 |
23 |
65 |
--------------------------------------------------------------------------------
/webs/src/layout/components/Sidebar/components/SidebarMenuItemTitle.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ translateRouteTitle(title) }}
8 |
9 |
10 |
24 |
25 |
43 |
--------------------------------------------------------------------------------
/webs/src/layout/components/Sidebar/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
30 |
31 |
38 |
--------------------------------------------------------------------------------
/webs/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from "vue";
2 | import App from "./App.vue";
3 | import router from "@/router";
4 | import { setupStore } from "@/store";
5 | import { setupDirective } from "@/directive";
6 | import { setupElIcons, setupI18n, setupPermission } from "@/plugins";
7 |
8 | // 本地SVG图标
9 | import "virtual:svg-icons-register";
10 |
11 | // 样式
12 | import "element-plus/theme-chalk/dark/css-vars.css";
13 | import "@/styles/index.scss";
14 | import "uno.css";
15 | import "animate.css";
16 |
17 | const app = createApp(App);
18 | // 全局注册 自定义指令(directive)
19 | setupDirective(app);
20 | // 全局注册 状态管理(store)
21 | setupStore(app);
22 | // 全局注册Element-plus图标
23 | setupElIcons(app);
24 | // 国际化
25 | setupI18n(app);
26 | // 注册动态路由
27 | setupPermission();
28 | app.use(router);
29 | app.mount("#app");
30 |
--------------------------------------------------------------------------------
/webs/src/plugins/i18n.ts:
--------------------------------------------------------------------------------
1 | // 国际化
2 | import i18n from "@/lang/index";
3 | import type { App } from "vue";
4 |
5 | export function setupI18n(app: App) {
6 | app.use(i18n);
7 | }
8 |
--------------------------------------------------------------------------------
/webs/src/plugins/icons.ts:
--------------------------------------------------------------------------------
1 | import type { App } from "vue";
2 | import * as ElementPlusIconsVue from "@element-plus/icons-vue";
3 |
4 | // 注册所有图标
5 | export function setupElIcons(app: App) {
6 | for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
7 | app.component(key, component);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/webs/src/plugins/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./icons";
2 | export * from "./i18n";
3 | export * from "./permission";
4 |
--------------------------------------------------------------------------------
/webs/src/settings.ts:
--------------------------------------------------------------------------------
1 | import { SizeEnum } from "./enums/SizeEnum";
2 | import { LayoutEnum } from "./enums/LayoutEnum";
3 | import { ThemeEnum } from "./enums/ThemeEnum";
4 | import { LanguageEnum } from "./enums/LanguageEnum";
5 |
6 | const { pkg } = __APP_INFO__;
7 |
8 | const defaultSettings: AppSettings = {
9 | title: pkg.name,
10 | version: pkg.version,
11 | showSettings: true,
12 | tagsView: true,
13 | fixedHeader: true,
14 | sidebarLogo: true,
15 | layout: LayoutEnum.LEFT,
16 | theme: ThemeEnum.LIGHT,
17 | size: SizeEnum.DEFAULT,
18 | language: LanguageEnum.ZH_CN,
19 | themeColor: "#409EFF",
20 | watermarkEnabled: false,
21 | watermarkContent: pkg.name,
22 | };
23 |
24 | export default defaultSettings;
25 |
--------------------------------------------------------------------------------
/webs/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import type { App } from "vue";
2 | import { createPinia } from "pinia";
3 |
4 | const store = createPinia();
5 |
6 | // 全局注册 store
7 | export function setupStore(app: App) {
8 | app.use(store);
9 | }
10 |
11 | export * from "./modules/app";
12 | export * from "./modules/permission";
13 | export * from "./modules/settings";
14 | export * from "./modules/tagsView";
15 | export * from "./modules/user";
16 | export { store };
17 |
--------------------------------------------------------------------------------
/webs/src/styles/index.scss:
--------------------------------------------------------------------------------
1 | @use "./reset";
2 |
3 | .app-container {
4 | padding: 10px;
5 | }
6 |
7 | .search-container {
8 | padding: 18px 0 0 10px;
9 | margin-bottom: 10px;
10 | background-color: var(--el-bg-color-overlay);
11 | border: 1px solid var(--el-border-color-light);
12 | border-radius: 4px;
13 | box-shadow: var(--el-box-shadow-light);
14 | }
15 |
16 | .table-container > .el-card__header {
17 | padding: calc(var(--el-card-padding) - 8px) var(--el-card-padding);
18 | }
19 |
20 | .link-type,
21 | .link-type:focus {
22 | color: #337ab7;
23 | cursor: pointer;
24 |
25 | &:hover {
26 | color: rgb(32 160 255);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/webs/src/styles/reset.scss:
--------------------------------------------------------------------------------
1 | *,
2 | ::before,
3 | ::after {
4 | box-sizing: border-box;
5 | border-color: currentcolor;
6 | border-style: solid;
7 | border-width: 0;
8 | }
9 |
10 | #app {
11 | width: 100%;
12 | height: 100%;
13 | }
14 |
15 | html {
16 | box-sizing: border-box;
17 | width: 100%;
18 | height: 100%;
19 | line-height: 1.5;
20 | tab-size: 4;
21 | text-size-adjust: 100%;
22 | }
23 |
24 | body {
25 | width: 100%;
26 | height: 100%;
27 | margin: 0;
28 | font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
29 | "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
30 | line-height: inherit;
31 | -moz-osx-font-smoothing: grayscale;
32 | -webkit-font-smoothing: antialiased;
33 | text-rendering: optimizelegibility;
34 | }
35 |
36 | a {
37 | color: inherit;
38 | text-decoration: inherit;
39 | }
40 |
41 | img,
42 | svg {
43 | display: inline-block;
44 | }
45 |
46 | svg {
47 | // 因icon大小被设置为和字体大小一致,而span等标签的下边缘会和字体的基线对齐,故需设置一个往下的偏移比例,来纠正视觉上的未对齐效果
48 | vertical-align: -0.15em;
49 | }
50 |
51 | ul,
52 | li {
53 | padding: 0;
54 | margin: 0;
55 | list-style: none;
56 | }
57 |
58 | *,
59 | *::before,
60 | *::after {
61 | box-sizing: inherit;
62 | }
63 |
64 | a,
65 | a:focus,
66 | a:hover {
67 | color: inherit;
68 | text-decoration: none;
69 | cursor: pointer;
70 | }
71 |
72 | a:focus,
73 | a:active,
74 | div:focus {
75 | outline: none;
76 | }
77 |
--------------------------------------------------------------------------------
/webs/src/styles/variables.module.scss:
--------------------------------------------------------------------------------
1 | /* stylelint-disable property-no-unknown */
2 | :export {
3 | sidebar-width: $sidebar-width;
4 | navbar-height: $navbar-height;
5 | menu-background: $menu-background;
6 | menu-text: $menu-text;
7 | menu-active-text: $menu-active-text;
8 | menu-hover: $menu-hover;
9 | }
10 | /* stylelint-enable property-no-unknown */
11 |
--------------------------------------------------------------------------------
/webs/src/styles/variables.scss:
--------------------------------------------------------------------------------
1 | /** 全局SCSS变量 */
2 |
3 | :root {
4 | --menu-background: #304156;
5 | --menu-text: #bfcbd9;
6 | --menu-active-text: var(--el-menu-active-color);
7 | --menu-hover: #263445;
8 | --sidebar-logo-background: #2d3748;
9 | }
10 |
11 | /** 暗黑主题 */
12 | html.dark {
13 | --menu-background: var(--el-bg-color-overlay);
14 | --menu-text: #fff;
15 | --menu-active-text: var(--el-menu-active-color);
16 | --menu-hover: rgb(0 0 0 / 20%);
17 | --sidebar-logo-background: rgb(0 0 0 / 20%);
18 | }
19 |
20 | $menu-background: var(--menu-background); // 菜单背景色
21 | $menu-text: var(--menu-text); // 菜单文字颜色
22 | $menu-active-text: var(--menu-active-text); // 菜单激活文字颜色
23 | $menu-hover: var(--menu-hover); // 菜单悬停背景色
24 | $sidebar-logo-background: var(--sidebar-logo-background); // 侧边栏 Logo 背景色
25 |
26 | $sidebar-width: 210px; // 侧边栏宽度
27 | $sidebar-width-collapsed: 54px; // 侧边栏收缩宽度
28 | $navbar-height: 50px; // 导航栏高度
29 | $tags-view-height: 34px; // TagsView 高度
30 |
--------------------------------------------------------------------------------
/webs/src/typings/env.d.ts:
--------------------------------------------------------------------------------
1 | // https://cn.vitejs.dev/guide/env-and-mode
2 |
3 | declare module "*.vue" {
4 | import { DefineComponent } from "vue";
5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
6 | const component: DefineComponent<{}, {}, any>;
7 | export default component;
8 | }
9 |
10 | // TypeScript 类型提示都为 string: https://github.com/vitejs/vite/issues/6930
11 | interface ImportMetaEnv {
12 | /** 应用端口 */
13 | VITE_APP_PORT: number;
14 | /** API 基础路径(代理前缀) */
15 | VITE_APP_BASE_API: string;
16 | /** API 地址 */
17 | VITE_APP_API_URL: string;
18 | /** 是否开启 Mock 服务 */
19 | VITE_MOCK_DEV_SERVER: boolean;
20 | }
21 |
22 | interface ImportMeta {
23 | readonly env: ImportMetaEnv;
24 | }
25 |
26 | /**
27 | * 平台的名称、版本、运行所需的`node`版本、依赖、构建时间的类型提示
28 | */
29 | declare const __APP_INFO__: {
30 | pkg: {
31 | name: string;
32 | version: string;
33 | engines: {
34 | node: string;
35 | };
36 | dependencies: Record;
37 | devDependencies: Record;
38 | };
39 | buildTimestamp: number;
40 | };
41 |
--------------------------------------------------------------------------------
/webs/src/typings/global.d.ts:
--------------------------------------------------------------------------------
1 | declare global {
2 | /**
3 | * 分页查询参数
4 | */
5 | interface PageQuery {
6 | pageNum: number;
7 | pageSize: number;
8 | }
9 |
10 | /**
11 | * 分页响应对象
12 | */
13 | interface PageResult {
14 | /** 数据列表 */
15 | list: T;
16 | /** 总数 */
17 | total: number;
18 | }
19 |
20 | /**
21 | * 页签对象
22 | */
23 | interface TagView {
24 | /** 页签名称 */
25 | name: string;
26 | /** 页签标题 */
27 | title: string;
28 | /** 页签路由路径 */
29 | path: string;
30 | /** 页签路由完整路径 */
31 | fullPath: string;
32 | /** 页签图标 */
33 | icon?: string;
34 | /** 是否固定页签 */
35 | affix?: boolean;
36 | /** 是否开启缓存 */
37 | keepAlive?: boolean;
38 | /** 路由查询参数 */
39 | query?: any;
40 | }
41 |
42 | /**
43 | * 系统设置
44 | */
45 | interface AppSettings {
46 | /** 系统标题 */
47 | title: string;
48 | /** 系统版本 */
49 | version: string;
50 | /** 是否显示设置 */
51 | showSettings: boolean;
52 | /** 是否固定头部 */
53 | fixedHeader: boolean;
54 | /** 是否显示多标签导航 */
55 | tagsView: boolean;
56 | /** 是否显示侧边栏Logo */
57 | sidebarLogo: boolean;
58 | /** 导航栏布局(left|top|mix) */
59 | layout: string;
60 | /** 主题颜色 */
61 | themeColor: string;
62 | /** 主题模式(dark|light) */
63 | theme: string;
64 | /** 布局大小(default |large |small) */
65 | size: string;
66 | /** 语言( zh-cn| en) */
67 | language: string;
68 | /** 是否开启水印 */
69 | watermarkEnabled: boolean;
70 | /** 水印内容 */
71 | watermarkContent: string;
72 | }
73 |
74 | /**
75 | * 组件数据源
76 | */
77 | interface OptionType {
78 | /** 值 */
79 | value: string | number;
80 | /** 文本 */
81 | label: string;
82 | /** 子列表 */
83 | children?: OptionType[];
84 | }
85 | }
86 | export {};
87 |
--------------------------------------------------------------------------------
/webs/src/typings/router.d.ts:
--------------------------------------------------------------------------------
1 | import "vue-router";
2 |
3 | declare module "vue-router" {
4 | // https://router.vuejs.org/zh/guide/advanced/meta.html#typescript
5 | // 可以通过扩展 RouteMeta 接口来输入 meta 字段
6 | interface RouteMeta {
7 | /** 菜单名称 */
8 | title?: string;
9 | /** 菜单图标 */
10 | icon?: string;
11 | /** 菜单是否隐藏 */
12 | hidden?: boolean;
13 | /** 是否固定页签 */
14 | affix?: boolean;
15 | /** 是否缓存页面 */
16 | keepAlive?: boolean;
17 | /** 是否在面包屑上隐藏 */
18 | breadcrumb?: boolean;
19 | /** 拥有菜单权限的角色编码集合 */
20 | roles?: string[];
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/webs/src/typings/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module "xlsx/xlsx.mjs";
2 |
--------------------------------------------------------------------------------
/webs/src/utils/i18n.ts:
--------------------------------------------------------------------------------
1 | // translate router.meta.title, be used in breadcrumb sidebar tagsview
2 | import i18n from "@/lang/index";
3 |
4 | export function translateRouteTitle(title: any) {
5 | // 判断是否存在国际化配置,如果没有原生返回
6 | const hasKey = i18n.global.te("route." + title);
7 | if (hasKey) {
8 | const translatedTitle = i18n.global.t("route." + title);
9 | return translatedTitle;
10 | }
11 | return title;
12 | }
13 |
--------------------------------------------------------------------------------
/webs/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Check if an element has a class
3 | * @param {HTMLElement} ele
4 | * @param {string} cls
5 | * @returns {boolean}
6 | */
7 | export function hasClass(ele: HTMLElement, cls: string) {
8 | return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)"));
9 | }
10 |
11 | /**
12 | * Add class to element
13 | * @param {HTMLElement} ele
14 | * @param {string} cls
15 | */
16 | export function addClass(ele: HTMLElement, cls: string) {
17 | if (!hasClass(ele, cls)) ele.className += " " + cls;
18 | }
19 |
20 | /**
21 | * Remove class from element
22 | * @param {HTMLElement} ele
23 | * @param {string} cls
24 | */
25 | export function removeClass(ele: HTMLElement, cls: string) {
26 | if (hasClass(ele, cls)) {
27 | const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
28 | ele.className = ele.className.replace(reg, " ");
29 | }
30 | }
31 |
32 | /**
33 | * 判断是否是外部链接
34 | *
35 | * @param {string} path
36 | * @returns {Boolean}
37 | */
38 | export function isExternal(path: string) {
39 | const isExternal = /^(https?:|http?:|mailto:|tel:)/.test(path);
40 | return isExternal;
41 | }
42 |
43 | /**
44 | * 设置Style属性
45 | *
46 | * @param propName
47 | * @param value
48 | */
49 | export function setStyleProperty(propName: string, value: string) {
50 | document.documentElement.style.setProperty(propName, value);
51 | }
52 |
--------------------------------------------------------------------------------
/webs/src/utils/nprogress.ts:
--------------------------------------------------------------------------------
1 | import NProgress from "nprogress";
2 | import "nprogress/nprogress.css";
3 |
4 | // 进度条
5 | NProgress.configure({
6 | // 动画方式
7 | easing: "ease",
8 | // 递增进度条的速度
9 | speed: 500,
10 | // 是否显示加载ico
11 | showSpinner: false,
12 | // 自动递增间隔
13 | trickleSpeed: 200,
14 | // 初始化时的最小百分比
15 | minimum: 0.3,
16 | });
17 |
18 | export default NProgress;
19 |
--------------------------------------------------------------------------------
/webs/src/views/demo/api/apifox.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
28 |
--------------------------------------------------------------------------------
/webs/src/views/demo/api/knife4j.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
28 |
--------------------------------------------------------------------------------
/webs/src/views/demo/api/swagger.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
28 |
--------------------------------------------------------------------------------
/webs/src/views/demo/dict.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 | 示例源码 请点击>>>>
16 |
17 |
18 |
19 | 值为String: const value = ref("1");
21 |
22 |
23 |
24 |
25 |
26 | 值为Number: const value = ref(1);
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/webs/src/views/demo/icon-selector.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | 示例源码 请点击>>>>
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/webs/src/views/demo/internal-doc.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
29 |
--------------------------------------------------------------------------------
/webs/src/views/demo/multi-level/children/children/level3-1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/webs/src/views/demo/multi-level/children/children/level3-2.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/webs/src/views/demo/multi-level/children/level2.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/webs/src/views/demo/multi-level/level1.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 示例源码 请点击>>>>
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/webs/src/views/demo/upload.vue:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 | 示例源码 请点击>>>>
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/webs/src/views/demo/wang-editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 | 示例源码 请点击>>>>
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/webs/src/views/redirect/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
--------------------------------------------------------------------------------
/webs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "useDefineForClassFields": true,
5 | "module": "esnext",
6 | "moduleResolution": "node",
7 | "strict": true,
8 | "noLib": false,
9 | "sourceMap": true,
10 | "resolveJsonModule": true,
11 | "esModuleInterop": true,
12 | "lib": ["esnext", "dom"],
13 | "baseUrl": ".",
14 | "allowJs": true,
15 | "paths": {
16 | "@/*": ["src/*"]
17 | },
18 | "types": ["vite/client", "unplugin-icons/types/vue", "element-plus/global"],
19 | "skipLibCheck": true /* Skip type checking all .d.ts files. */,
20 | "allowSyntheticDefaultImports": true /* 允许默认导入 */,
21 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
22 |
23 | "jsx": "preserve",
24 | "jsxFactory": "h",
25 | "jsxFragmentFactory": "Fragment"
26 | },
27 | "include": [
28 | "src/**/*.ts",
29 | "src/**/*.vue",
30 | "src/typings/**/*.d.ts",
31 | "mock/**/*.ts",
32 | "vite.config.ts"
33 | ],
34 | "exclude": ["node_modules", "dist", "**/*.js"]
35 | }
36 |
--------------------------------------------------------------------------------
/webs/uno.config.ts:
--------------------------------------------------------------------------------
1 | // uno.config.ts
2 | import {
3 | defineConfig,
4 | presetAttributify,
5 | presetIcons,
6 | presetTypography,
7 | presetUno,
8 | presetWebFonts,
9 | transformerDirectives,
10 | transformerVariantGroup,
11 | } from "unocss";
12 |
13 | export default defineConfig({
14 | shortcuts: {
15 | "flex-center": "flex justify-center items-center",
16 | "flex-x-center": "flex justify-center",
17 | "flex-y-center": "flex items-center",
18 | "wh-full": "w-full h-full",
19 | "flex-x-between": "flex items-center justify-between",
20 | "flex-x-end": "flex items-center justify-end",
21 | "absolute-lt": "absolute left-0 top-0",
22 | "absolute-rt": "absolute right-0 top-0 ",
23 | "fixed-lt": "fixed left-0 top-0",
24 | },
25 | theme: {
26 | colors: {
27 | primary: "var(--el-color-primary)",
28 | primary_dark: "var(--el-color-primary-light-5)",
29 | },
30 | },
31 | presets: [
32 | presetUno(),
33 | presetAttributify(),
34 | presetIcons(),
35 | presetTypography(),
36 | presetWebFonts({
37 | fonts: {
38 | // ...
39 | },
40 | }),
41 | ],
42 | transformers: [transformerDirectives(), transformerVariantGroup()],
43 | });
44 |
--------------------------------------------------------------------------------