├── public ├── favicon.ico ├── index.dev.html └── index.prod.html ├── src ├── assets │ ├── logo.png │ ├── background.png │ ├── nuaa_logo.jpeg │ ├── default_upload_icon │ │ ├── doc.png │ │ ├── pdf.png │ │ ├── ppt.png │ │ ├── rar.png │ │ ├── xls.png │ │ └── zip.png │ ├── logo.svg │ ├── docs │ │ ├── Privacy_Policy.md │ │ └── Terms_of_Use.md │ ├── css │ │ └── FilelistView.css │ └── background.svg ├── components │ ├── RecodeUnauthored.css │ ├── RecodeUnauthored.vue │ ├── UploadedFiles.css │ ├── Navbar.css │ ├── Navbar.vue │ ├── Home.vue │ ├── Download.css │ ├── Download.vue │ ├── Home.css │ ├── RecodeDisplay.css │ ├── upload.css │ ├── UploadedFiles.vue │ ├── RecodeDisplay.vue │ └── upload.vue ├── UploadView.vue ├── DownloadView.vue ├── UploadedRecodeView.vue ├── Global.vue ├── HomeView.vue ├── About.vue ├── Privacy.vue ├── Terms.vue ├── App.vue ├── main.prod.js ├── main.dev.js └── FilelistView.vue ├── .env.development ├── .env.local ├── .env.production ├── .env.staging ├── babel.config.js ├── .gitignore ├── vue.config.js ├── Dockerfile ├── docs └── events.md ├── webpack.config.js ├── README.md ├── scripts └── docker.sh └── package.json /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUAA-Open-Source/safeu-frontend/dev/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUAA-Open-Source/safeu-frontend/dev/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUAA-Open-Source/safeu-frontend/dev/src/assets/background.png -------------------------------------------------------------------------------- /src/assets/nuaa_logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUAA-Open-Source/safeu-frontend/dev/src/assets/nuaa_logo.jpeg -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | VUE_APP_CURRENTMODE = 'development' 2 | VUE_APP_TITLE=safeu-frontend (dev) 3 | NODE_ENV = 'development' -------------------------------------------------------------------------------- /.env.local: -------------------------------------------------------------------------------- 1 | VUE_APP_CURRENTMODE = 'local' 2 | VUE_APP_TITLE=safeu-frontend 3 | NODE_ENV = 'production' 4 | outputDir = 'dist' -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | VUE_APP_CURRENTMODE = 'production' 2 | VUE_APP_TITLE=safeu-frontend 3 | NODE_ENV = 'production' 4 | outputDir = 'dist' -------------------------------------------------------------------------------- /.env.staging: -------------------------------------------------------------------------------- 1 | VUE_APP_CURRENTMODE = 'staging' 2 | VUE_APP_TITLE=safeu-frontend (staging) 3 | NODE_ENV = 'production' 4 | outputDir = 'dist' -------------------------------------------------------------------------------- /src/assets/default_upload_icon/doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUAA-Open-Source/safeu-frontend/dev/src/assets/default_upload_icon/doc.png -------------------------------------------------------------------------------- /src/assets/default_upload_icon/pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUAA-Open-Source/safeu-frontend/dev/src/assets/default_upload_icon/pdf.png -------------------------------------------------------------------------------- /src/assets/default_upload_icon/ppt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUAA-Open-Source/safeu-frontend/dev/src/assets/default_upload_icon/ppt.png -------------------------------------------------------------------------------- /src/assets/default_upload_icon/rar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUAA-Open-Source/safeu-frontend/dev/src/assets/default_upload_icon/rar.png -------------------------------------------------------------------------------- /src/assets/default_upload_icon/xls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUAA-Open-Source/safeu-frontend/dev/src/assets/default_upload_icon/xls.png -------------------------------------------------------------------------------- /src/assets/default_upload_icon/zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NUAA-Open-Source/safeu-frontend/dev/src/assets/default_upload_icon/zip.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@vue/app", 5 | { 6 | useBuiltIns: "entry", 7 | }, 8 | ], 9 | ], 10 | }; 11 | -------------------------------------------------------------------------------- /src/components/RecodeUnauthored.css: -------------------------------------------------------------------------------- 1 | .container { 2 | width: 40%; 3 | height: 80%; 4 | margin-left: 30%; 5 | margin-top: 5%; 6 | display: flex; 7 | flex-direction: row; 8 | justify-content: center; 9 | align-items: center; 10 | } 11 | 12 | .unauthored-title { 13 | font-size: 28px; 14 | } 15 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /src/components/RecodeUnauthored.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /src/components/UploadedFiles.css: -------------------------------------------------------------------------------- 1 | @media (max-width: 700px) { 2 | .uploadedfiles-container { 3 | width: 90%; 4 | margin-top: 20px; 5 | margin-bottom: 40px; 6 | } 7 | } 8 | 9 | @media (min-width: 700px) { 10 | .uploadedfiles-container { 11 | width: 600px; 12 | margin-top: 20px; 13 | margin-bottom: 40px; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | Artboard 46 2 | -------------------------------------------------------------------------------- /src/UploadView.vue: -------------------------------------------------------------------------------- 1 | 6 | 19 | 29 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | publicPath: "/", 3 | outputDir: process.env.outputDir, 4 | assetsDir: "static", 5 | productionSourceMap: false, 6 | pages: { 7 | index: { 8 | entry: 9 | process.env.NODE_ENV === "production" 10 | ? "./src/main.prod.js" 11 | : "./src/main.dev.js", 12 | template: 13 | process.env.NODE_ENV === "production" 14 | ? "./public/index.prod.html" 15 | : "./public/index.dev.html", 16 | }, 17 | }, 18 | devServer: { 19 | disableHostCheck: true 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /src/DownloadView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | 28 | -------------------------------------------------------------------------------- /public/index.dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | SafeU | 云U盘 9 | 10 | 11 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10-alpine 2 | 3 | # install simple http server for serving static content 4 | RUN npm install -g http-server --registry=https://registry.npm.taobao.org 5 | 6 | # make the 'app' folder the current working directory 7 | WORKDIR /app 8 | 9 | # copy both 'package.json' and 'package-lock.json' (if available) 10 | COPY package*.json ./ 11 | 12 | # install project dependencies 13 | RUN npm config set registry https://registry.npm.taobao.org && \ 14 | npm install --registry=https://registry.npm.taobao.org 15 | 16 | # copy project files and folders to the current working directory (i.e. 'app' folder) 17 | COPY . . 18 | 19 | # build app for production with minification 20 | RUN npm run build 21 | 22 | EXPOSE 8080 23 | CMD [ "http-server", "dist" ] 24 | -------------------------------------------------------------------------------- /src/assets/docs/Privacy_Policy.md: -------------------------------------------------------------------------------- 1 | # SafeU 云U盘的隐私权政策 2 | 3 | > 您使用 SafeU 云U盘,即表示您信赖我们对您信息的处理方式。我们深知这项责任事关重大,因此我们将矢志不渝地保护您的信息,并让您拥有控制权。 4 | 5 | ## 收集的信息及其处理方式 6 | 7 | 1. 您的浏览器标识、设备标识信息。我们会收集您访问 SafeU 服务时使用的应用、浏览器和设备的相关信息,以便提供对特定设备的产品优化。这些信息同样会提供给我们的开发者以确定产品的优化方向。 8 | 2. 您上传文件的文件名、文件类型、文件大小等文件信息。我们提供文件上传、暂存与下载服务,我们对您的文件的存储、压缩等处理方式依赖于您的文件信息。我们不会查看您的文件内容,除非满足下述《信息分享条款》中的条件 9 | 3. 您在使用本产品时的行为特征。主要包括使用时间段、页面停留时间、产品使用偏好。这些信息将会帮助我们对产品进行有针对性的优化。 10 | 4. 您的所有隐私信息将会以匿名方式上传。 11 | 12 | ## 信息分享条款 13 | 14 | 我们不会与任何第三方政府、组织、企业或个人分享您的任何信息,除非以下情况: 15 | 16 | 1. 征得您的同意。 17 | 2. 出于法律原因。如果我们有充分理由相信,出于以下目的有必要访问、使用、保留或披露您的信息,我们将会与第三方分享您的个人信息: 18 | - 实施适用的服务条款,包括调查可能存在的违规情况。 19 | - 满足任何适用法律、法规、法律程序的要求或强制性的政府要求。 20 | - 检测、防范或解决欺诈、安全或技术问题。 21 | - 在法律要求或允许的范围内,保护 A2OS 团队、我们的用户或公众的权利、财产或安全免遭损害。 -------------------------------------------------------------------------------- /src/assets/docs/Terms_of_Use.md: -------------------------------------------------------------------------------- 1 | # SafeU 云U盘的使用条款 2 | 3 | > 南航,会驶向开源的宇宙 4 | 5 | 欢迎使用 SafeU 云U盘,本项目由南京航空航天大学 A2OS 团队开发并供南航内部乃至全体人类使用,旨在给大家提供更加便捷的文件传输服务,推广云存储、淘汰旧时代的U盘等媒介,并将文件隐私泄露、靠U盘传播的病毒扼杀在摇篮之中。 6 | 7 | ## 我们提供的服务 8 | 9 | 我们为大家提供免费且便捷的文件上传、暂存、下载服务。要使用我们的任意服务,您必须连接互联网,并在我们的网站内完成操作。 10 | 11 | 1. 文件上传服务。您可以通过本产品内的“上传”功能,将您本地的文件上传至本站。单次最多上传 20 个文件,总大小不超过 50M。 12 | 2. 文件暂存服务。根据您的设定,您上传的文件将在本站暂存 4-24 小时。 13 | 3. 文件下载服务。根据您的个人设定,您可以通过自动生成或个人指定的提取码在本站进行下载,或者通过扫码获取链接完成下载。您可以根据自己的需求选择下载次数。如果您设置了文件加密,则必须输入正确的密码才能下载。 14 | 4. 达到以下条件,您上传的文件将被本站彻底删除。 15 | 1. 达到您设定的文件暂存时间。 16 | 2. 达到您设定的最大下载次数。 17 | 18 | ## 隐私政策 19 | 20 | 详见本站首页的“隐私政策”链接。 21 | 22 | ## 免责声明 23 | 24 | 1. 我们尽力做到最好,但是不能保证万无一失,如果遇到天灾人祸等不可抗力,您暂存的文件可能在规定时间或下载次数以内,就无法进行下载。故请务必保留您重要文件的备份。 25 | 2. 在公测期间,本产品可能存在或多或少的故障,某些故障可能影响您的使用。遇到问题,请使用本站的反馈功能与我们取得联系。 26 | 3. 一旦达到文件删除条件,您的文件将无法找回。故请务必选择您需要的文件留存时间、文件下载次数,并留意是否达到条件。 -------------------------------------------------------------------------------- /src/components/Navbar.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | width: 90%; 3 | position: absolute; 4 | margin-left: 5%; 5 | height: 80px; 6 | margin-top: 0; 7 | display: flex; 8 | flex-direction: row; 9 | justify-content: space-between; 10 | align-items: center; 11 | } 12 | 13 | .logo { 14 | display: flex; 15 | flex-direction: row; 16 | justify-content: center; 17 | align-items: center; 18 | } 19 | 20 | .logo-name { 21 | font-size: 30px; 22 | font-weight: bold; 23 | color: black; 24 | } 25 | 26 | .logo-sub { 27 | display: flex; 28 | flex-direction: column; 29 | justify-content: center; 30 | align-items: flex-start; 31 | margin-left: 12px; 32 | } 33 | 34 | .logo-sub p { 35 | margin-bottom: 0; 36 | } 37 | 38 | .logo-subname { 39 | font-size: 12px; 40 | font-weight: 500; 41 | } 42 | 43 | .logo-des { 44 | font-size: 12px; 45 | } 46 | 47 | .feedback { 48 | background: #40a9ff; 49 | padding: 4px 8px; 50 | border-radius: 4px; 51 | } 52 | 53 | .feedback a { 54 | color: white; 55 | } 56 | -------------------------------------------------------------------------------- /src/UploadedRecodeView.vue: -------------------------------------------------------------------------------- 1 | 10 | 32 | 45 | -------------------------------------------------------------------------------- /src/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 45 | 46 | 49 | -------------------------------------------------------------------------------- /src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 24 | 38 | 41 | -------------------------------------------------------------------------------- /src/components/Download.css: -------------------------------------------------------------------------------- 1 | @media (max-width: 700px) { 2 | .download-container { 3 | width: 90%; 4 | height: 60%; 5 | display: flex; 6 | flex-direction: column; 7 | justify-content: start; 8 | align-items: center; 9 | } 10 | } 11 | 12 | @media (min-width: 700px) { 13 | .download-container { 14 | width: 600px; 15 | height: 60%; 16 | display: flex; 17 | flex-direction: column; 18 | justify-content: start; 19 | align-items: center; 20 | } 21 | } 22 | 23 | .download-top-hint { 24 | font-size: 32px; 25 | font-weight: 800; 26 | } 27 | 28 | .download-recode-input { 29 | width: 160px; 30 | text-align: center; 31 | padding: 4px 20px 4px 20px; 32 | outline: none; 33 | border: 1px solid #cccccc; 34 | border-radius: 12px; 35 | font-size: 28px; 36 | font-weight: 800; 37 | color: #cd365f; 38 | } 39 | 40 | .download-password-input { 41 | height: 52px; 42 | margin-top: 20px; 43 | padding: 4px 4px 4px 4px; 44 | width: 160px; 45 | border: 1px solid #cccccc; 46 | border-radius: 12px; 47 | font-size: 20px; 48 | outline: none; 49 | text-align: center; 50 | } 51 | 52 | .download-button { 53 | width: 160px; 54 | margin-top: 40px; 55 | padding: 10px 4px; 56 | background: #3596ff; 57 | border: none; 58 | color: white; 59 | text-align: center; 60 | font-size: 20px; 61 | font-weight: 800; 62 | border-radius: 30px; 63 | } 64 | -------------------------------------------------------------------------------- /docs/events.md: -------------------------------------------------------------------------------- 1 | # 前端数据埋点 2 | 3 | ## Beta 4 | | 埋点名称 | 埋点对应含义 | 5 | | ------------------------------------------------------------------------------------------------------------- | ------------ | 6 | | home | 主页 | 7 | | upload

- homebutton(首页上传按钮)
- 无 from (url) | 上传页 | 8 | | download

- homebutton(首页下载按钮)
- history(历史上传)
- qrcode(二维码)
- copyurl(拷贝链接)
- 无 from (url) | 下载输入提取码页面 | 9 | | file_list | 文件列表 | 10 | | upload_success | 上传成功后显示提取码页面 | 11 | | delete_expired_file | 删除过期文件 | 12 | | delete_file | 手动删除文件 | 13 | | recode_display_backbtn | 修改提取码页返回按钮 | 14 | | zip_download | 打包下载 | 15 | 16 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const { join: pathJoin } = require("path"); 2 | const VueLoaderPlugin = require("vue-loader/lib/plugin"); // +++ 3 | const BundleAnalyzerPlugin = require("webpack-bundle-analyzer") 4 | .BundleAnalyzerPlugin; 5 | require("babel-polyfill"); 6 | module.exports = { 7 | mode: "production", 8 | entry: { 9 | app: ["babel-polyfill", "./src/main.js"], 10 | }, 11 | externals: { 12 | vue: "Vue", 13 | "vue-router": "VueRouter", 14 | antd: "antd", 15 | }, 16 | output: { 17 | filename: "[name].bundle.js", 18 | path: pathJoin(__dirname, "./dist"), 19 | }, 20 | module: { 21 | rules: [ 22 | { 23 | test: /\.js$/, 24 | loader: "babel-loader", 25 | include: [resolve("src"), resolve("/node_modules/vue-qr/src")], 26 | }, 27 | { 28 | test: /\.vue$/, 29 | use: ["vue-loader"], // +++ 30 | }, 31 | { 32 | test: /\.css$/, 33 | use: [ 34 | { 35 | loader: "style-loader", 36 | }, 37 | { 38 | loader: "css-loader", 39 | options: { 40 | sourceMap: true, 41 | }, 42 | }, 43 | ], // +++ 44 | }, 45 | { 46 | test: /\.(jpe?g|png|gif|svg)$/i, 47 | loader: "file-loader?name=/public/icons/[name].[ext]", 48 | }, 49 | ], 50 | }, 51 | plugins: [new VueLoaderPlugin(), new BundleAnalyzerPlugin()], 52 | babel: { 53 | presets: ["es2015"], 54 | plugins: ["transform-runtime"], 55 | }, 56 | }; 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # safeu-frontend 2 | > SafeU 前端仓库 3 | 4 | ## Framework 5 | 本项目使用 `Vue` 前端框架,使用 `yarn` 作为依赖管理工具。 6 | 7 | ### Dependencies we used 8 | > 详细的依赖版本号可见 `package.json` 文件 9 | 10 | - plupload 文件上传组件 11 | - ant-design-vue 大部分组件使用该组件库 12 | - vue-router 路由管理 13 | - VueQriously 二维码生成 14 | - FontAwesome 图标库 15 | - vue-clipboard2 自动复制 16 | 17 | ## Install & Run 18 | ### For development 19 | 20 | ``` 21 | yarn install 22 | yarn run serve 23 | ``` 24 | ### For production 25 | 通过 `vue.config.js` 配置 `dev & prod` 不同环境的代码 26 | 27 | ``` 28 | yarn run build 29 | serve -s dist 30 | ``` 31 | 32 | 这里我使用了 `Vue CLI` 官方文档中提到的部署方式: [serve](https://cli.vuejs.org/zh/guide/deployment.html#%E9%80%9A%E7%94%A8%E6%8C%87%E5%8D%97) 33 | 34 | ``` 35 | npm install -g serve 36 | # -s 参数的意思是将其架设在 Single-Page Application 模式下 37 | # 这个模式会处理即将提到的路由问题 38 | serve -s dist 39 | ``` 40 | 41 | ## Deployment 42 | 43 | ### Docker 44 | 45 | 该项目提供了 `docker.sh` 脚本来进行容器部署的全生命周期管理,包装了如 `build`, `run`, `stop` `rm`, `logs` 命令。 46 | 47 | ```bash 48 | $ ./docker.sh help 49 | 50 | Build, up, down, check logs for SafeU front-end development docker container. 51 | 52 | Usage: 53 | ./docker.sh [COMMAND] 54 | ./docker.sh -h|--help 55 | 56 | Commands: 57 | build Build SafeU front-end container image. 58 | help Show this help message. 59 | logs View output from front-end container. 60 | rm Remove SafeU front-end container. 61 | run Run SafeU front-end container. 62 | stop Stop SafeU front-end container. 63 | ``` 64 | 65 | > 使用时请进入 `scripts/` 目录! 66 | 67 | ## Events 数据埋点 68 | 69 | [READ MORE](./docs/events.md) -------------------------------------------------------------------------------- /src/Global.vue: -------------------------------------------------------------------------------- 1 | 51 | -------------------------------------------------------------------------------- /scripts/docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Author: TripleZ 3 | # Date: 2019-03-11 4 | 5 | echo -e "\n Build, up, down, check logs for SafeU front-end development docker container.\n" 6 | 7 | if [ "$1" == "build" ] 8 | then 9 | sudo docker build --force-rm -t safeu-frontend:latest -f ../Dockerfile .. 10 | 11 | elif [ "$1" == "run" ] 12 | then 13 | sudo docker run -d -e TZ=Asia/Shanghai -p 8000:8080 --name safeu-frontend safeu-frontend 14 | echo -e " Your SafeU front-end container running on backgroud, 15 | served on http://127.0.0.1:8000\n" 16 | 17 | elif [ "$1" == "stop" ] 18 | then 19 | sudo docker stop safeu-frontend 20 | 21 | elif [ "$1" == "logs" ] 22 | then 23 | echo -e " Follow log output? (y/n, default: n): \c" 24 | read isF 25 | echo "" 26 | if [ "$isF" == "y" ] || [ "$isF" == "Y" ] 27 | then 28 | sudo docker logs -f safeu-frontend 29 | else 30 | sudo docker logs safeu-frontend 31 | fi 32 | 33 | elif [ "$1" == "rm" ] 34 | then 35 | sudo docker rm safeu-frontend 36 | 37 | elif [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$1" == "--help" ] 38 | then 39 | echo -e " Usage: 40 | ./docker.sh [COMMAND] 41 | ./docker.sh -h|--help 42 | 43 | Commands: 44 | build Build SafeU front-end container image. 45 | help Show this help message. 46 | logs View output from front-end container. 47 | rm Remove SafeU front-end container. 48 | run Run SafeU front-end container. 49 | stop Stop SafeU front-end container. 50 | " 51 | 52 | else 53 | echo -e " Cannot match the command \"$1\", please type \"help\" command for help.\n" 54 | fi 55 | -------------------------------------------------------------------------------- /src/HomeView.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 35 | 78 | -------------------------------------------------------------------------------- /src/About.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 34 | 35 | 68 | -------------------------------------------------------------------------------- /public/index.prod.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | SafeU | 云U盘 9 | 10 | 11 | 12 | 13 | 17 | 26 | 39 | 43 | 44 | 45 | 51 |
52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "safeu-frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build --mode production", 8 | "build:stage": "vue-cli-service build --mode staging", 9 | "build:dev": "vue-cli-service build --mode dev", 10 | "build:local": "vue-cli-service build --mode local", 11 | "lint": "vue-cli-service lint" 12 | }, 13 | "dependencies": { 14 | "@fortawesome/fontawesome-svg-core": "^1.2.14", 15 | "@fortawesome/free-solid-svg-icons": "^5.7.1", 16 | "@fortawesome/vue-fontawesome": "^0.1.5", 17 | "@sentry/browser": "^5.0.7", 18 | "@sentry/integrations": "^5.0.7", 19 | "ant-design-vue": "^1.3.4", 20 | "axios": "^0.18.0", 21 | "babel-polyfill": "^6.26.0", 22 | "css-loader": "^2.1.0", 23 | "file-loader": "^3.0.1", 24 | "js-sha256": "^0.9.0", 25 | "plupload": "^2.3.6", 26 | "style-loader": "^0.23.1", 27 | "vue": "^2.6.10", 28 | "vue-clipboard2": "^0.3.0", 29 | "vue-loader": "^15.6.2", 30 | "vue-qr": "^1.5.2", 31 | "vue-qriously": "^1.1.1", 32 | "vue-router": "^3.0.2", 33 | "vue-style-loader": "^4.1.2", 34 | "vue-template-compiler": "^2.6.10", 35 | "webpack": "^4.29.4", 36 | "webpack-cli": "^3.2.3", 37 | "webpack-merge": "^4.2.1" 38 | }, 39 | "devDependencies": { 40 | "@babel/polyfill": "^7.2.5", 41 | "@vue/cli-plugin-babel": "^3.2.0", 42 | "@vue/cli-plugin-eslint": "^3.2.0", 43 | "@vue/cli-service": "^3.2.0", 44 | "babel-eslint": "^10.0.1", 45 | "eslint": "^5.8.0", 46 | "eslint-plugin-vue": "^5.0.0-0", 47 | "stylus": "^0.54.5", 48 | "stylus-loader": "^3.0.1" 49 | }, 50 | "eslintConfig": { 51 | "root": true, 52 | "env": { 53 | "node": true 54 | }, 55 | "extends": [ 56 | "plugin:vue/essential", 57 | "eslint:recommended" 58 | ], 59 | "rules": {}, 60 | "parserOptions": { 61 | "parser": "babel-eslint" 62 | } 63 | }, 64 | "postcss": { 65 | "plugins": { 66 | "autoprefixer": {} 67 | } 68 | }, 69 | "browserslist": [ 70 | "cover 99.5%", 71 | "not ie <= 8" 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /src/Privacy.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 51 | 52 | 85 | -------------------------------------------------------------------------------- /src/Terms.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 60 | 61 | 90 | -------------------------------------------------------------------------------- /src/components/Download.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 84 | 85 | 88 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 23 | 60 | 108 | -------------------------------------------------------------------------------- /src/assets/css/FilelistView.css: -------------------------------------------------------------------------------- 1 | #filelistview { 2 | width: 100%; 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | } 8 | 9 | @media (max-width: 700px) { 10 | .filelist-container { 11 | width: 90%; 12 | display: flex; 13 | flex-direction: column; 14 | align-items: center; 15 | min-height: 50%; 16 | } 17 | } 18 | 19 | @media (min-width: 700px) { 20 | .filelist-container { 21 | display: flex; 22 | flex-direction: column; 23 | align-items: center; 24 | width: 600px; 25 | min-height: 50%; 26 | } 27 | } 28 | 29 | .filelist-container-title { 30 | font-size: 28px; 31 | font-weight: bold; 32 | } 33 | 34 | .filelist-item { 35 | width: 100%; 36 | margin-top: 4px; 37 | display: flex; 38 | flex-direction: row; 39 | justify-content: start; 40 | align-items: center; 41 | } 42 | 43 | @media (max-width: 700px) { 44 | .download-files-item-left { 45 | display: flex; 46 | flex-direction: row; 47 | justify-content: center; 48 | align-content: center; 49 | width: 10%; 50 | margin-left: 8px; 51 | } 52 | 53 | .download-files-item-left img { 54 | width: 20px; 55 | height: 20px; 56 | } 57 | 58 | .download-files-item-name { 59 | margin-left: 8px; 60 | width: 60%; 61 | } 62 | 63 | .download-files-item-btn { 64 | display: flex; 65 | justify-content: flex-end; 66 | width: 25%; 67 | } 68 | } 69 | 70 | @media (min-width: 700px) { 71 | .download-files-item-left { 72 | display: flex; 73 | flex-direction: row; 74 | justify-content: center; 75 | align-content: center; 76 | width: 10%; 77 | margin-left: 8px; 78 | } 79 | 80 | .download-files-item-left img { 81 | width: 36px; 82 | height: 36px; 83 | } 84 | 85 | .download-files-item-name { 86 | margin-left: 16px; 87 | width: 60%; 88 | } 89 | 90 | .download-files-item-btn { 91 | display: flex; 92 | justify-content: flex-end; 93 | width: 20%; 94 | } 95 | } 96 | 97 | .download-files-btn-download { 98 | padding: 4px 4px; 99 | color: white; 100 | background: #1ab20a; 101 | border-radius: 4px; 102 | border: none; 103 | } 104 | 105 | .download-files-btn-downloading { 106 | padding: 4px 4px; 107 | color: white; 108 | background: gray; 109 | border-radius: 4px; 110 | border: none; 111 | } 112 | 113 | .zip-download-row { 114 | width: 100%; 115 | margin-top: 40px; 116 | display: flex; 117 | flex-direction: row; 118 | justify-content: flex-end; 119 | align-items: center; 120 | } 121 | 122 | .zip-download-btn { 123 | padding: 8px 16px; 124 | border-radius: 4px; 125 | background: #3596ff; 126 | color: white; 127 | font-size: 16px; 128 | border: 0px; 129 | } 130 | 131 | .zip-downloading-btn { 132 | text-align: center; 133 | padding: 8px 16px; 134 | border-radius: 4px; 135 | border: 1px solid #3596ff; 136 | color: #3596ff; 137 | font-size: 16px; 138 | border: 0px; 139 | } 140 | 141 | .download-files-item-name p { 142 | overflow: hidden; 143 | text-overflow: ellipsis; 144 | white-space: nowrap; 145 | } 146 | -------------------------------------------------------------------------------- /src/main.prod.js: -------------------------------------------------------------------------------- 1 | // import Vue from 'vue' 2 | // import { message, Table, Radio, notification, Modal, Icon, Tooltip} from "ant-design-vue"; 3 | // import "ant-design-vue/dist/antd.css"; 4 | import "@babel/polyfill"; 5 | import App from "./App.vue"; 6 | import VueClipboard from "vue-clipboard2"; 7 | import { library, icon } from "@fortawesome/fontawesome-svg-core"; 8 | import { 9 | faCloudUploadAlt, 10 | faCommentDots, 11 | faEye, 12 | faEyeSlash, 13 | faTrash, 14 | faArrowAltCircleDown, 15 | faArrowAltCircleUp, 16 | faMinusCircle, 17 | } from "@fortawesome/free-solid-svg-icons"; 18 | import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; 19 | // import VueRouter from 'vue-router' 20 | import VueQriously from "vue-qriously"; 21 | import axios from "axios"; 22 | import * as Sentry from "@sentry/browser"; 23 | import * as Integrations from "@sentry/integrations"; 24 | import _global from "./Global.vue"; 25 | 26 | Vue.use(VueQriously); 27 | // Vue.use(notification) 28 | // Vue.use(Modal) 29 | // Vue.use(Icon) 30 | // Vue.use(message) 31 | // Vue.use(Radio) 32 | // Vue.use(Table) 33 | // Vue.prototype.$message = message 34 | // Vue.prototype.$notification = notification 35 | Vue.prototype.$axios = axios; 36 | Vue.use(VueClipboard); 37 | Vue.use(VueRouter); 38 | Vue.use(antd); 39 | library.add( 40 | faCloudUploadAlt, 41 | faCommentDots, 42 | faEye, 43 | faEyeSlash, 44 | faTrash, 45 | faArrowAltCircleDown, 46 | faArrowAltCircleUp, 47 | faMinusCircle 48 | ); 49 | Vue.component("font-awesome-icon", FontAwesomeIcon); 50 | Vue.prototype.$event = function (event_name, from) { 51 | from = typeof from !== "undefined" ? from : null; 52 | const xhr = new XMLHttpRequest(); 53 | xhr.withCredentials = true; 54 | xhr.open("POST", _global.behavior_api_url + "event", true); 55 | xhr.setRequestHeader( 56 | "X-CSRF-TOKEN", 57 | sessionStorage.getItem("behavior_csrf_token") 58 | ); 59 | if (from == null) { 60 | xhr.send(JSON.stringify({ name: event_name })); 61 | } else { 62 | xhr.send(JSON.stringify({ name: event_name, src: from })); 63 | } 64 | }; 65 | 66 | Vue.prototype.$error = function (code) { 67 | if (_global.error_code[code] == "") { 68 | Vue.prototype.$message.error("未知错误"); 69 | } else { 70 | Vue.prototype.$message.error(_global.error_code[code]); 71 | } 72 | }; 73 | 74 | // Vue.config.productionTip = false 75 | const DownloadView = () => 76 | import(/* webpackChunkName: "group-foo" */ "./DownloadView.vue"); 77 | const HomeView = () => 78 | import(/* webpackChunkName: "group-foo" */ "./HomeView.vue"); 79 | const UploadView = () => 80 | import(/* webpackChunkName: "group-foo" */ "./UploadView.vue"); 81 | const UploadedRecodeView = () => 82 | import(/* webpackChunkName: "group-foo" */ "./UploadedRecodeView.vue"); 83 | const FilelistView = () => 84 | import(/* webpackChunkName: "group-foo" */ "./FilelistView.vue"); 85 | const Terms = () => import(/* webpackChunkName: "group-foo" */ "./Terms.vue"); 86 | const Privacy = () => 87 | import(/* webpackChunkName: "group-foo" */ "./Privacy.vue"); 88 | const About = () => import(/* webpackChunkName: "group-foo" */ "./About.vue"); 89 | 90 | let router = new VueRouter({ 91 | mode: "history", 92 | routes: [ 93 | { path: "/download", component: DownloadView }, 94 | { path: "/download/:recode", component: DownloadView }, 95 | { path: "/filelist", component: FilelistView }, 96 | { path: "/upload", component: UploadView }, 97 | { path: "/", component: HomeView }, 98 | { path: "/recode", component: UploadedRecodeView }, 99 | { path: "/terms", component: Terms }, 100 | { path: "/privacy", component: Privacy }, 101 | { path: "/about", component: About }, 102 | ], 103 | }); 104 | 105 | new Vue({ 106 | el: "#app", 107 | router: router, 108 | render: (h) => h(App), 109 | }).$mount("#app"); 110 | 111 | Sentry.init({ 112 | dsn: "https://4443b7d10fec41a98326d1012c416c7b@sentry.io/1437455", 113 | integrations: [ 114 | new Integrations.Vue({ 115 | Vue, 116 | attachProps: true, 117 | }), 118 | ], 119 | }); 120 | -------------------------------------------------------------------------------- /src/main.dev.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import { 3 | message, 4 | Table, 5 | Radio, 6 | notification, 7 | Modal, 8 | Icon, 9 | Tooltip, 10 | } from "ant-design-vue"; 11 | import "ant-design-vue/dist/antd.css"; 12 | import App from "./App.vue"; 13 | import VueClipboard from "vue-clipboard2"; 14 | import { library, icon } from "@fortawesome/fontawesome-svg-core"; 15 | import { 16 | faCloudUploadAlt, 17 | faCommentDots, 18 | faEye, 19 | faEyeSlash, 20 | faTrash, 21 | faArrowAltCircleDown, 22 | faArrowAltCircleUp, 23 | faMinusCircle, 24 | } from "@fortawesome/free-solid-svg-icons"; 25 | import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; 26 | import VueRouter from "vue-router"; 27 | import VueQriously from "vue-qriously"; 28 | import axios from "axios"; 29 | import * as Sentry from "@sentry/browser"; 30 | import * as Integrations from "@sentry/integrations"; 31 | import _global from "./Global.vue"; 32 | 33 | Vue.use(VueQriously); 34 | Vue.use(notification); 35 | Vue.use(Modal); 36 | Vue.use(Icon); 37 | Vue.use(message); 38 | Vue.use(Radio); 39 | Vue.use(Table); 40 | Vue.use(Tooltip); 41 | Vue.prototype.$message = message; 42 | Vue.prototype.$notification = notification; 43 | Vue.prototype.$axios = axios; 44 | Vue.use(VueClipboard); 45 | Vue.use(VueRouter); 46 | library.add( 47 | faCloudUploadAlt, 48 | faCommentDots, 49 | faEye, 50 | faEyeSlash, 51 | faTrash, 52 | faArrowAltCircleDown, 53 | faArrowAltCircleUp, 54 | faMinusCircle 55 | ); 56 | Vue.component("font-awesome-icon", FontAwesomeIcon); 57 | Vue.prototype.$event = function (event_name, from) { 58 | from = typeof from !== "undefined" ? from : null; 59 | const xhr = new XMLHttpRequest(); 60 | xhr.withCredentials = true; 61 | xhr.open("POST", _global.behavior_api_url + "event", true); 62 | xhr.setRequestHeader( 63 | "X-CSRF-TOKEN", 64 | sessionStorage.getItem("behavior_csrf_token") 65 | ); 66 | if (from == null) { 67 | xhr.send(JSON.stringify({ name: event_name })); 68 | } else { 69 | xhr.send(JSON.stringify({ name: event_name, src: from })); 70 | } 71 | }; 72 | 73 | Vue.prototype.$error = function (code) { 74 | if (_global.error_code[code] == "") { 75 | Vue.prototype.$message.error("未知错误"); 76 | } else { 77 | Vue.prototype.$message.error(_global.error_code[code]); 78 | } 79 | }; 80 | 81 | // Vue.config.productionTip = false 82 | const DownloadView = () => 83 | import(/* webpackChunkName: "group-foo" */ "./DownloadView.vue"); 84 | const HomeView = () => 85 | import(/* webpackChunkName: "group-foo" */ "./HomeView.vue"); 86 | const UploadView = () => 87 | import(/* webpackChunkName: "group-foo" */ "./UploadView.vue"); 88 | const UploadedRecodeView = () => 89 | import(/* webpackChunkName: "group-foo" */ "./UploadedRecodeView.vue"); 90 | const FilelistView = () => 91 | import(/* webpackChunkName: "group-foo" */ "./FilelistView.vue"); 92 | const Terms = () => import(/* webpackChunkName: "group-foo" */ "./Terms.vue"); 93 | const Privacy = () => 94 | import(/* webpackChunkName: "group-foo" */ "./Privacy.vue"); 95 | const About = () => import(/* webpackChunkName: "group-foo" */ "./About.vue"); 96 | 97 | let router = new VueRouter({ 98 | mode: "history", 99 | routes: [ 100 | { path: "/download", component: DownloadView }, 101 | { path: "/download/:recode", component: DownloadView }, 102 | { path: "/filelist", component: FilelistView }, 103 | { path: "/upload", component: UploadView }, 104 | { path: "/", component: HomeView }, 105 | { path: "/recode", component: UploadedRecodeView }, 106 | { path: "/terms", component: Terms }, 107 | { path: "/privacy", component: Privacy }, 108 | { path: "/about", component: About }, 109 | ], 110 | }); 111 | 112 | new Vue({ 113 | el: "#app", 114 | router: router, 115 | render: (h) => h(App), 116 | }).$mount("#app"); 117 | 118 | Sentry.init({ 119 | dsn: "https://4443b7d10fec41a98326d1012c416c7b@sentry.io/1437455", 120 | integrations: [ 121 | new Integrations.Vue({ 122 | Vue, 123 | attachProps: true, 124 | }), 125 | ], 126 | }); 127 | -------------------------------------------------------------------------------- /src/components/Home.css: -------------------------------------------------------------------------------- 1 | @media (max-width: 700px) { 2 | .home-container { 3 | width: 90%; 4 | height: 100%; 5 | display: flex; 6 | flex-direction: column; 7 | align-items: center; 8 | justify-content: center; 9 | } 10 | 11 | .intro { 12 | display: flex; 13 | width: 100%; 14 | height: 100%; 15 | flex-direction: column; 16 | align-items: flex-start; 17 | } 18 | 19 | .intro-title { 20 | margin-bottom: -8px; 21 | font-size: 35px; 22 | font-weight: bold; 23 | } 24 | 25 | .intro-subtitle { 26 | margin-top: 16px; 27 | margin-bottom: 0; 28 | font-size: 20px; 29 | } 30 | 31 | .buttons-container { 32 | width: 100%; 33 | height: 100%; 34 | display: flex; 35 | flex-direction: column; 36 | justify-content: flex-start; 37 | align-items: center; 38 | margin-top: 12px; 39 | } 40 | 41 | .main-upload-buttons { 42 | font-size: 20px; 43 | width: 100%; 44 | text-align: center; 45 | background: rgb(64, 169, 255); 46 | padding: 10px 40px 10px; 47 | border-radius: 30px; 48 | color: white !important; 49 | font-weight: bold; 50 | text-decoration: none; 51 | display: inline-block; 52 | margin-top: 8px; 53 | } 54 | 55 | .main-download-buttons { 56 | font-size: 20px; 57 | width: 100%; 58 | text-align: center; 59 | color: rgb(64, 169, 255) !important; 60 | padding: 10px 40px 10px; 61 | border-radius: 30px; 62 | background-color: white !important; 63 | border: 1px solid rgb(64, 169, 255); 64 | font-weight: bold; 65 | text-decoration: none; 66 | display: inline-block; 67 | margin-top: 8px; 68 | } 69 | 70 | .name { 71 | display: none; 72 | } 73 | } 74 | 75 | @media (min-width: 700px) { 76 | .home-container { 77 | width: 600px; 78 | height: 300px; 79 | display: flex; 80 | flex-direction: column; 81 | align-items: center; 82 | justify-content: center; 83 | } 84 | 85 | .intro { 86 | display: flex; 87 | width: 100%; 88 | flex-direction: column; 89 | align-items: flex-start; 90 | justify-content: flex-end; 91 | } 92 | 93 | .intro-title { 94 | margin-bottom: -8px; 95 | font-size: 35px; 96 | font-weight: bold; 97 | max-width: 90%; 98 | height: 50%; 99 | } 100 | 101 | .intro-sub { 102 | width: 100%; 103 | height: 50%; 104 | margin-top: 36px; 105 | display: flex; 106 | flex-direction: row; 107 | justify-content: center; 108 | align-items: flex-start; 109 | } 110 | 111 | .intro-subtitle { 112 | width: 50%; 113 | margin-bottom: 0; 114 | font-size: 20px; 115 | max-width: 90%; 116 | } 117 | 118 | .buttons-container { 119 | width: 50%; 120 | height: 100%; 121 | display: flex; 122 | flex-direction: column; 123 | justify-content: flex-start; 124 | align-items: flex-end; 125 | } 126 | 127 | .main-upload-buttons { 128 | font-size: 20px; 129 | width: 70%; 130 | text-align: center; 131 | background: rgb(64, 169, 255); 132 | padding: 10px 40px 10px; 133 | border-radius: 30px; 134 | color: white !important; 135 | font-weight: bold; 136 | text-decoration: none; 137 | display: inline-block; 138 | margin-bottom: 8px; 139 | outline: 2px; 140 | border: 1px solid rgb(64, 169, 255); 141 | } 142 | 143 | .main-download-buttons { 144 | font-size: 20px; 145 | width: 70%; 146 | text-align: center; 147 | color: rgb(64, 169, 255) !important; 148 | padding: 10px 40px 10px; 149 | border-radius: 30px; 150 | background-color: white; 151 | border: 1px solid rgb(64, 169, 255); 152 | font-weight: bold; 153 | text-decoration: none; 154 | display: inline-block; 155 | margin-top: 8px; 156 | outline: 2px; 157 | } 158 | } 159 | 160 | .main-download-buttons:hover { 161 | background-color: rgb(64, 169, 255) !important; 162 | border: none; 163 | color: white !important; 164 | } 165 | .main-upload-buttons:hover { 166 | background-color: white; 167 | border: none; 168 | color: rgb(64, 169, 255) !important; 169 | border: 1px solid rgb(64, 169, 255); 170 | } 171 | -------------------------------------------------------------------------------- /src/components/RecodeDisplay.css: -------------------------------------------------------------------------------- 1 | @media (max-width: 700px) { 2 | .out-container { 3 | width: 90%; 4 | margin-top: 5%; 5 | display: flex; 6 | flex-direction: column; 7 | justify-content: center; 8 | align-items: center; 9 | } 10 | .vertical-divider { 11 | border-left: 1px solid rgb(193, 193, 193); 12 | height: 0px; 13 | margin-top: 40px; 14 | } 15 | } 16 | 17 | @media (min-width: 700px) { 18 | .out-container { 19 | width: 1000px; 20 | margin-top: 5%; 21 | display: flex; 22 | flex-direction: row; 23 | justify-content: center; 24 | align-items: flex-start; 25 | } 26 | .vertical-divider { 27 | border-left: 1px solid rgb(193, 193, 193); 28 | height: 500px; 29 | } 30 | } 31 | 32 | #custom-settings { 33 | font-size: 20px; 34 | margin: 30px 0px 30px; 35 | text-align: center; 36 | border: 2px solid rgb(64, 169, 255); 37 | border-radius: 10px; 38 | font-weight: bold; 39 | } 40 | 41 | #custom-settings:hover { 42 | font-size: 20px; 43 | background-color: rgb(64, 169, 255); 44 | color: white; 45 | margin: 30px 0px 30px; 46 | text-align: center; 47 | border: 2px solid rgb(64, 169, 255); 48 | border-radius: 10px; 49 | 50 | font-weight: bold; 51 | } 52 | 53 | .container p { 54 | margin-bottom: 0.5em; 55 | } 56 | 57 | .recode-container { 58 | width: 100%; 59 | display: inline-flex; 60 | flex-direction: column; 61 | justify-content: start; 62 | align-items: center; 63 | } 64 | 65 | .recode-container details { 66 | width: 100%; 67 | } 68 | 69 | .recode-container details summary { 70 | outline: none; 71 | text-align: center; 72 | } 73 | 74 | .alert { 75 | width: 160px; 76 | margin-top: 8px; 77 | } 78 | 79 | .recode-top-hint, 80 | .setting-top-hint { 81 | font-size: 32px; 82 | margin-bottom: 0.5em; 83 | font-weight: 800; 84 | } 85 | 86 | .recode-input-row { 87 | display: flex; 88 | flex-direction: row; 89 | justify-content: center; 90 | align-items: center; 91 | } 92 | 93 | .recode-input-row a { 94 | align-self: flex-end; 95 | margin-left: 8px; 96 | font-size: 14px; 97 | color: #3596ff; 98 | } 99 | 100 | .recode-box { 101 | margin-left: 36px; 102 | padding: 4px 20px 4px 20px; 103 | border: 1px solid #cccccc; 104 | border-radius: 12px; 105 | font-size: 28px; 106 | font-family: Monaco, Menlo, Consolas, "Courier New", monospace; 107 | font-weight: 800; 108 | color: #cd365f; 109 | text-align: center; 110 | } 111 | 112 | .more-setting-container { 113 | width: 100%; 114 | display: flex; 115 | margin-top: 20px; 116 | flex-direction: column; 117 | justify-content: start; 118 | align-items: center; 119 | } 120 | 121 | .setting-title { 122 | align-self: flex-start; 123 | margin-left: 10%; 124 | font-size: 20px; 125 | font-weight: 700; 126 | } 127 | 128 | .setting-password-input, 129 | .setting-download-count-input { 130 | width: 80%; 131 | border: 0; 132 | border-bottom: 1px solid #ccc; 133 | outline: none; 134 | font-size: 18px; 135 | } 136 | 137 | .setting-back-btn { 138 | margin-top: 14px; 139 | height: 40px; 140 | width: 80%; 141 | border: 1px solid #3596ff; 142 | border-radius: 8px; 143 | color: #3596ff; 144 | } 145 | 146 | .setting-confirm-btn { 147 | margin-top: 16px; 148 | height: 40px; 149 | width: 80%; 150 | border: 0; 151 | border-radius: 8px; 152 | background: #3596ff; 153 | color: white; 154 | } 155 | 156 | .download-count-row { 157 | display: flex; 158 | flex-direction: row; 159 | justify-content: start; 160 | align-items: center; 161 | align-self: flex-start; 162 | margin-left: 10%; 163 | } 164 | 165 | .download-count-btn { 166 | width: 80px; 167 | height: 40px; 168 | margin-right: 10px; 169 | border: 1px solid #1ab20a; 170 | border-radius: 4px; 171 | } 172 | 173 | .selected { 174 | color: white; 175 | background: #1ab20a; 176 | } 177 | 178 | .download-count-btn-group { 179 | align-self: flex-start; 180 | margin-left: 10%; 181 | } 182 | 183 | .download-count { 184 | margin-right: 8px; 185 | border-radius: 4px !important; 186 | } 187 | 188 | .setting-password-input-row { 189 | display: flex; 190 | width: 80%; 191 | flex-direction: row; 192 | justify-content: start; 193 | align-items: center; 194 | } 195 | 196 | .setting-password-input-row input { 197 | width: 95%; 198 | } 199 | 200 | .setting-password-input-row a { 201 | color: black; 202 | width: 5%; 203 | } 204 | 205 | .expire-time-btn-group { 206 | align-self: flex-start; 207 | margin-left: 10%; 208 | } 209 | 210 | .expire-time { 211 | margin-right: 8px; 212 | border-radius: 4px !important; 213 | } 214 | 215 | .back-btn { 216 | margin-top: 16px; 217 | height: 40px; 218 | line-height: 40px; 219 | width: 80%; 220 | border: 1px solid #3596ff; 221 | border-radius: 8px; 222 | text-align: center; 223 | background: white; 224 | color: #3596ff; 225 | } 226 | 227 | .overlay { 228 | color: gray; 229 | } 230 | 231 | .overlay .ant-tooltip-inner { 232 | background-color: white; 233 | } 234 | 235 | .overlay .ant-tooltip-arrow { 236 | border-bottom-color: white; 237 | } 238 | 239 | .copy-downloadurl-btn { 240 | width: 40%; 241 | border: none; 242 | border-radius: 30px; 243 | background: #3596ff; 244 | color: white; 245 | font-weight: bold; 246 | padding: 10px 40px 10px; 247 | } 248 | -------------------------------------------------------------------------------- /src/components/upload.css: -------------------------------------------------------------------------------- 1 | @media (max-width: 700px) { 2 | .upload-container { 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | width: 90%; 7 | min-height: 400px; 8 | border: 2px dashed grey; 9 | border-radius: 10px; 10 | } 11 | 12 | .upload-files-item { 13 | margin-left: 5%; 14 | display: flex; 15 | flex-direction: row; 16 | justify-content: center; 17 | align-items: center; 18 | width: 90%; 19 | } 20 | } 21 | 22 | @media (min-width: 700px) { 23 | .upload-container { 24 | display: flex; 25 | flex-direction: column; 26 | align-items: center; 27 | width: 600px; 28 | min-height: 400px; 29 | border: 2px dashed grey; 30 | border-radius: 10px; 31 | } 32 | 33 | .upload-files-item { 34 | margin-left: 3%; 35 | display: flex; 36 | flex-direction: row; 37 | justify-content: center; 38 | align-items: center; 39 | width: 45%; 40 | } 41 | } 42 | 43 | a:hover { 44 | border-color: #40a9ff; 45 | } 46 | 47 | .drag-files-mask { 48 | position: absolute; 49 | width: 100%; 50 | height: 100%; 51 | background: rgba(128, 128, 128, 0.3); 52 | display: flex; 53 | flex-direction: row; 54 | justify-content: center; 55 | align-items: center; 56 | font-size: 30px; 57 | } 58 | 59 | .justify-content-center { 60 | justify-content: center; 61 | } 62 | 63 | .justify-content-space-between { 64 | justify-content: space-between; 65 | } 66 | 67 | .upload-nofiles-container { 68 | display: flex; 69 | flex-direction: column; 70 | justify-content: center; 71 | align-items: center; 72 | width: 100%; 73 | height: 100%; 74 | } 75 | 76 | .upload-files-container { 77 | display: flex; 78 | flex-direction: column; 79 | justify-content: space-between; 80 | align-items: center; 81 | width: 100%; 82 | height: 100%; 83 | } 84 | 85 | .upload-files { 86 | margin-top: 8px; 87 | display: flex; 88 | flex-direction: row; 89 | flex-wrap: wrap; 90 | justify-content: start; 91 | align-items: flex-start; 92 | width: 100%; 93 | /* height: 100%; */ 94 | } 95 | 96 | .browse-more-button-container { 97 | width: 100%; 98 | display: flex; 99 | flex-direction: row; 100 | justify-content: center; 101 | align-items: center; 102 | position: relative; 103 | bottom: 0; 104 | } 105 | 106 | .upload-files-item-left { 107 | width: 20%; 108 | } 109 | 110 | .upload-files-item-right { 111 | flex: 1; 112 | width: 70%; 113 | display: flex; 114 | flex-direction: column; 115 | justify-content: center; 116 | align-items: flex-start; 117 | overflow: hidden; 118 | } 119 | 120 | .upload-files-item-progress { 121 | width: 98%; 122 | margin-left: 1%; 123 | margin-right: 1%; 124 | overflow: hidden; 125 | background-color: #f5f5f5; 126 | border-radius: 4px; 127 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 128 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 129 | display: flex; 130 | position: relative; 131 | } 132 | 133 | .progress-bar { 134 | background-color: rgb(84, 185, 249); 135 | background-image: linear-gradient( 136 | 45deg, 137 | rgba(255, 255, 255, 0.14902) 25%, 138 | transparent 25%, 139 | transparent 50%, 140 | rgba(255, 255, 255, 0.14902) 50%, 141 | rgba(255, 255, 255, 0.14902) 75%, 142 | transparent 75%, 143 | transparent 144 | ); 145 | background-size: 20px 20px; 146 | box-shadow: rgba(0, 0, 0, 0.14902) 0 -1px 0 0 inset; 147 | box-sizing: border-box; 148 | color: rgb(255, 255, 255); 149 | justify-content: center; 150 | align-content: center; 151 | align-items: center; 152 | align-self: center; 153 | float: none; 154 | font-size: 12px; 155 | height: 15px; 156 | text-align: center; 157 | transition-delay: 0s; 158 | transition-duration: 0.6s; 159 | transition-property: width; 160 | transition-timing-function: ease; 161 | position: relative; 162 | width: 100%; 163 | } 164 | 165 | .upload-files-item-progress span { 166 | display: inline-block; 167 | width: 100%; 168 | text-align: center; 169 | position: absolute; 170 | left: 0; 171 | bottom: 0; 172 | color: #fafafa; 173 | text-shadow: #000 1px 1px 1px; 174 | } 175 | 176 | .upload-files-item-right p { 177 | overflow: hidden; 178 | text-overflow: ellipsis; 179 | white-space: nowrap; 180 | } 181 | 182 | .upload-tip { 183 | margin-bottom: 0; 184 | margin-top: 1em; 185 | color: grey; 186 | } 187 | 188 | .browse-button { 189 | border: 1px solid #3596ff; 190 | color: #3596ff; 191 | font-weight: bold; 192 | border-radius: 6px; 193 | padding: 6px 12px 6px 12px; 194 | margin-top: 1em; 195 | } 196 | 197 | .start-upload-button { 198 | border: 1px solid #3596ff; 199 | background: white; 200 | color: #3596ff; 201 | font-weight: bold; 202 | border-radius: 6px; 203 | padding: 6px 12px 6px 12px; 204 | margin: 1em 0 1em 1em; 205 | } 206 | 207 | .start-upload-button:hover { 208 | border: 1px solid #3596ff; 209 | background: #3596ff; 210 | color: white; 211 | font-weight: bold; 212 | border-radius: 6px; 213 | padding: 6px 12px 6px 12px; 214 | margin: 1em 0 1em 1em; 215 | } 216 | 217 | .browse-button:hover { 218 | border: 1px solid #3596ff; 219 | background: #3596ff; 220 | color: white; 221 | font-weight: bold; 222 | border-radius: 6px; 223 | padding: 6px 12px 6px 12px; 224 | margin-top: 1em; 225 | } 226 | 227 | .upload-files-remove-btn { 228 | width: 10%; 229 | } 230 | 231 | .upload-files-remove-btn img { 232 | width: 90%; 233 | } 234 | -------------------------------------------------------------------------------- /src/components/UploadedFiles.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 204 | 205 | 208 | -------------------------------------------------------------------------------- /src/assets/background.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Artboard 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | .XLS 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | .DOC 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | .PPT 41 | 42 | 43 | 44 | 45 | 46 | 47 | .XLS 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | .PDF 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | .DOC 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | .PDF 81 | 82 | 83 | 84 | 85 | 86 | 87 | .PPT 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /src/FilelistView.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 273 | 274 | 277 | -------------------------------------------------------------------------------- /src/components/RecodeDisplay.vue: -------------------------------------------------------------------------------- 1 | 123 | 124 | 429 | 430 | 433 | -------------------------------------------------------------------------------- /src/components/upload.vue: -------------------------------------------------------------------------------- 1 | 79 | 80 | 445 | 448 | --------------------------------------------------------------------------------