1. 程式人生 > >vue+nodejs+express+mysql 建立一個在線網盤程序

vue+nodejs+express+mysql 建立一個在線網盤程序

網盤 cnpm rst lec inpu lsi turn pat 建立

vue+nodejs+express+mysql 建立一個在線網盤程序

目錄

  • vue+nodejs+express+mysql 建立一個在線網盤程序
    • 第一章 開發環境準備
      • 1.1 開發所用工具簡介
      • 1.2 安裝 MySQL
        • 1.2.1 下載安裝 MySQL
        • 1.2.2 可能出現的問題和解決方案
      • 1.3 安裝 vue-cli
      • 1.4 安裝 express
    • 第二章 數據庫設計和創建
      • 2.1 數據庫和表設計
      • 2.2 user 表
      • 2.3 file 表
      • 2.4 創建數據庫和表所用 sql 語句參考
    • 第三章 後臺模塊開發
      • 3.1 創建數據庫連接
      • 3.2 創建表模型
      • 3.3 編寫接口
        • 3.3.1 定義接口
        • 3.3.2 編寫控制器文件
      • 3.4 接口測試
    • 第四章 前端模塊開發
      • 4.1 安裝並引入前端開發所需外部模塊
      • 4.2 建立路由
      • 4.3 編寫組件

代碼戳這裏--> code

第一章 開發環境準備

1.1 開發所用工具簡介

主要開發所用工具:

  • MySQL、Express、NodeJS、Vue
  • 其他工具: element-ui、axios

1.2 安裝 MySQL

1.2.1 下載安裝 MySQL

參照: MySQL 安裝 | 菜鳥教程

1.2.2 可能出現的問題和解決方案

1.提示:Found option without preceding group in config file:XXX; Fatal error in defaults handling.

解決方法:用電腦的記事本打開my.ini文件,將其另存為 ANSI 編碼格式並替換原來的my.ini文件

2.提示:you must reset your password using ALTER USER statement before executing this statement.
解決方法:重新設置密碼
在 mysql 環境下,輸入alter user user() identified by "123456";退出 sql 重新登錄即可。

1.3 安裝 vue-cli

  1. 新建一個文件夾cloud-drive,在該文件下中使用 webpack 生成一個 vue 項目

參考代碼如下:

mkdir cloud-drive
cd cloud-drive

cnpm install vue-cli -g
vue init webpack "client" //建立一個名稱為client的前端項目
cnpm install // 安裝依賴
npm run dev
  1. 在執行npm run dev後,在瀏覽器中輸入http://localhost:8080/#後顯示以下界面,則 client 項目生成完畢!
    技術分享圖片

1.4 安裝 express

1.在cloud-drive下建立一個文件夾,名稱為 server,用於存放服務端的代碼。

mkdir server
cd server
  1. server文件夾下利用npm init -f生成一個package.json文件.
  2. package.json文件添加啟動項目代碼
...
"scripts": {
    "start": "node src/app.js", // 加入這一條用於啟動程序
    "test": "echo \"Error: no test specified\" && exit 1"
  },

...

4.在server文件夾下創建src文件夾,在src文件夾下創建app.js文件,在app.js寫入以下信息用於測試

console.log('Hello World!');
  1. 執行npm start命令,輸出信息如以下代表成功
Hello World!
  1. 安裝 express 框架
npm install express --save
  1. 安裝其他的依賴
npm install body-parser cors morgan nodemon multer md5 --save
  • body-parser 解析
  • cors 跨域
  • morgan 日誌記錄
  • nodemon 程序調試自啟
  • multer 文件上傳中間件
  • md5 生成 md5 碼模塊 8.將src/app.js用以下內容替代,該內容創建了一個運行於 8081 接口的服務器,建立了一個測試用接口,名稱為 posts
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const morgan = require('morgan')

const app = express()
app.use(morgan('combined'))
app.use(bodyParser.json())
app.use(cors())

app.get('/posts', (req, res) => {
  res.send(
    [{
      title: "Hello World!",
      description: "Hi there! How are you?"
    }]
  )
})

app.listen(process.env.PORT || 8081)

9.修改package.json文件,采用 nodemon 啟動

"scripts": {
    "start": "nodemon src/app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

10.使用npm start啟動應用,在瀏覽器中訪問localhost:8081/posts地址,如若成功,應該看到以下信息
技術分享圖片
至此,後端環境準備完畢

第二章 數據庫設計和創建

2.1 數據庫和表設計

  • 數據庫名稱:cloud_drive
  • 數據庫表: user 表和 file 表

2.2 user 表

user 表:管理網盤註冊用戶信息

字段 中文釋義 類型 是否為空 默認值 其他
uid 用戶 id int(10) unsigned NO 主鍵 null auto_increment
username 用戶名 varchar(20) NO null
password 密碼 varchar(20) NO null

2.3 file 表

file 表:管理用戶上傳文件信息

字段 中文釋義 類型 是否為空 默認值 其他
id 文件 id int(10) unsigned NO 主鍵 auto_increment
file_name 文件名稱 varchar(255) NO null
hash_name 使用 hash 算法生成的文件名稱 varchar(255) NO null
upload_time 上傳時間 varchar(255) No null
type 文件類型 varchar(255) No null
size 文件大小 varchar(255) No null
download 下載次數 varchar(255) No null
uid 上傳用戶 id int(10) unsigned No 外鍵 null

2.4 創建數據庫和表所用 sql 語句參考

  1. 創建數據庫cloud_drive和表user語句
DROP DATABASE IF EXISTS cloud_drive;
CREATE DATABASE cloud_drive;
use cloud_drive;
DROP TABLE IF EXISTS user;
CREATE TABLE IF NOT EXISTS `user`(
   `uid` INT UNSIGNED AUTO_INCREMENT COMMENT '用戶id',
   `username` VARCHAR(20) NOT NULL COMMENT '用戶名',
   `password` VARCHAR(20) NOT NULL COMMENT '密碼',
   PRIMARY KEY ( `uid` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '用戶表';
  1. 創建用戶上傳文件表
use cloud_drive;
DROP TABLE IF EXISTS file;
CREATE TABLE `file`
(
    id int(10) AUTO_INCREMENT COMMENT '文件id',
    file_name varchar(200) NOT NULL COMMENT '文件名稱',
    hash_name varchar(200) NOT NULL COMMENT '文件hash名稱',
    upload_time DateTime NOT NULL COMMENT '上傳時間',
    type varchar(20) NOT NULL COMMENT '文件類型',
    size varchar(20) NOT NULL COMMENT '文件大小',
    download varchar(50) NOT NULL COMMENT '下載次數',
    uid int unsigned COMMENT '用戶id',
    PRIMARY KEY (id),
    foreign key(uid) references user(uid)
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '上傳文件表';

第三章 後臺模塊開發

3.1 創建數據庫連接

  1. 創建/server/config/env.js文件
//  數據庫連接參數
const env = {
  database: 'cloud_drive',
  username: 'root',
  password: '123456',
  host: 'localhost',
  dialect: 'mysql',
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  }
};
module.exports = env;
  1. 創建/server/config/db.config.js文件
const env = require('./env.js');

const Sequelize = require('sequelize');
const sequelize = new Sequelize(env.database, env.username, env.password, {
  host: env.host,
  dialect: env.dialect,
  operatorsAliases: false,

  pool: {
    max: env.max,
    min: env.pool.min,
    acquire: env.pool.acquire,
    idle: env.pool.idle
  }
});

const db = {};

db.Sequelize = Sequelize;
db.sequelize = sequelize;

// 引入表模型
db.user = require('../model/user.model')(sequelize, Sequelize);
db.file = require('../model/file.model')(sequelize, Sequelize);

module.exports = db;

3.2 創建表模型

  1. 安裝sequelize-auto模塊,利用sequelize-auto模塊自動生成 user 表模型和 file 表模型
npm install -g sequelize-auto
sequelize-auto -h localhost -d cloud_drive -u root -x 123456 -p 3306 -t user
sequelize-auto -h localhost -d cloud_drive -u root -x 123456 -p 3306 -t file

註意:此處生成的表模型需要根據實際進行調整

2.復制生成的/models/book.js文件,粘貼至/model目錄下,並修改文件名後綴為.model.js,刪除生成的models目錄

3.3 編寫接口

3.3.1 定義接口

  1. /server/route/user.route.js文件
//  用戶
module.exports = function(app) {
  const user = require('../controller/user.controller');

  //  新增用戶
  app.post('/user/add', user.create);

  //  根據用戶名和密碼查詢用戶
  app.post('/user/validate', user.validate);

  //  修改密碼
  app.put('/user/update/:userId', user.updatePassWord);
};

  1. /server/route/file.route.js文件
//  文件
module.exports = function(app) {
  const file = require('../controller/file.controller');

  //  新增文件
  app.post('/file/add', file.create);

  //  刪除文件
  app.delete('/file/delete/:fileName/:fileId', file.delete);

  // 下載文件
  app.get('/file/download/:fileName/:fileId', file.download);

  // 獲取文件信息列表
  app.post('/file/list', file.findAll);
};

3.3.2 編寫控制器文件

  1. /server/controller/user.controller.js文件
const db = require('../config/db.config.js');
const User = db.user; //  引入表模型
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
//  新增用戶
exports.create = (req, res) => {
  if (req.body.username && req.body.password) {
    User.create(req.body)
      .then(user => {
        let msg = {};
        if (user) {
          msg = {
            flag: 1,
            msg: '註冊成功!',
            uid: user.uid,
            username: user.username
          };
        } else {
          msg = {
            flag: 0,
            msg: '註冊失敗,請稍後註冊'
          };
        }
        res.status(200).json(msg);
      })
      .catch(err => {
        res.status(500).json('Error -> ' + err);
      });
  } else {
    let msg = {
      flag: 0,
      msg: '用戶名或者密碼不能為空!'
    };
    res.status(200).json(msg);
  }
};

//  驗證用戶名和密碼
exports.validate = (req, res) => {
  if (req.body.username && req.body.password) {
    User.findOne({
      where: {
        [Op.and]: [
          {
            username: req.body.username
          },
          [
            {
              password: req.body.password
            }
          ]
        ]
      },
      attributes: ['uid', 'username']
    })
      .then(user => {
        let msg = {};
        if (user) {
          msg = {
            flag: 1,
            msg: '用戶名和密碼正確!',
            uid: user.uid,
            username: user.username
          };
        } else {
          msg = {
            flag: 0,
            msg: '用戶名或密碼錯誤!'
          };
        }

        res.status(200).json(msg);
      })
      .catch(err => {
        res.status(500).json('Error -> ' + err);
      });
  } else {
    let msg = {
      flag: 0,
      msg: '用戶名或者密碼不能為空!'
    };
    res.status(200).json(msg);
  }
};

//  修改密碼
exports.updatePassWord = (req, res) => {
  User.findOne({
    where: {
      [Op.and]: [
        {
          uid: req.params.userId
        },
        {
          password: req.body.oldPassword
        }
      ]
    }
  }).then(user => {
    if (user) {
      User.update(
        {
          password: req.body.newPassword
        },
        {
          where: {
            uid: req.params.uid
          }
        }
      ).then(() => {
        let msg = {
          flag: 1,
          msg: '修改密碼成功!'
        };
        res.status(200).json(msg);
      });
    } else {
      let msg = {
        flag: 0,
        msg: '密碼不正確!'
      };
      res.status(200).json(msg);
    }
  });
};

  1. /server/controller/file.controller.js文件
const db = require('../config/db.config.js');
const File = db.file; //  引入表模型
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
const path = require('path');
const fs = require('fs');

//  添加文件
exports.create = (req, res) => {
  let params = {
    file_name: req.files[0].originalname,
    hash_name: req.files[0].filename,
    upload_time: new Date().toLocaleDateString() + ' ' + new Date().toLocaleTimeString(),
    type: path.parse(req.files[0].originalname).ext,
    size: req.files[0].size,
    download: 0,
    uid: req.body.uid
  };
  File.create(params)
    .then(file => {
      if (file) {
        let msg = {
          flag: 1,
          msg: '文件上傳成功!'
        };
        res.status(200).json(msg);
      } else {
        let msg = {
          flag: 0,
          msg: '文件上傳失敗,請稍後重新上傳!'
        };
        res.status(500).json(msg);
      }
    })
    .catch(err => {
      res.status(500).json('Error->' + err);
    });
};

//  刪除文件
exports.delete = (req, res) => {
  const id = req.params.fileId;
  File.destroy({
    where: { id: id }
  })
    .then(_ => {
      //  從資源文件夾從刪除
      let fileName = req.params.fileName;
      let path = `${__dirname}/../resource/${fileName}`;
      fs.unlink(path, err => {
        if (err) {
          let msg = {
            flag: 0,
            msg: '刪除失敗!'
          };
          res.status(200).json(msg);
        } else {
          let msg = {
            flag: 1,
            msg: '刪除成功!'
          };
          res.status(200).json(msg);
        }
      });
    })
    .catch(err => {
      res.status(500).json('Error=>', err);
    });
};

//  下載文件
exports.download = (req, res) => {
  let fileId = req.params.fileId;
  File.findById(fileId).then(file => {
    file
      .increment('download')
      .then(file => {
        let fileName = req.params.fileName;
        let path = `${__dirname}/../resource/${fileName}`;
        res.download(path, fileName);
      })
      .catch(err => {
        res.status(500).json('Error=>', err);
      });
  });
};

//  獲取文件列表信息
exports.findAll = (req, res) => {
  File.findAll({
    where: { uid: req.body.uid }
  })
    .then(file => {
      res.status(200).json(file);
    })
    .catch(err => {
      res.status(500).json('Error=>', err);
    });
};

3.4 接口測試

使用 postman 進行測試(略)

第四章 前端模塊開發

4.1 安裝並引入前端開發所需外部模塊

  1. 安裝axios模塊
  • npm install axios --save
  • 編寫文件src/utils/http.js,並引入封裝好的 axios 類
import axios from 'axios'

let httpInstance = axios.create()

httpInstance.defaults.baseURL = 'http://localhost:8081/'
httpInstance.defaults.timeout = 5000

httpInstance.formurl = (url, data, config) => {
  return httpInstance.post(url, data, {
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    ...config
  })
};

//  request攔截器
httpInstance.interceptors.request.use(
  config => {
    console.log(config)
    return config
  },
  error => {
    return Promise.reject(error)
  }
)
//  reponse攔截器
httpInstance.interceptors.response.use(
  response => {
    if (response.status === 200) {
      return Promise.resolve(response)
    }
  },
  error => {
    return Promise.reject(error)
  }
)
export default httpInstance
  • main.js中引入http.js文件,並將其註冊為 vue 全局變量
import http from './utils/http'
Vue.prototype.$http = http;
  1. 安裝element-ui模塊
  • npm install element-ui --save
  • main.js中引入element-ui模塊
  import ElementUI from 'element-ui'
  import 'element-ui/lib/theme-chalk/index.css'
  Vue.use(ElementUI)

4.2 建立路由

  1. 建立文件 在components 下新建文件如下,並刪除原有的HelloWorld.vue文件。
  • file-list.vue: 已上傳文件列表界面
  • file-upload.vue:上傳文件界面
  • index.vue:登錄註冊界面
  • tab-list.vue:tab 頁
  • user-set.vue:用戶設置界面
  1. 修改路由 在 router/main.js 中將路由修改如下
import Vue from 'vue'
import Router from 'vue-router'
import index from '@/components/index'
import list from '@/components/tab-list'

Vue.use(Router)

const router = new Router({
  routes: [
    {
      path: '/',
      name: 'index',
      component: index
    },
    {
      path: '/tab-list',
      name: 'tab-list',
      component: list
    }
  ]
})
//  校驗登錄
router.beforeEach((to, from, next) => {
  if (to.name === 'tab-list') {
    if (!sessionStorage.username) {
      window.alert('您的登錄信息無效或過期,請重新登錄')
      return window.location.replace('/')
    } else {
      next()
    }
  } else {
    next()
  }
})
export default router
  1. 刪除App.vue文件中以下代碼
<img src="./assets/logo.png">
  1. index.vue中寫入以下代碼:
<template>
  <div>
    Hello World!
  </div>
</template>
<script>
export default {}
</script>
<style scoped>
</style>
  1. 使用npm start運行項目,在瀏覽器中訪問,則會出現npm start的文字

4.3 編寫組件

1.index.vue登錄註冊界面
(1)界面預覽
技術分享圖片
技術分享圖片
(2)代碼編寫

<template>
  <div class="index">
    <div class="title">
      在線網盤系統
    </div>
    <div class="label">
      Cloud Driver
    </div>
    <div class="btn">
      <el-button type="primary"
        @click="dialogFormVisible = true">登錄/註冊</el-button>
    </div>
    <el-dialog title="登錄/註冊"
      :visible.sync="dialogFormVisible"
      width="400px">
      <el-form :model="form">
        <el-form-item label="用戶名"
          :label-width="formLabelWidth">
          <el-input v-model="form.username"
            autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="密碼"
          :label-width="formLabelWidth">
          <el-input v-model="form.password"
            autocomplete="off"
            type="password"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer"
        class="dialog-footer">
        <el-button @click="signUp">註 冊</el-button>
        <el-button type="primary"
          @click="signIn">登 錄</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: 'index',
  data () {
    return {
      dialogFormVisible: false,
      form: {
        username: '',
        password: ''
      },
      formLabelWidth: '120px'
    }
  },
  methods: {
    // 登錄
    signIn () {
      this.dialogFormVisible = false
      this.$http
        .post('/user/validate', this.form)
        .then(res => {
          if (res.data.flag === 0) {
            this.$message.error(res.data.msg)
          } else {
            this.$message.success(res.data.msg)
            sessionStorage.setItem('uid', res.data.uid)
            sessionStorage.setItem('username', res.data.username)

            //  跳轉到其他頁面
            this.$router.push('tab-list')
          }
        })
        .catch(err => {
          console.log(err)
        })
    },
    //  註冊
    signUp () {
      this.dialogFormVisible = false
      this.$http
        .post('/user/add', this.form)
        .then(res => {
          if (res.data.flag === 0) {
            this.$message.error(res.data.msg)
          } else {
            this.$message.success(res.data.msg)
            this.$router.push('tab-list')
          }
        })
        .catch(err => {
          console.log(err)
        })
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.index {
  margin-top: 80px;
  text-align: center;
}
.title {
  font-size: 60px;
}
.label {
  font-size: 40px;
  margin-top: 10px;
}
.btn {
  margin-top: 10px;
}
.dialog-footer {
  text-align: center;
}
</style>
  1. tab-list.vue選項卡切換界面
    (1)界面預覽
    技術分享圖片
    (2)代碼
<template>
  <div class="show">
    <base-header></base-header>
    <el-tabs v-model="tabActivedName"
      class="tab"
      @tab-click="handleClick">
      <el-tab-pane v-for="(item, index) in componentList"
        :key="index"
        :label="item.tabLabel"
        :name="item.tabName">
        <component :is="item.compoName"
          v-if="tabActivedName===item.tabName"></component>
      </el-tab-pane>
    </el-tabs>
    <base-footer></base-footer>
  </div>
</template>

<script>
import BaseHeader from '../layout/header';
import BaseFooter from '../layout/footer';
import UploadFile from './file-upload';
import FileList from './file-list';
import userSet from './user-set';
export default {
  name: 'show',
  components: {
    BaseHeader,
    BaseFooter,
    UploadFile,
    FileList,
    userSet
  },
  data () {
    return {
      tabActivedName: 'second',
      componentList: [
        {
          tabName: 'first',
          compoName: 'upload-file',
          tabLabel: '上傳文件'
        },
        {
          tabName: 'second',
          compoName: 'file-list',
          tabLabel: '文件列表'
        },
        {
          tabName: 'third',
          compoName: 'user-set',
          tabLabel: '用戶設置'
        }
      ]
    }
  },
  methods: {
    handleClick (tab, event) {
      console.log(tab, event)
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.tab {
  min-height: 400px;
  padding: 20px 40px;
}
</style>

3.file-upload文件上傳組件
(1)界面預覽
技術分享圖片
(2)代碼

<template>
  <el-upload drag
    multiple
    action="http://localhost:8081/file/add"
    :data="userInfo"
    :on-success="dealSuccess"
    :on-error="dealError">
    <i class="el-icon-upload"></i>
    <div class="el-upload__text">將文件拖到此處,或<em>點擊上傳</em></div>
  </el-upload>
</template>
<script>
export default {
  data () {
    return {
      userInfo: {
        uid: sessionStorage.getItem('uid')
      }
    }
  },
  methods: {
    dealSuccess () {
      this.$message.success('上傳文件成功!')
    },
    dealError () {
      this.$message.error('上傳文件失敗,請重新上傳!')
    }
  }
}
</script>
<style scoped>
</style>
  1. file-list.vue文件上傳列表組件
    (1)界面預覽
    技術分享圖片
    (2)代碼
<template>
  <div>
    <el-table :data="tableData"
      :cell-style="{'text-align':'center'}"
      :header-cell-style="{'text-align':'center'}"
      style="width: 100%">
      <el-table-column type="index">
      </el-table-column>
      <el-table-column prop="file_name"
        label="文件名"
        width="180px">
      </el-table-column>
      <el-table-column prop="size"
        label="文件大小"
        width="180px"
        :formatter="dealSize">
      </el-table-column>
      <el-table-column prop="upload_time"
        label="上傳時間"
        width="180px"
        :formatter="dealTime">
      </el-table-column>
      <el-table-column prop="download"
        label="下載次數"
        width="180px">
      </el-table-column>
      <el-table-column prop="type"
        label="類型"
        width="180px">
      </el-table-column>
      <el-table-column label="操作">
        <template slot-scope="scope">
          <a :href="getFile(scope.row)">
            <el-button size="mini"
              type="info"
              @click="handleDownload">下載</el-button>
          </a>
          <el-button size="mini"
            type="danger"
            @click="handleDelete(scope.$index, scope.row)">刪除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data () {
    return {
      tableData: []
    }
  },
  methods: {
    handleDelete (index, row) {
      this.$http
        .delete(`/file/delete/${row.hash_name}/${row.id}`)
        .then(res => {
          this.$message.success(res.data.msg)
          this.refreshFileList()
        })
        .catch(err => {
          console.log('Error=>', err)
        })
    },
    handleDownload () {
      setTimeout(() => {
        this.refreshFileList()
      }, 1000)
    },
    refreshFileList () {
      this.getFileList()
    },
    getFileList () {
      let params = {
        uid: sessionStorage.getItem('uid')
      }
      this.$http
        .post('/file/list', params)
        .then(res => {
          if (res.data.code === 0) {
            this.$message.error(res.data.msg)
          } else {
            this.tableData = res.data
          }
        })
        .catch(err => {
          console.log(err)
        })
    },
    getFile (data) {
      let url = `http://localhost:8081/file/download/${data.hash_name}/${
        data.id
      }`
      return url
    },
    dealSize (row, column) {
      let fileSize = (row.size / 1024).toFixed(2)
      return `${fileSize}kb`
    },
    dealTime (row, column) {
      return this.formatTime(row.upload_time)
    },
    formatTime (value) {
      var date = new Date(value)
      var Y = date.getFullYear()
      var M =
        date.getMonth() + 1 < 10
          ? `0${date.getMonth() + 1}`
          : date.getMonth() + 1
      var D = date.getDate() < 10 ? `0${date.getDate()}` : date.getDate()
      var h = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours()
      var m =
        date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes()
      var s =
        date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds()
      return `${Y}-${M}-${D} ${h}:${m}:${s}`
    }
  },
  mounted () {
    this.getFileList()
  }
}
</script>
  1. user-set.vue用戶設置組件
<template>
  <div>
    <el-form :model="ruleForm"
      status-icon
      :rules="rules"
      ref="ruleForm"
      label-width="100px"
      class="change-password">
      <el-form-item label="原密碼"
        prop="oldPass">
        <el-input type="password"
          v-model="ruleForm.oldPass"
          autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="新密碼"
        prop="newPass">
        <el-input type="password"
          v-model="ruleForm.newPass"
          autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="確認新密碼"
        prop="checkNewPass">
        <el-input type="password"
          v-model="ruleForm.checkNewPass"
          autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary"
          @click="submitForm('ruleForm')">提交</el-button>
        <el-button @click="resetForm('ruleForm')">重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>
<script>
export default {
  data () {
    //  驗證原密碼
    let validateOldPass = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('請輸入密碼'))
      } else {
        if (this.ruleForm.oldPass !== '') {
          this.$refs.ruleForm.validateField('newPass')
        }
        callback()
      }
    }
    //  驗證新密碼
    var validateNewPass = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('請輸入新密碼'))
      } else if (value === this.ruleForm.oldPass) {
        callback(new Error('新舊密碼不能相同!'))
      } else {
        callback()
      }
    }
    //  驗證再次輸入密碼

    var validateCheckNewPass = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('請再次輸入密碼'))
      } else if (value !== this.ruleForm.newPass) {
        callback(new Error('兩次輸入密碼不一致!!'))
      } else {
        callback()
      }
    }

    return {
      ruleForm: {
        oldPass: '',
        newPass: '',
        checkNewPass: ''
      },
      rules: {
        oldPass: [{ validator: validateOldPass, trigger: 'blur' }],
        newPass: [{ validator: validateNewPass, trigger: 'blur' }],
        checkNewPass: [{ validator: validateCheckNewPass, trigger: 'blur' }]
      }
    }
  },
  methods: {
    submitForm (formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          let params = {
            oldPassword: this.ruleForm.oldPass,
            newPassword: this.ruleForm.newPass
          }
          this.$http
            .put(`/user/update/${sessionStorage.uid}`, params)
            .then(res => {
              this.$message.success('修改密碼成功!請重新登錄')
              sessionStorage.clear()
              setTimeout(() => {
                this.$router.push({ path: '/' })
              }, 1000)
            })
            .catch(err => {
              console.log('Error=>', err)
            })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    resetForm (formName) {
      this.$refs[formName].resetFields()
    }
  }
}
</script>
<style scoped>
.change-password {
  width: 400px;
  margin: 10px auto;
}
</style>

vue+nodejs+express+mysql 建立一個在線網盤程序