用vue+node+koa+sequlize實現後臺管理系統(1)

首先構建前端項目
1.按照vue官網步驟css

# 1. 若是沒有安裝 Vue CLI 就先安裝
npm install --global @vue/cli

# 2. 建立一個新工程,並選擇 "Manually select features (手動選擇特性)" 選項
vue create my-project-name
一路默認小跑下來便可。

2.安裝一些須要用的依賴包前端

{
  "name": "ace",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "axios": "^0.19.0",
    "core-js": "^3.3.2",
    "element-ui": "^2.12.0",
    "vue": "^2.6.10",
    "vue-class-component": "^7.0.2",
    "vue-property-decorator": "^8.3.0",
    "vue-router": "^3.1.3"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^4.0.0",
    "@vue/cli-plugin-typescript": "^4.0.0",
    "@vue/cli-service": "^4.0.0",
    "less": "^3.10.3",
    "less-loader": "^5.0.0",
    "style-loader": "^1.0.0",
    "typescript": "~3.5.3",
    "vue-template-compiler": "^2.6.10"
  }
}

添加依賴包到package.json中保存,npm install 便可。vue

3.我用到了餓了麼UI庫element,須要在main.ts中引入,webpack

import Element from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(Element);

4.改造vue初始化的項目ios

.
├── App.vue
├── assets
├── components
├── main.ts
├── model
│   └── user.ts
├── router
│   └── index.ts
├── service
│   ├── index.ts
│   └── userService.ts
├── shims-tsx.d.ts
├── shims-vue.d.ts
├── utils
│   └── validators
│       └── index.ts
└── views
    ├── About.vue
    ├── home
    │   ├── Home.less
    │   ├── Home.ts
    │   └── Home.vue
    ├── pager
    │   ├── Paper.ts
    │   └── Paper.vue
    └── user
        ├── User.less
        ├── User.ts
        ├── User.vue
        └── component
            ├── AddUser.ts
            └── AddUser.vue

新增以上文件,頁面能夠本身隨便寫點東西。
下面主要說幾個必須的文件。
-- router/index.ts 前端項目路由配置文件。git

import Vue from 'vue';
import VueRouter from 'vue-router';
const Home = () => import(/* webpackChunkName: "Home" */ '../views/home/Home.vue');
const User = () => import(/* webpackChunkName: "User" */ '../views/user/User.vue');
const Paper = () => import(/* webpackChunkName: "Paper" */ '../views/pager/Paper.vue');
const AddUser = () => import(/* webpackChunkName: "User" */ '../views/user/component/AddUser.vue');
const About = () => import(/* webpackChunkName: "about" */ '../views/About.vue');

Vue.use(VueRouter);

const routes = [
    {
        path: '/',
        name: 'home',
        component: Home,
    },
    {
        path: '/user',
        name: 'name',
        component: User,
    },
    {
        path: '/add',
        name: 'addUser',
        component: AddUser,
    },
    {
        path: '/about',
        name: 'about',
        component: About,
    },
    {
        path: '/paper',
        name: 'paper',
        component: Paper,
    },
];

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes,
});

export default router;

我在項目中用的是axios,service/index.ts文件就是對axios的一個基礎配置,若是你們有其餘的需求,這裏均可以配置。
service/index.tsgithub

import Axios from 'axios';

const instance = Axios.create({
    baseURL: 'http://localhost:3000',
    timeout: 10000,
    headers: {
        'cache-control': 'no-cache',
    },
});

export default instance;

這裏是用戶服務,放在這裏統必定義,方便維護。
service/userService.tsweb

import { IUserList, IUserListModel, IUserModel } from '@/model/user';
import { IQuery } from '../model/user';
import instance from './index';

/**
 * 查詢用戶列表
 */
export const getUserList = async (query: IQuery) => {
    const { data } = await instance.get<IUserListModel>('/api/getUserList', {
        params: {
            ...query,
        },
    });
    return data;
};

/**
 * 添加用戶
 * @param user
 */
export const addUser = async (user: IUserModel) => {
    const data = await instance.post<IUserModel>('/api/addUser', {
        user,
    });
    return data;
};

/**
 * 刪除用戶
 * @param id
 */
export const delUser = async (id: number) => {
    const data = await instance.post('/api/delUser', {
        id,
    });
    return data;
};

/**
 * 根據id查詢用戶信息
 * @param id
 */
export const getUserInfoById = async (id: number) => {
    const { data } = await instance.get<IUserList>('/api/getUserInfoById', {
        params: {
            id,
        },
    });
    return data;
};

/**
 * 編輯用戶
 * @param user
 */
export const editUser = async (user: IUserList) => {
    const { data } = await instance.post<IUserList>('/api/updateUser', {
        user,
    });
    return data;
};

這裏是定一個用戶相關的interface。
model/user.tsvue-router

export interface IUserListModel {
    list: IUserList[];
    totalRows: number;
}
export interface IUserList {
    name: string;
    password: string;
    mobile: string;
    email: string;
    createTime: string;
    updateTime: string;
}

export interface IUserModel {
    name: string;
    password: string;
    mobile: string;
    email: string;
}

export interface IQuery {
    email: string;
    name: string;
    mobile: string;
    pageNo: number;
    pageSize: number;
}

這個文件爲element表單提供驗證,放在一塊兒方便調用,方便維護,能夠根據不一樣的需求改變驗證方式。很靈活。
validators/index.tsvue-cli

export const validateEmail = (_rule: object, value: string, callback: (err?: Error) => void) => {
    if (!value) {
        callback();
    } else {
        if (!/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/.test(value)) {
            callback(new Error('請輸入正確郵箱格式'));
        } else {
            callback();
        }
    }
};

export const validateEmailRequired = (_rule: object, value: string, callback: (err?: Error) => void) => {
    if (!value) {
        callback(new Error('請填寫郵箱'));
    } else {
        if (!/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/.test(value)) {
            callback(new Error('請輸入正確郵箱格式'));
        } else {
            callback();
        }
    }
};

export const validateMobile = (_rule: object, value: string, callback: (err?: Error) => void) => {
    if (!value) {
        callback();
    } else {
        if (!/^1[3456789]\d{9}$/.test(value)) {
            callback(new Error('請輸入正確手機號'));
        } else {
            callback();
        }
    }
};

export const validateMobileRequired = (_rule: object, value: string, callback: (err?: Error) => void) => {
    if (!value) {
        callback(new Error('請填寫手機號'));
    } else {
        if (!/^1[3456789]\d{9}$/.test(value)) {
            callback(new Error('請輸入正確手機號'));
        } else {
            callback();
        }
    }
};

最後寫一個主要的頁面。
views/user/*
user.Vue

<template>
    <div>
        <div class="search-line">
            <el-form :model="query" :rules="queryRules" ref="query" label-width="50px">
                <el-form-item
                    label="姓名"
                    prop="name"
                >
                    <el-input type="text" v-model="query.name" :maxlength="50" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item
                    label="郵箱"
                    prop="email"
                >
                    <el-input type="text" v-model="query.email" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item
                    label="電話"
                    prop="mobile"
                >
                    <el-input type="text" v-model="query.mobile" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="search('query')">搜索</el-button>
                    <el-button @click="addUser">添加</el-button>
                </el-form-item>
            </el-form>
        </div>
        <el-table :data="userList" style="width: 100%">
            <el-table-column prop="name" label="姓名"></el-table-column>
            <el-table-column prop="email" label="郵箱"></el-table-column>
            <el-table-column prop="mobile" label="聯繫方式"></el-table-column>
            <el-table-column prop="createTime" label="建立時間"></el-table-column>
            <el-table-column prop="updateTime" label="更新時間"></el-table-column>
            <el-table-column
                fixed="right"
                label="操做"
                width="100">
                <template slot-scope="scope">
                    <el-button @click="editUser(scope.row.id)" type="text" size="small">編輯</el-button>
                    <el-button type="text" @click="delUser(scope.row.id)" size="small">刪除</el-button>
                </template>
            </el-table-column>
        </el-table>

        <div class="footer-pagi">
            <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="query.pageNo"
                :page-sizes="[5, 10, 20]"
                :page-size="query.pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="totalRows">
        </el-pagination>
        </div>
    </div>
</template>
<script lang="ts" src="./User.ts"></script>
<style scoped lang="less" src="./User.less"></style>

user.ts

import { IUserList } from '@/model/user';
import { Form } from 'element-ui';
import { Component, Vue } from 'vue-property-decorator';
import { IQuery } from '../../model/user';
import { delUser, getUserList } from '../../service/userService';
import { validateEmail, validateMobile } from '../../utils/validators/index';

@Component({})
export default class User extends Vue {
    public userList: IUserList[] = [];

    public query = {
        email: '',
        name: '',
        mobile: '',
        pageNo: 1,
        pageSize: 5,
    };

    public totalRows: number = 0;

    public queryRules: object = {
        email: [{ validator: validateEmail, trigger: 'change' }],
        mobile: [{ validator: validateMobile, trigger: 'change' }],
    };

    public async created() {
        await this.initUserList(this.query);
    }
    public async initUserList(query: IQuery) {
        const data = await getUserList(query);
        this.userList = data.list;
        this.totalRows = data.totalRows;
    }
    public addUser() {
        this.$router.push('/add');
    }
    public async delUser(id: number) {
        this.$confirm('是否繼續?', '提示', {
            confirmButtonText: '肯定',
            cancelButtonText: '取消',
            type: 'warning',
        })
            .then(async () => {
                await delUser(id);
                await this.initUserList(this.query);
                this.$message({
                    type: 'success',
                    message: '刪除成功!',
                });
            })
            .catch(() => {
                this.$message({
                    type: 'info',
                    message: '已取消刪除',
                });
            });
    }

    public editUser(id: number) {
        this.$router.push(`/add?id=${id}`);
    }

    public async search(val: string) {
        (this.$refs[val] as Form).validate((valid) => {
            if (valid) {
                this.initUserList(this.query);
            }
        });
    }

    public resetForm(val: string) {
        (this.$refs[val] as Form).resetFields();
    }

    public async handleSizeChange(val: number) {
        this.query.pageSize = val;
        await this.initUserList(this.query);
    }

    public async handleCurrentChange(val: number) {
        this.query.pageNo = val;
        await this.initUserList(this.query);
    }
}

user.less

.search-line {
    display: flex;
    flex-wrap: nowrap;
}
.search-line .el-form {
    display: flex;
    flex-wrap: nowrap;
}

.footer-pagi {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 999;
    padding-left: 30px;
    height: 50px;
    background: #fff;
    box-shadow: 0 0 10px rgba(0,0,0,.12);
}

.footer-pagi .el-pagination {
    margin-top: 10px;
}

vue所需的基本頁面及配置文件基本添加完畢。若是有同窗也用ts寫的話,能夠參考typescript官網修改tslint.json和tsconfig.json.
tslint配置項

至此,前端頁面基本完畢。下一篇我貼上後臺代碼。

相關文章
相關標籤/搜索