├── .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 |
14 |
15 |
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 | "", 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 | "", 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 |
12 |
13 |
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 | 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 | 6 | 7 | 34 | -------------------------------------------------------------------------------- /webs/src/components/Hamburger/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 28 | 29 | 40 | -------------------------------------------------------------------------------- /webs/src/components/LangSelect/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 48 | -------------------------------------------------------------------------------- /webs/src/components/Pagination/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 70 | 71 | 80 | -------------------------------------------------------------------------------- /webs/src/components/SizeSelect/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 40 | -------------------------------------------------------------------------------- /webs/src/components/SvgIcon/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 34 | 35 | 46 | -------------------------------------------------------------------------------- /webs/src/components/Upload/SingleUpload.vue: -------------------------------------------------------------------------------- 1 | 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 | 10 | 11 | 20 | -------------------------------------------------------------------------------- /webs/src/layout/components/NavBar/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 19 | -------------------------------------------------------------------------------- /webs/src/layout/components/Settings/components/ThemeColorPicker.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 36 | 37 | 42 | -------------------------------------------------------------------------------- /webs/src/layout/components/Sidebar/components/SidebarLogo.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 31 | 32 | 65 | -------------------------------------------------------------------------------- /webs/src/layout/components/Sidebar/components/SidebarMenu.vue: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 65 | -------------------------------------------------------------------------------- /webs/src/layout/components/Sidebar/components/SidebarMenuItemTitle.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | 25 | 43 | -------------------------------------------------------------------------------- /webs/src/layout/components/Sidebar/index.vue: -------------------------------------------------------------------------------- 1 | 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 | 12 | 13 | 28 | -------------------------------------------------------------------------------- /webs/src/views/demo/api/knife4j.vue: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 28 | -------------------------------------------------------------------------------- /webs/src/views/demo/api/swagger.vue: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 28 | -------------------------------------------------------------------------------- /webs/src/views/demo/dict.vue: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 33 | -------------------------------------------------------------------------------- /webs/src/views/demo/icon-selector.vue: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | -------------------------------------------------------------------------------- /webs/src/views/demo/internal-doc.vue: -------------------------------------------------------------------------------- 1 | 9 | 29 | -------------------------------------------------------------------------------- /webs/src/views/demo/multi-level/children/children/level3-1.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /webs/src/views/demo/multi-level/children/children/level3-2.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /webs/src/views/demo/multi-level/children/level2.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /webs/src/views/demo/multi-level/level1.vue: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /webs/src/views/demo/upload.vue: -------------------------------------------------------------------------------- 1 | 2 | 18 | 38 | -------------------------------------------------------------------------------- /webs/src/views/demo/wang-editor.vue: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 20 | -------------------------------------------------------------------------------- /webs/src/views/redirect/index.vue: -------------------------------------------------------------------------------- 1 | 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 | --------------------------------------------------------------------------------