├── 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 |
2 |
3 |
Woops, 此链接已过期或者从未生效。
4 |
5 |
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 |
2 |
--------------------------------------------------------------------------------
/src/UploadView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
2 |
3 |
4 |
5 |
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 |
2 |
3 |
7 |
8 |
9 |
10 |
32 |
45 |
--------------------------------------------------------------------------------
/src/components/Navbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
SafeU
5 |
15 | beta
16 |
17 |
18 |
云U盘
19 |
quick & safe for share.
20 |
21 |
22 |
27 |
28 |
29 |
30 |
45 |
46 |
49 |
--------------------------------------------------------------------------------
/src/components/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
SafeU
5 |
隐私、安全、易用
6 |
的文件分享服务
7 |
8 |
9 |
10 | 使用 SafeU
11 | 存储、分享文件,设定下载次数、自毁时间,既安全又高效,可取代绝大多数U盘应用场景。
12 |
13 |
21 |
22 |
23 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
35 |
78 |
--------------------------------------------------------------------------------
/src/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
关于 SafeU 云U盘
5 |
简介
6 |
7 | 这里是 SafeU 云U盘,一款好用、快捷、安全的文件分享服务。
8 | 我们为文件的便捷、安全传输而来。
9 | 虽然还处于起步阶段,但是我们仍然提供了非常安全及高效的文件传输服务,简单来说:我们可以完胜并取代
10 | 90% 的 U 盘应用场景。我们使用国际标准的 TLS
11 | 技术,使您的文件在传输时经过严格加密。在下载时,只有知道文件提取码及其密钥(如果您设置了密钥)的人才能获取此文件。同时,您可以设置文件过期时间以及最大下载次数以保证文件的安全性。更多的是,您的一切活动都是匿名的,完全不必担心隐私问题。
12 |
13 |
开发组成员
14 |
20 |
本项目已在 GitHub 上开源,并提供了私有化部署的模式,欢迎 Star.
21 |
25 |
26 |
27 |
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 |
2 |
3 |
4 |
SafeU 云U盘的隐私权政策
5 |
6 | 您使用 SafeU
7 | 云U盘,即表示您信赖我们对您信息的处理方式。我们深知这项责任事关重大,因此我们将矢志不渝地保护您的信息,并让您拥有控制权。
8 |
9 |
收集的信息及其处理方式
10 |
11 | -
12 | 您的浏览器标识、设备标识信息。我们会收集您访问 SafeU
13 | 服务时使用的应用、浏览器和设备的相关信息,以便提供对特定设备的产品优化。这些信息同样会提供给我们的开发者以确定产品的优化方向。
14 |
15 | -
16 | 您上传文件的文件名、文件类型、文件大小等文件信息。我们提供文件上传、暂存与下载服务,我们对您的文件的存储、压缩等处理方式依赖于您的文件信息。我们不会查看您的文件内容,除非满足下述《信息分享条款》中的条件
17 |
18 | -
19 | 您在使用本产品时的行为特征。主要包括使用时间段、页面停留时间、产品使用偏好。这些信息将会帮助我们对产品进行有针对性的优化。
20 |
21 | - 您的所有隐私信息将会以匿名方式上传。
22 |
23 |
信息分享条款
24 |
25 | 我们不会与任何第三方政府、组织、企业或个人分享您的任何信息,除非以下情况:
26 |
27 |
28 | - 征得您的同意。
29 | -
30 | 出于法律原因。如果我们有充分理由相信,出于以下目的有必要访问、使用、保留或披露您的信息,我们将会与第三方分享您的个人信息:
31 |
32 | - 实施适用的服务条款,包括调查可能存在的违规情况。
33 | - 满足任何适用法律、法规、法律程序的要求或强制性的政府要求。
34 | - 检测、防范或解决欺诈、安全或技术问题。
35 | -
36 | 在法律要求或允许的范围内,保护 A2OS
37 | 团队、我们的用户或公众的权利、财产或安全免遭损害。
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
51 |
52 |
85 |
--------------------------------------------------------------------------------
/src/Terms.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
SafeU 云U盘的使用条款
5 |
6 | 欢迎使用 SafeU 云U盘,本项目由南京航空航天大学 A2OS
7 | 团队开发并供南航内部乃至全体人类使用,旨在给大家提供更加便捷的文件传输服务,推广云存储、淘汰旧时代的U盘等媒介,并将文件隐私泄露、靠U盘传播的病毒扼杀在摇篮之中。
8 |
9 |
我们提供的服务
10 |
11 | 我们为大家提供免费且便捷的文件上传、暂存、下载服务。要使用我们的任意服务,您必须连接互联网,并在我们的网站内完成操作。
12 |
13 |
14 | -
15 | 文件上传服务。您可以通过本产品内的“上传”功能,将您本地的文件上传至本站。单次最多上传
16 | 20 个文件,总大小不超过 50M。
17 |
18 | -
19 | 文件暂存服务。根据您的设定,您上传的文件将在本站暂存 4-24 小时。
20 |
21 | -
22 | 文件下载服务。根据您的个人设定,您可以通过自动生成或个人指定的提取码在本站进行下载,或者通过扫码获取链接完成下载。您可以根据自己的需求选择下载次数。如果您设置了文件加密,则必须输入正确的密码才能下载。
23 |
24 | -
25 | 达到以下条件,您上传的文件将被本站彻底删除。
26 |
27 | - 达到您设定的文件暂存时间。
28 | - 达到您设定的最大下载次数。
29 |
30 |
31 |
32 |
隐私政策
33 |
详见本站首页的“隐私政策”链接。
34 |
免责声明
35 |
36 | -
37 | 我们尽力做到最好,但是不能保证万无一失,如果遇到天灾人祸等不可抗力,您暂存的文件可能在规定时间或下载次数以内,就无法进行下载。故请务必保留您重要文件的备份。
38 |
39 | -
40 | 在内测/公测期间,本产品可能存在或多或少的故障,某些故障可能影响您的使用。遇到问题,请使用本站的反馈功能与我们取得联系。
41 |
42 | -
43 | 一旦达到文件删除条件,您的文件将无法找回。故请务必选择您需要的文件留存时间、文件下载次数,并留意是否达到条件。
44 |
45 | -
46 | 鉴于网络服务的特殊性,用户同意 SafeU
47 | 服务有权随时变更、中断或终止部分或全部的网络服务。如变更、中断或终止的网络服务,SafeU
48 | 将在24小时前在网站首页公示。
49 |
50 |
51 |
52 |
53 |
54 |
55 |
60 |
61 |
90 |
--------------------------------------------------------------------------------
/src/components/Download.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
输入提取码
4 |
9 |
17 |
18 |
19 |
20 |
21 |
84 |
85 |
88 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
22 |
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 |
2 |
3 |
历史上传文件
4 |
10 |
11 | {{
12 | recode.recode
13 | }}
14 | {{ recode.recode }}
15 |
16 |
17 | 提取
20 | 提取
21 |
22 |
23 | {{ remain_time }}
24 | 已过期
25 |
26 |
27 |
30 |
33 |
34 |
35 |
41 | 您确定要删除该文件嘛,这不仅会删除历史记录,也将无法提取该文件
42 |
43 |
44 |
45 |
46 |
204 |
205 |
208 |
--------------------------------------------------------------------------------
/src/assets/background.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/FilelistView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
文件列表
5 |
6 |
7 | 全选
8 |
9 |
10 |
11 |
12 |
![]()
13 |
14 |
15 |
{{item.original_name}}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
273 |
274 |
277 |
--------------------------------------------------------------------------------
/src/components/RecodeDisplay.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
您的提取码
5 |
26 |
30 | 点击提取码一键复制
31 |
32 |
33 |
41 |
47 | 分享二维码
48 |
49 |
55 |
56 | 保存分享二维码
57 |
58 |
59 |
60 |
61 |
62 |
63 |
自定义设置
64 |
65 |
66 | 加密
71 |
72 |
83 |
下载次数
84 |
85 |
86 | 1 次
89 | 10 次
92 | 20 次
95 | 50 次
98 |
99 |
100 |
有效期
101 |
102 |
103 | 4 小时
106 | 8 小时
109 | 12 小时
112 | 24 小时
115 |
116 |
117 |
118 |
返回
119 |
120 |
121 |
122 |
123 |
124 |
429 |
430 |
433 |
--------------------------------------------------------------------------------
/src/components/upload.vue:
--------------------------------------------------------------------------------
1 |
2 |
78 |
79 |
80 |
445 |
448 |
--------------------------------------------------------------------------------