├── .browserslistrc ├── .env ├── .eslintrc.js ├── .github └── workflows │ ├── build.yml │ └── docker-build-push.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── babel.config.js ├── package.json ├── public ├── _redirects ├── favicon.ico ├── img │ └── icons │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── android-chrome-maskable-192x192.png │ │ ├── android-chrome-maskable-512x512.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── msapplication-icon-144x144.png │ │ ├── mstile-150x150.png │ │ └── safari-pinned-tab.svg ├── index.html ├── manifest.json └── robots.txt ├── services ├── .env ├── .gitignore ├── data │ └── .gitkeep └── docker-compose.yaml ├── src ├── App.vue ├── assets │ ├── css │ │ ├── element-ui.scss │ │ └── element-variables.scss │ └── logo.png ├── components │ └── SvgIcon │ │ └── index.vue ├── icons │ ├── index.js │ └── svg │ │ └── github.svg ├── main.js ├── plugins │ ├── axios.js │ ├── base64.js │ ├── clipboard.js │ ├── device.js │ ├── element-ui.js │ └── particles.js ├── registerServiceWorker.js ├── router │ └── index.js └── views │ └── Subconverter.vue ├── vue.config.js └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | VUE_APP_PROJECT = "https://github.com/CareyWang/sub-web" 2 | 3 | VUE_APP_BOT_LINK = "https://t.me/subconverter_discuss" 4 | 5 | VUE_APP_BACKEND_RELEASE = "https://github.com/tindy2013/subconverter/actions" 6 | 7 | VUE_APP_SUBCONVERTER_REMOTE_CONFIG = "https://raw.githubusercontent.com/tindy2013/subconverter/master/base/config/example_external_config.ini" 8 | 9 | VUE_APP_SUBCONVERTER_DOC_ADVANCED = "https://github.com/tindy2013/subconverter/blob/master/README-cn.md#%E8%BF%9B%E9%98%B6%E9%93%BE%E6%8E%A5" 10 | 11 | # API 后端 12 | VUE_APP_SUBCONVERTER_DEFAULT_BACKEND = "https://api.wcc.best" 13 | 14 | # 短链接后端 15 | VUE_APP_MYURLS_API = "https://suo.yt/short" 16 | 17 | # 文本托管后端 18 | VUE_APP_CONFIG_UPLOAD_API = "https://oss.wcc.best/upload" 19 | 20 | # 页面配置 21 | VUE_APP_USE_STORAGE = true 22 | VUE_APP_CACHE_TTL = 86400 23 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | 'eslint:recommended' 9 | ], 10 | rules: { 11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 13 | 'semi': 0, 14 | 'vue/multi-word-component-names': 'off' 15 | }, 16 | parserOptions: { 17 | parser: '@babel/eslint-parser' 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [ master, dev ] 6 | 7 | jobs: 8 | 9 | build: 10 | name: Build 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [20.x] 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: Use Node.js ${{ matrix.node-version }} 21 | uses: actions/setup-node@v1 22 | with: 23 | node-version: ${{ matrix.node-version }} 24 | 25 | - name: Get dependencies and build 26 | run: | 27 | yarn install 28 | yarn build 29 | 30 | - name: Upload 31 | uses: actions/upload-artifact@v4 32 | with: 33 | name: dist 34 | path: dist/ 35 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-push.yml: -------------------------------------------------------------------------------- 1 | name: Build and Push Multi-Arch Docker Image 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build-and-push: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Check out repository 14 | uses: actions/checkout@master 15 | 16 | - name: Set up Docker Buildx 17 | uses: docker/setup-buildx-action@v2 18 | 19 | - name: Log in to Docker Hub 20 | uses: docker/login-action@v2 21 | with: 22 | username: ${{ secrets.DOCKERHUB_USERNAME }} 23 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 24 | 25 | - name: Build and push Docker image 26 | uses: docker/build-push-action@v3 27 | with: 28 | context: . 29 | platforms: linux/amd64,linux/arm64 30 | push: true 31 | tags: careywong/subweb:latest 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # ---- Dependencies ---- 2 | FROM node:20-alpine AS build 3 | WORKDIR /app 4 | COPY . . 5 | RUN yarn install 6 | RUN yarn build 7 | 8 | FROM nginx:1.24-alpine 9 | COPY --from=build /app/dist /usr/share/nginx/html 10 | EXPOSE 80 11 | CMD [ "nginx", "-g", "daemon off;" ] 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 CareyWong 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sub-web 2 | 3 | 基于 vue-cli 与 [tindy2013/subconverter](https://github.com/tindy2013/subconverter) 后端实现的配置自动生成。 4 | 5 | ## Table of Contents 6 | 7 | - [ChangeLog](#ChangeLog) 8 | - [Docker](#Docker) 9 | - [Requirements](#Requirements) 10 | - [Install](#install) 11 | - [Usage](#usage) 12 | - [Related](#Related) 13 | - [Contributing](#contributing) 14 | - [License](#license) 15 | 16 | ## ChangeLog 17 | 18 | - 20200730 19 | 20 | - 独立各类后端配置到 .env 文件中,现在修改后端只需要修改 .env 即可。 21 | 22 | 23 | ## Docker 24 | 25 | ```shell 26 | docker run -d -p 58080:80 --restart always --name subweb careywong/subweb:latest 27 | ``` 28 | 29 | 若需要对代码进行修改,你需要在本地构建镜像并运行。 30 | 注:每次修改代码,你都需要重新执行 docker build 来执行打包操作。 31 | 32 | ```shell 33 | docker -v 34 | Docker version 23.0.4, build f480fb1 35 | 36 | docker build -t subweb-local:latest . 37 | docker run -d -p 58080:80 --restart always --name subweb subweb-local:latest 38 | ``` 39 | 40 | ## Requirements 41 | 42 | 你需要安装 [Node](https://nodejs.org/zh-cn/) 与 [Yarn](https://legacy.yarnpkg.com/en/docs/install) 来安装依赖与打包发布。你可以通过以下命令查看是否安装成功。 43 | 注:以下步骤为 Ubuntu 下相应命令,其他系统请自行修改。为了方便后来人解决问题,有问题请发 issue。 44 | 45 | ```shell 46 | node -v 47 | v20.xx.x 48 | 49 | yarn -v 50 | 1.22.22 51 | ``` 52 | 53 | ## Install 54 | 55 | ```shell 56 | yarn install 57 | ``` 58 | 59 | ## Usage 60 | 61 | ```shell 62 | yarn serve 63 | ``` 64 | 65 | 浏览器访问 66 | 67 | ## Deploy 68 | 69 | 发布到线上环境,你需要安装依赖,执行以下打包命令,生成的 dist 目录即为发布目录。如需修改默认后端,请修改 src/views/Subconverter.vue 中 **defaultBackend** 配置项。 70 | 71 | ```shell 72 | yarn build 73 | ``` 74 | 75 | 你需要安装 nginx (或其他 web 服务器)并正确配置。以下为示例配置,你需要修改 example.com 为自己域名并配置正确的项目根路径(https 自行配置)。 76 | 77 | ```shell 78 | server { 79 | listen 80; 80 | server_name example.com; 81 | 82 | root /var/www/http/sub-web/dist; 83 | index index.html index.htm; 84 | 85 | error_page 404 /index.html; 86 | 87 | gzip on; #开启gzip压缩 88 | gzip_min_length 1k; #设置对数据启用压缩的最少字节数 89 | gzip_buffers 4 16k; 90 | gzip_http_version 1.0; 91 | gzip_comp_level 6; #设置数据的压缩等级,等级为1-9,压缩比从小到大 92 | gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml; #设置需要压缩的数据格式 93 | gzip_vary on; 94 | 95 | location ~* \.(css|js|png|jpg|jpeg|gif|gz|svg|mp4|ogg|ogv|webm|htc|xml|woff)$ { 96 | access_log off; 97 | add_header Cache-Control "public,max-age=30*24*3600"; 98 | } 99 | } 100 | ``` 101 | 102 | ## Related 103 | 104 | - [tindy2013/subconverter](https://github.com/tindy2013/subconverter) 105 | - [CareyWang/MyUrls](https://github.com/CareyWang/MyUrls) 106 | 107 | ## Contributing 108 | 109 | PRs accepted. 110 | 111 | Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. 112 | 113 | ## License 114 | 115 | MIT © 2020 CareyWang 116 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ], 5 | plugins: [ 6 | [ 7 | "component", 8 | { 9 | "libraryName": "element-ui", 10 | "styleLibraryName": "theme-chalk" 11 | } 12 | ] 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sub-web", 3 | "version": "0.1.0", 4 | "private": true, 5 | "engines": { 6 | "node": ">=20.0.0" 7 | }, 8 | "scripts": { 9 | "serve": "vue-cli-service serve", 10 | "build": "vue-cli-service build", 11 | "lint": "vue-cli-service lint" 12 | }, 13 | "dependencies": { 14 | "atob": "^2.1.2", 15 | "axios": "^0.21.1", 16 | "btoa": "^1.2.1", 17 | "core-js": "^3.12.1", 18 | "element-ui": "^2.15.1", 19 | "register-service-worker": "^1.7.1", 20 | "vue": "^2.6.10", 21 | "vue-clipboard2": "^0.3.1", 22 | "vue-router": "^3.5.1" 23 | }, 24 | "devDependencies": { 25 | "@babel/core": "^7.26.0", 26 | "@babel/eslint-parser": "^7.25.9", 27 | "@vue/cli-plugin-babel": "5", 28 | "@vue/cli-plugin-eslint": "5", 29 | "@vue/cli-plugin-pwa": "5", 30 | "@vue/cli-plugin-router": "5", 31 | "@vue/cli-service": "5", 32 | "babel-plugin-component": "^1.1.1", 33 | "babel-plugin-import": "^1.13.3", 34 | "eslint": "8.56.0", 35 | "eslint-plugin-vue": "9.17.0", 36 | "sass": "^1.43.4", 37 | "sass-loader": "^8.0.0", 38 | "svg-sprite-loader": "6.0.11", 39 | "vue-particles": "^1.0.9", 40 | "vue-template-compiler": "^2.6.10" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | # 单页应用的 Netlify 设置 2 | /* /index.html 200 -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/favicon.ico -------------------------------------------------------------------------------- /public/img/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-maskable-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/android-chrome-maskable-192x192.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-maskable-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/android-chrome-maskable-512x512.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /public/img/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/favicon-16x16.png -------------------------------------------------------------------------------- /public/img/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/favicon-32x32.png -------------------------------------------------------------------------------- /public/img/icons/msapplication-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/msapplication-icon-144x144.png -------------------------------------------------------------------------------- /public/img/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/public/img/icons/mstile-150x150.png -------------------------------------------------------------------------------- /public/img/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | sub-web 10 | 11 | 12 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "sub-web", 3 | "name": "sub-web", 4 | "icon": [ 5 | { 6 | "src": "./img/icons/icon-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "./img/icons/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "start_url": "index.html", 17 | "display": "standalone", 18 | "background_color": "#002140", 19 | "theme_color": "#002140" 20 | } 21 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /services/.env: -------------------------------------------------------------------------------- 1 | SUBWEB_PORT=58080 2 | 3 | MYURLS_PORT=8002 4 | MYURLS_DOMAIN=example.com 5 | MYURLS_TTL=180 6 | -------------------------------------------------------------------------------- /services/.gitignore: -------------------------------------------------------------------------------- 1 | data/ 2 | -------------------------------------------------------------------------------- /services/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/services/data/.gitkeep -------------------------------------------------------------------------------- /services/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | subweb: 4 | build: ../. 5 | container_name: subweb 6 | restart: always 7 | ports: 8 | - "${SUBWEB_PORT}:80" 9 | 10 | myurls: 11 | image: "careywong/myurls:latest" 12 | container_name: myurls 13 | restart: always 14 | ports: 15 | - "${MYURLS_PORT}:8002" 16 | volumes: 17 | - ./data/myurls/logs:/app/logs 18 | depends_on: 19 | - myurls-redis 20 | entrypoint: ["/app/myurls", "-domain", "${MYURLS_DOMAIN}", "-conn", myurls-redis:6379, "-ttl", "${MYURLS_TTL}"] 21 | 22 | myurls-redis: 23 | image: "redis:5" 24 | container_name: myurls-redis 25 | restart: always 26 | volumes: 27 | - ./data/redis:/data 28 | expose: 29 | - "6379" 30 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/assets/css/element-ui.scss: -------------------------------------------------------------------------------- 1 | // cover some element-ui styles 2 | 3 | .el-breadcrumb__inner, 4 | .el-breadcrumb__inner a { 5 | font-weight: 400 !important; 6 | } 7 | 8 | .el-upload { 9 | input[type="file"] { 10 | display: none !important; 11 | } 12 | } 13 | 14 | .el-upload__input { 15 | display: none; 16 | } 17 | 18 | .cell { 19 | .el-tag { 20 | margin-right: 0px; 21 | } 22 | } 23 | 24 | .small-padding { 25 | .cell { 26 | padding-left: 5px; 27 | padding-right: 5px; 28 | } 29 | } 30 | 31 | .fixed-width { 32 | .el-button--mini { 33 | padding: 7px 10px; 34 | width: 60px; 35 | } 36 | } 37 | 38 | .status-col { 39 | .cell { 40 | padding: 0 10px; 41 | text-align: center; 42 | 43 | .el-tag { 44 | margin-right: 0px; 45 | } 46 | } 47 | } 48 | 49 | // to fixed https://github.com/ElemeFE/element/issues/2461 50 | .el-dialog { 51 | transform: none; 52 | left: 0; 53 | position: relative; 54 | margin: 0 auto; 55 | } 56 | 57 | // refine element ui upload 58 | .upload-container { 59 | .el-upload { 60 | width: 100%; 61 | 62 | .el-upload-dragger { 63 | width: 100%; 64 | height: 200px; 65 | } 66 | } 67 | } 68 | 69 | // dropdown 70 | .el-dropdown-menu { 71 | a { 72 | display: block 73 | } 74 | } 75 | 76 | // fix date-picker ui bug in filter-item 77 | .el-range-editor.el-input__inner { 78 | display: inline-flex !important; 79 | } -------------------------------------------------------------------------------- /src/assets/css/element-variables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * I think element-ui's default theme color is too light for long-term use. 3 | * So I modified the default color and you can modify it to your liking. 4 | **/ 5 | 6 | /* theme color */ 7 | $--color-primary: #304156; 8 | $--color-success: #65C934; 9 | $--color-warning: #E6A23C; 10 | $--color-danger: #F56C6C; 11 | // $--color-info: #1E1E1E; 12 | 13 | $--button-font-weight: 400; 14 | 15 | // $--color-text-regular: #1f2d3d; 16 | 17 | $--border-color-light: #dfe4ed; 18 | $--border-color-lighter: #e6ebf5; 19 | 20 | $--table-border:1px solid#dfe6ec; 21 | 22 | /* icon font path, required */ 23 | $--font-path: '~element-ui/lib/theme-chalk/fonts'; 24 | 25 | @import "~element-ui/packages/theme-chalk/src/index"; 26 | 27 | // the :export directive is the magic sauce for webpack 28 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass 29 | :export { 30 | theme: $--color-primary; 31 | } -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CareyWang/sub-web/a8788c1a02e100ada38efc48ab72f390cd41d54c/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/SvgIcon/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 34 | 35 | 44 | -------------------------------------------------------------------------------- /src/icons/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import SvgIcon from '@/components/SvgIcon'// svg component 3 | 4 | // register globally 5 | Vue.component('svg-icon', SvgIcon) 6 | 7 | const req = require.context('./svg', false, /\.svg$/) 8 | const requireAll = requireContext => requireContext.keys().map(requireContext) 9 | requireAll(req) 10 | -------------------------------------------------------------------------------- /src/icons/svg/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | require(`@/plugins/element-ui`) 5 | require(`@/plugins/clipboard`) 6 | require(`@/plugins/base64`) 7 | require(`@/plugins/particles`) 8 | require(`@/plugins/axios`) 9 | require(`@/plugins/device`) 10 | 11 | import '@/icons' // icon 12 | import './registerServiceWorker' 13 | 14 | Vue.config.productionTip = false 15 | 16 | new Vue({ 17 | router, 18 | render: h => h(App) 19 | }).$mount('#app') 20 | -------------------------------------------------------------------------------- /src/plugins/axios.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import axios from "axios" 3 | 4 | axios.defaults.timeout = 5000 //请求超时的时间设定 5 | 6 | Vue.prototype.$axios = axios -------------------------------------------------------------------------------- /src/plugins/base64.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import btoa from 'btoa' 3 | import atob from 'atob' 4 | 5 | Vue.prototype.$btoa = (string) => btoa(string) 6 | Vue.prototype.$atob = (string) => atob(string) 7 | -------------------------------------------------------------------------------- /src/plugins/clipboard.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import clipboard from 'vue-clipboard2' 3 | 4 | Vue.use(clipboard) 5 | -------------------------------------------------------------------------------- /src/plugins/device.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.prototype.$getOS = () => { 4 | let ua = navigator.userAgent, 5 | isWindowsPhone = /(?:Windows Phone)/.test(ua), 6 | isSymbian = /(?:SymbianOS)/.test(ua) || isWindowsPhone, 7 | isAndroid = /(?:Android)/.test(ua), 8 | isFireFox = /(?:Firefox)/.test(ua), 9 | // isChrome = /(?:Chrome|CriOS)/.test(ua), 10 | isTablet = /(?:iPad|PlayBook)/.test(ua) || (isAndroid && !/(?:Mobile)/.test(ua)) || (isFireFox && /(?:Tablet)/.test(ua)), 11 | isIPhone = /(?:iPhone)/.test(ua) && !isTablet, 12 | isPc = !isIPhone && !isAndroid && !isSymbian && !isWindowsPhone; 13 | 14 | return { 15 | isTablet: isTablet, 16 | isIPhone: isIPhone, 17 | isAndroid: isAndroid, 18 | isPc: isPc 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/plugins/element-ui.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Element from 'element-ui' 3 | import locale from 'element-ui/lib/locale/lang/zh-CN' 4 | // import '@/assets/css/element-ui.scss' 5 | // import '@/assets/css/element-element-variables.scss' 6 | 7 | Vue.use(Element, { 8 | locale, 9 | size: 'small' 10 | }) 11 | 12 | Vue.use(Element.Loading.directive); 13 | 14 | Vue.prototype.$loading = Element.Loading.service; 15 | Vue.prototype.$msgbox = Element.MessageBox; 16 | Vue.prototype.$alert = Element.MessageBox.alert; 17 | Vue.prototype.$confirm = Element.MessageBox.confirm; 18 | Vue.prototype.$prompt = Element.MessageBox.prompt; 19 | Vue.prototype.$notify = Element.Notification; 20 | Vue.prototype.$message = Element.Message; 21 | -------------------------------------------------------------------------------- /src/plugins/particles.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueParticles from 'vue-particles' 3 | 4 | Vue.use(VueParticles) 5 | -------------------------------------------------------------------------------- /src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { register } from 'register-service-worker' 4 | 5 | if (process.env.NODE_ENV === 'production') { 6 | register(`${process.env.BASE_URL}sub-web.js`, { 7 | ready () { 8 | console.log( 9 | 'App is being served from cache by a service worker.\n' + 10 | 'For more details, visit https://goo.gl/AFskqB' 11 | ) 12 | }, 13 | registered () { 14 | console.log('Service worker has been registered.') 15 | }, 16 | cached () { 17 | console.log('Content has been cached for offline use.') 18 | }, 19 | updatefound () { 20 | console.log('New content is downloading.') 21 | }, 22 | updated () { 23 | console.log('New content is available; please refresh.') 24 | }, 25 | offline () { 26 | console.log('No internet connection found. App is running in offline mode.') 27 | }, 28 | error (error) { 29 | console.error('Error during service worker registration:', error) 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import VueRouter from "vue-router"; 3 | 4 | Vue.use(VueRouter); 5 | 6 | const routes = [ 7 | { 8 | path: "/", 9 | name: "SubConverter", 10 | component: () => import("../views/Subconverter.vue") 11 | } 12 | ]; 13 | 14 | const router = new VueRouter({ 15 | mode: "history", 16 | base: process.env.BASE_URL, 17 | routes 18 | }); 19 | 20 | export default router; 21 | -------------------------------------------------------------------------------- /src/views/Subconverter.vue: -------------------------------------------------------------------------------- 1 | 196 | 197 | 758 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | function resolve(dir) { 4 | return path.join(__dirname, dir) 5 | } 6 | 7 | module.exports = { 8 | css: { 9 | loaderOptions: { 10 | less: { 11 | javascriptEnabled: true 12 | } 13 | } 14 | }, 15 | 16 | chainWebpack: config => { 17 | // set svg-sprite-loader 18 | config.module 19 | .rule('svg') 20 | .exclude.add(resolve('src/icons')) 21 | .end() 22 | config.module 23 | .rule('icons') 24 | .test(/\.svg$/) 25 | .include.add(resolve('src/icons')) 26 | .end() 27 | .use('svg-sprite-loader') 28 | .loader('svg-sprite-loader') 29 | .options({ 30 | symbolId: 'icon-[name]' 31 | }) 32 | .end() 33 | }, 34 | 35 | pwa: { 36 | workboxOptions: { 37 | // https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin 38 | skipWaiting: true, 39 | clientsClaim: true, 40 | importScripts: [ 41 | 'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js' 42 | ], 43 | navigateFallback: '/', 44 | navigateFallbackDenylist: [/\/api\//] 45 | } 46 | } 47 | }; 48 | --------------------------------------------------------------------------------