0
点赞
收藏
分享

微信扫一扫

vue易购商城项目code

一点读书 2022-04-13 阅读 23
vue.js

ego/server/config.js

module.exports = {
    jwtSecret:"somesecretkeyforjsonwebtoken"
}

ego/server/index.js

const express = require("express");
const app = express();
const router = require("./router")
const debug = require('debug')("my-application")
const bodyParser = require("body-parser");
const cors = require("cors");
const port = 3005;

app.use(express.static('upload'))
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended:true
}));
app.use("/api",router)
// cors跨域处理
app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "http://localhost:3005");
    res.header("Access-Control-Allow-Headers", "Content-Type,Access-Token");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",' 3.2.1');
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
})

app.listen(port,() =>{
    debug("服务器运行在:http://localhost:"+port);
})

ego/server/mysql.js

const mysql = require("mysql");
var client = mysql.createConnection({
    host:"localhost",
    user:"root",
    password:"",
    database:"ego02"
})

function sqlFn(sql,arr,callback){
    client.query(sql,arr,function(error,result){
        if(error){
            console.log(error);
            return;
        }
        // 回调函数
        callback(result)
    })
}

module.exports = sqlFn

ego/server/nodemon.json

{
    "restartable": "rs",
    "ignore": [
        ".git",
        ".svn",
        "node_modules/**/node_modules"
    ],
    "verbose": true,
    "execMap": {
        "js": "node --harmony"
    },
    "watch": [
 
    ],
    "env": {
        "NODE_ENV": "development"
    },
    "ext": "js json"
}

ego/server/router.js

const express = require("express");
const router = express.Router();
const sqlFn = require("./mysql");
const jwt = require("jsonwebtoken");
const config = require("./config");
const url = require("url")
const multer = require("multer");
const fs = require("fs");
const { isFunction } = require("util");

/**
 * 登陆接口
 */
router.post("/login", (req, res) => {
    const { username, password } = req.body;
    const sql = "select * from user where `username`=? and `password`=?";
    const arr = [username, password];
    sqlFn(sql, arr, result => {
        // 返回用户信息
        if (result.length > 0) {
            const token = jwt.sign({
                id: result[0].id,
                username: result[0].username
            }, config.jwtSecret)
            res.send(token);
        } else {
            res.status(401).json({
                errors: "用户名密码错误"
            })
        }
    })
})

/**
 * 注册接口
 */
router.post("/register", (req, res) => {
    const { username, password, email } = req.body;
    const sql = "insert into user values(null,?,?,?)";
    const arr = [username, password, email];
    sqlFn(sql, arr, (result) => {
        if (result.affectedRows > 0) {
            res.send({
                msg: "注册成功",
                status: 200
            })
        } else {
            res.status(401).json({
                errors: "用户名密码错误"
            })
        }
    })
})

/**
 * 商品管理 查询接口
 * 参数:page
 */
router.get("/backend/item/selectTbItemAllByPage", (req, res) => {
    const page = url.parse(req.url, true).query.page || 1;
    const sql = "select * from project order by id desc limit 10 offset " + (page - 1) * 10;
    sqlFn(sql, null, result => {
        if (result.length > 0) {
            res.send({
                status: 200,
                data: result
            })
        } else {
            res.send({
                status: 500,
                msg: "暂无数据"
            })
        }
    })
})

/**
 * 商品总条数
 */
router.get("/total", (req, res) => {
    const sql = "select count(*) from project where id";
    sqlFn(sql, null, result => {
        if (result.length > 0) {
            res.send({
                status: 200,
                result
            })
        } else {
            res.send({
                status: 500,
                msg: "无更多数据"
            })
        }
    })
})

/**
 * 类目选择
 */
router.get("/backend/itemCategory/selectItemCategoryByParentId", (req, res) => {
    const id = url.parse(req.url, true).query.id || 1;
    const sql = "select * from category where id=?"
    var arr = [id];
    sqlFn(sql, arr, result => {
        if (result.length > 0) {
            res.send({
                status: 200,
                result
            })
        } else {
            res.send({
                status: 500,
                msg: "暂无数据"
            })
        }
    })
})

/**
 * 上传图片
 */
var storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "./upload/")
    },
    filename: function (req, file, cb) {
        cb(null, Date.now() + "-" + file.originalname)
    }
})

var createFolder = function (folder) {
    try {
        fs.accessSync(folder);
    } catch (e) {
        fs.mkdirSync(folder);
    }
}

var uploadFolder = './upload/';
createFolder(uploadFolder);
var upload = multer({ storage: storage });

router.post('/upload', upload.single('file'), function (req, res, next) {
    var file = req.file;
    console.log('文件类型:%s', file.mimetype);
    console.log('原始文件名:%s', file.originalname);
    console.log('文件大小:%s', file.size);
    console.log('文件保存路径:%s', file.path);
    res.json({ res_code: '0', name: file.originalname, url: file.path });
});

/**
 * 商品添加
 */
router.get("/backend/item/insertTbItem", (req, res) => {
    /**
     * 获取参数
     */
    var title = url.parse(req.url, true).query.title || "";
    var cid = url.parse(req.url, true).query.cid || "";
    var sellPoint = url.parse(req.url, true).query.sellPoint || "";
    var price = url.parse(req.url, true).query.price || "";
    var num = url.parse(req.url, true).query.num || "";
    var desc = url.parse(req.url, true).query.desc || "";
    var image = url.parse(req.url, true).query.image || "";

    const sql = "insert into project values (null,?,?,?,?,?,?,'',1,'','',?)"
    var arr = [title, image, sellPoint, price, cid, num, desc];
    sqlFn(sql, arr, result => {
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "添加成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "添加失败"
            })
        }
    })
})

/**
 * 在写东西的时候,知识点不会或者某个细节卡住了,不太重要
 * 重要的是业务和流程必须心里清楚
 */

/**
 * 商品查询接口
 */
router.get("/search", (req, res) => {
    var search = url.parse(req.url, true).query.search;
    const sql = "select * from project where concat(`title`,`sellPoint`,`descs`) like '%" + search + "%'";
    sqlFn(sql, null, (result) => {
        if (result.length > 0) {
            res.send({
                status: 200,
                result
            })
        } else {
            res.send({
                status: 500,
                msg: "暂无数据"
            })
        }
    })
})

/**
 * 商品删除接口
 */
router.get("/backend/item/deleteItemById", (req, res) => {
    var id = url.parse(req.url, true).query.id;
    const sql = "delete from project where id=?"
    const arr = [id];
    sqlFn(sql, arr, result => {
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "删除成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "删除失败"
            })
        }
    })
})

/**
 * 预更新接口
 */
router.get("/backend/item/preUpdateItem", (req, res) => {
    var id = url.parse(req.url, true).query.id;
    const sql = "select * from project where id=?";
    sqlFn(sql, [id], result => {
        if (result.length > 0) {
            res.send({
                status: 200,
                result
            })
        } else {
            res.send({
                status: 500,
                msg: "预更新失败"
            })
        }
    })
})

/**
 * 修改商品
 */

router.get("/backend/item/updateTbItem", (req, res) => {
    var id = url.parse(req.url, true).query.id;
    var title = url.parse(req.url, true).query.title || "";
    var sellPoint = url.parse(req.url, true).query.sellPoint || "";
    var price = url.parse(req.url, true).query.price || "";
    var num = url.parse(req.url, true).query.num || "";
    var desc = url.parse(req.url, true).query.desc || "";
    var image = url.parse(req.url, true).query.image || "";
    var sql = "update project set title=?,sellPoint=?,price=?,num=?,descs=?,image=? where id=?";
    var arr = [title, sellPoint, price, num, desc, image, id];
    sqlFn(sql, arr, result => {
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "修改成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "修改失败"
            })
        }
    })
})

/**
 * 预更新 类目选择
 */
router.get("/preCategory", (req, res) => {
    var cid = url.parse(req.url, true).query.cid;
    const sql = "select * from category where cid=?";
    sqlFn(sql, [cid], result => {
        if (result.length > 0) {
            res.send({
                status: 200,
                result
            })
        } else {
            res.send({
                status: 500,
                msg: "获取失败"
            })
        }
    })
})

/**
 * 规格参数 查询
 */
router.get("/backend/itemParam/selectItemParamAll", (req, res) => {
    const page = url.parse(req.url, true).query.page || 1;
    const sql = "select * from params order by id desc limit 10 offset " + (page - 1) * 10;
    sqlFn(sql, [page], result => {
        if (result.length > 0) {
            res.send({
                status: 200,
                result
            })
        } else {
            res.send({
                status: 500,
                msg: "暂无数据"
            })
        }
    })
})

/**
 * 规格参数  模糊查询
 */
router.get("/params/search", (req, res) => {
    var search = url.parse(req.url, true).query.search;
    const sql = "select * from params where concat(`paramData`) like '%" + search + "%'";
    sqlFn(sql, [search], result => {
        if (result.length > 0) {
            res.send({
                status: 200,
                result
            })
        } else {
            res.send({
                status: 500,
                msg: '暂无数据'
            })
        }
    })
})

/**
 * 规格参数 添加
 */
router.get("/backend/itemParam/insertItemParam", (req, res) => {
    var itemCatId = url.parse(req.url, true).query.itemCatId;
    var paramsContent = url.parse(req.url, true).query.content;
    var sql = "insert into params values (null,?,?)";
    sqlFn(sql, [itemCatId, paramsContent], result => {
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "添加成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "添加失败"
            })
        }
    })
})

/**
 * 类目结构数据获取
 */
router.get("/category/data", (req, res) => {
    var cid = url.parse(req.url, true).query.cid;
    var sql = "select * from params where itemCatId=?";
    sqlFn(sql, [cid], result => {
        if (result.length > 0) {
            res.send({
                status: 200,
                result
            })
        } else {
            res.send({
                status: 500,
                msg: "暂无数据"
            })
        }
    })
})

/**
 * 修改规格参数
 */
router.get("/update/category", (req, res) => {
    var cid = url.parse(req.url, true).query.cid;
    var content = url.parse(req.url, true).query.content;
    var sql = "update params set paramData=? where itemCatId=?";
    sqlFn(sql, [content, cid], result => {
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "修改成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "修改失败"
            })
        }
    })
})

/**
 * 规格参数删除
 */
router.get("/params/delete", (req, res) => {
    var id = url.parse(req.url, true).query.id;
    const sql = "delete from params where id=?"
    const arr = [id];
    sqlFn(sql, arr, result => {
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "删除成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "删除失败"
            })
        }
    })
})

/**
 * 内容分类管理 导航
 */
router.get("/content/selectContentCategoryByParentId", (req, res) => {
    const id = url.parse(req.url, true).query.id || 1;
    const sql = "select * from content where id=?";
    sqlFn(sql, [id], result => {
        if (result.length > 0) {
            res.send({
                status: 200,
                result
            })
        } else {
            res.send({
                status: 500,
                msg: "暂无数据"
            })
        }
    })
})

/**
 * 内容分类管理 增加子导航
 */
router.get("/content/insertContentCategory", (req, res) => {
    const pid = url.parse(req.url, true).query.pid;
    const name = url.parse(req.url, true).query.name;
    const currentId = Math.floor(Math.random() * 10000)
    const sql = "insert into content values (?,?,?)"
    sqlFn(sql, [pid, name, currentId], result => {
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "添加成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "添加失败"
            })
        }
    })
})

/**
 *  内容分类管理 修改子导航
 */
router.get("/content/updateContentCategory", (req, res) => {
    const pid = url.parse(req.url, true).query.pid;
    const name = url.parse(req.url, true).query.name;
    const sql = "update content set name=? where pid=?"
    sqlFn(sql, [name, pid], result => {
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "修改成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "修改失败"
            })
        }
    })
})

/**
 * 内容分类管理 删除子导航
 */
router.get("/content/deleteContentCategoryById", (req, res) => {
    const pid = url.parse(req.url, true).query.pid;
    const sql = "delete from content where pid=?"
    sqlFn(sql, [pid], result => {
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "删除成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "删除失败"
            })
        }
    })
})

/**
 * 内容分类管理 内容增加
 */
router.get("/content/insertTbContent",(req,res) =>{
    const pid = url.parse(req.url, true).query.pid;
    const name = url.parse(req.url, true).query.name;
    const contentUrl = url.parse(req.url, true).query.url;
    const image = url.parse(req.url, true).query.image;
    const sql = "insert into contentinfo values(null,?,?,?,?)";
    sqlFn(sql,[pid,name,contentUrl,image],result =>{
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "添加成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "添加失败"
            })
        }
    })
})


/**
* 内容分类管理 内容删除
*/

router.get("/content/deleteContentByIds",(req,res) =>{
    const id = url.parse(req.url, true).query.id;
    const sql = "delete from contentinfo where id=?"
    sqlFn(sql,[id],result =>{
        if (result.affectedRows > 0) {
            res.send({
                status: 200,
                msg: "删除成功"
            })
        } else {
            res.send({
                status: 500,
                msg: "删除失败"
            })
        }
    })
})

/**
 * 内容分类管理 内容查询
 */
router.get("/content/selectTbContentAllByCategoryId", (req, res) => {
    const pid = url.parse(req.url, true).query.pid;
    const sql = "select * from contentinfo where pid=?"
    sqlFn(sql, [pid], result => {
        if (result.length > 0) {
            res.send({
                status: 200,
                result
            })
        } else {
            res.send({
                status: 500,
                msg: "暂无数据"
            })
        }
    })
})

module.exports = router;

ego/src/api/base.js

/**
 * 网络请求地址
 */

const base = {
    iwenBaseUrl:"/iwen_api",
    baseUrl:"/api",
    loginUrl:"/api/login",
    register:"/api/register",
    projectList:"/api/backend/item/selectTbItemAllByPage",
    total:"/api/total", // 商品总条数据
    categoryUrl:"/api/backend/itemCategory/selectItemCategoryByParentId", // 类目选择地址
    productAdd:"/api/backend/item/insertTbItem", // 商品添加
    search:"/api/search", // 商品查询
    deleteProject:"/api/backend/item/deleteItemById", // 商品删除
    preUpdate:"/api/backend/item/preUpdateItem", // 预更新
    updateProject:"/api/backend/item/updateTbItem", // 修改商品
    preCategory:"/api/preCategory", // 预更新 类目选择
    paramsList:"/api/backend/itemParam/selectItemParamAll", // 规格参数列表
    paramsSearch:"/api/params/search", // 规格参数模糊查询
    paramsAdd:"/api/backend/itemParam/insertItemParam", // 规格参数添加
    categoryData:"/api/category/data", // 添加商品类目数据获取
    updateCategory:"/api/update/category", // 修改规格参数
    paramsDel:"/api/params/delete", // 规格参数删除
    contentList:"/api/content/selectContentCategoryByParentId", // 内容分类管理的查询
    contentAdd:"/api/content/insertContentCategory", // 内容分类管理添加子导航
    contentUpdate:"/api/content/updateContentCategory", // 内容分类管理修改子导航
    contentDel:"/api/content/deleteContentCategoryById", // 内容分类管理删除子导航
    contentInfoList:"/api/content/selectTbContentAllByCategoryId", // 内容分类管理 内容查询
    contentInfoDel:"/api/content/deleteContentByIds", // 内容分类管理 内容删除
    contentInfoAdd:"/api/content/insertTbContent", // 内容分类管理 内容添加
}

export default base

ego/src/api/index.js

/**
 * 网络请求的方法
 */
import axios from "../utils/request"
import base from "./base"

const api = {
    /**
     * 登陆
     */
    login(params) {
        return axios.post(base.baseUrl + base.loginUrl, params);
    },

    /**
     * 注册
     */
    register(params) {
        return axios.post(base.baseUrl + base.register, params)
    },
    /**
     * 商品列表查询
     */
    projectList(params) {
        return axios.get(base.baseUrl + base.projectList, {
            params
        })
    },
    /**
     * 商品数据总条数
     */
    total() {
        return axios.get(base.baseUrl + base.total)
    },
    /**
     * 类目选择
     */
    category(params) {
        return axios.get(base.baseUrl + base.categoryUrl, {
            params
        })
    },
    /**
     * 商品添加
     */
    productAdd(params) {
        return axios.get(base.baseUrl + base.productAdd, {
            params
        })
    },
    /**
     * 商品查询
     */
    search(params) {
        return axios.get(base.baseUrl + base.search, {
            params
        })
    },
    /**
     * 删除商品
     */
    deleteProject(params) {
        return axios.get(base.baseUrl + base.deleteProject, {
            params
        })
    },
    /**
     * 预更新
     */
    preUpdate(params) {
        return axios.get(base.baseUrl + base.preUpdate, {
            params
        })
    },
    /**
     * 修改商品
     */
    updateProject(params) {
        return axios.get(base.baseUrl + base.updateProject, {
            params
        })
    },
    /**
     * 预更新类目选择
     */
    preCategory(params) {
        return axios.get(base.baseUrl + base.preCategory, {
            params
        })
    },
    /**
     * 规格参数查询
     */
    paramsList(params) {
        return axios.get(base.baseUrl + base.paramsList, {
            params
        })
    },
    /**
     * 规格参数 模糊查询
     */
    paramsSearch(params) {
        return axios.get(base.baseUrl + base.paramsSearch, {
            params
        })
    },
    /**
     * 规格参数 添加
     */
    paramsAdd(params) {
        return axios.get(base.baseUrl + base.paramsAdd, {
            params
        })
    },
    /**
     * 添加产品类目获取数据
     */
    categoryData(params) {
        return axios.get(base.baseUrl + base.categoryData, {
            params
        })
    },
    /**
     * 修改规格参数内容
     */
    updateCategory(params) {
        return axios.get(base.baseUrl + base.updateCategory, {
            params
        })
    },
    /**
     * 规格参数删除
     */
    paramsDel(params) {
        return axios.get(base.baseUrl + base.paramsDel, {
            params
        })
    },
    /**
     * 内容分类管理 查询 
     */
    contentList(params) {
        return axios.get(base.baseUrl + base.contentList, {
            params
        })
    },
    /**
     * 内容分类管理 添加
     */
    contentAdd(params){
        return axios.get(base.baseUrl + base.contentAdd, {
            params
        })
    },
    /**
     * 内容分类管理 修改
     */
    contentUpdate(params){
        return axios.get(base.baseUrl + base.contentUpdate, {
            params
        })
    },
    /**
     * 内容分类管理 删除
     */
    contentDel(params){
        return axios.get(base.baseUrl + base.contentDel, {
            params
        })
    },
    /**
     * 内容分类管理 内容查询
     */
    contentInfoList(params){
        return axios.get(base.baseUrl + base.contentInfoList, {
            params
        })
    },
    /**
     * 内容分类管理 内容删除
     */
    contentInfoDel(params){
        return axios.get(base.baseUrl + base.contentInfoDel, {
            params
        })
    },
    /**
     * 内容分类管理 内容添加
     */
    contentInfoAdd(params){
        return axios.get(base.baseUrl + base.contentInfoAdd, {
            params
        })
    }
}

export default api;

ego/src/js/index.js

var obj = {
    value: "111",
    data: [
        {
            childValue: "111",
            children: [
                {
                    label: "111",
                    text: "111"
                }
            ]
        },
        {
            childValue: "222",
            children: [
                {
                    label: "222",
                    text: "222"
                }
            ]
        }
    ]
}

obj.data[1].children.splice(0,1);

obj.data[1].children.push(
    {
        label: "2222",
        text: "2222"
    }
)

obj.data.splice(1,1);

obj.data.push({
    childValue: "222",
    children: [
        {
            label: "222",
            text: "222"
        }
    ]
})


ego/src/plugins/echarts.js

import echarts from "echarts"

const install = function (Vue) {
    // defineProperties:Vue双向数据绑定原理的重要方法2.x
    Object.defineProperties(Vue.prototype, {
        $charts: {
            get() {
                return {
                    line: function (id,echartsData) {
                        this.chart = echarts.init(document.getElementById(id));
                        var colors = echartsData.color;
                        var option = {
                            color: colors,

                            tooltip: {
                                trigger: 'none',
                                axisPointer: {
                                    type: 'cross'
                                }
                            },
                            legend: {
                                data: ['2015 降水量', '2016 降水量']
                            },
                            grid: {
                                top: 70,
                                bottom: 50
                            },
                            xAxis: [
                                {
                                    type: 'category',
                                    axisTick: {
                                        alignWithLabel: true
                                    },
                                    axisLine: {
                                        onZero: false,
                                        lineStyle: {
                                            color: colors[1]
                                        }
                                    },
                                    axisPointer: {
                                        label: {
                                            formatter: function (params) {
                                                return '降水量  ' + params.value
                                                    + (params.seriesData.length ? ':' + params.seriesData[0].data : '');
                                            }
                                        }
                                    },
                                    data: ['2016-1', '2016-2', '2016-3', '2016-4', '2016-5', '2016-6', '2016-7', '2016-8', '2016-9', '2016-10', '2016-11', '2016-12']
                                },
                                {
                                    type: 'category',
                                    axisTick: {
                                        alignWithLabel: true
                                    },
                                    axisLine: {
                                        onZero: false,
                                        lineStyle: {
                                            color: colors[0]
                                        }
                                    },
                                    axisPointer: {
                                        label: {
                                            formatter: function (params) {
                                                return '降水量  ' + params.value
                                                    + (params.seriesData.length ? ':' + params.seriesData[0].data : '');
                                            }
                                        }
                                    },
                                    data: ['2015-1', '2015-2', '2015-3', '2015-4', '2015-5', '2015-6', '2015-7', '2015-8', '2015-9', '2015-10', '2015-11', '2015-12']
                                }
                            ],
                            yAxis: [
                                {
                                    type: 'value'
                                }
                            ],
                            series: [
                                {
                                    name: '2015 降水量',
                                    type: 'line',
                                    xAxisIndex: 1,
                                    smooth: true,
                                    data: echartsData.water
                                },
                                {
                                    name: '2016 降水量',
                                    type: 'line',
                                    smooth: true,
                                    data: [3.9, 5.9, 11.1, 18.7, 48.3, 69.2, 231.6, 46.6, 55.4, 18.4, 10.3, 0.7]
                                }
                            ]
                        }
                        this.chart.setOption(option)
                    }
                }
            }
        }
    })
}

export default install;

ego/src/plugins/element.js

import Vue from 'vue';
import {
  Pagination,
  Dialog,
  Autocomplete,
  Dropdown,
  DropdownMenu,
  DropdownItem,
  Menu,
  Submenu,
  MenuItem,
  MenuItemGroup,
  Input,
  InputNumber,
  Radio,
  RadioGroup,
  RadioButton,
  Checkbox,
  CheckboxButton,
  CheckboxGroup,
  Switch,
  Select,
  Option,
  OptionGroup,
  Button,
  ButtonGroup,
  Table,
  TableColumn,
  DatePicker,
  TimeSelect,
  TimePicker,
  Popover,
  Tooltip,
  Breadcrumb,
  BreadcrumbItem,
  Form,
  FormItem,
  Tabs,
  TabPane,
  Tag,
  Tree,
  Alert,
  Slider,
  Icon,
  Row,
  Col,
  Upload,
  Progress,
  Spinner,
  Badge,
  Card,
  Rate,
  Steps,
  Step,
  Carousel,
  CarouselItem,
  Collapse,
  CollapseItem,
  Cascader,
  ColorPicker,
  Transfer,
  Container,
  Header,
  Aside,
  Main,
  Footer,
  Timeline,
  TimelineItem,
  Link,
  Divider,
  Image,
  Calendar,
  Backtop,
  PageHeader,
  CascaderPanel,
  Loading,
  MessageBox,
  Message,
  Notification
} from 'element-ui';

Vue.use(Pagination);
Vue.use(Dialog);
Vue.use(Autocomplete);
Vue.use(Dropdown);
Vue.use(DropdownMenu);
Vue.use(DropdownItem);
Vue.use(Menu);
Vue.use(Submenu);
Vue.use(MenuItem);
Vue.use(MenuItemGroup);
Vue.use(Input);
Vue.use(InputNumber);
Vue.use(Radio);
Vue.use(RadioGroup);
Vue.use(RadioButton);
Vue.use(Checkbox);
Vue.use(CheckboxButton);
Vue.use(CheckboxGroup);
Vue.use(Switch);
Vue.use(Select);
Vue.use(Option);
Vue.use(OptionGroup);
Vue.use(Button);
Vue.use(ButtonGroup);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(DatePicker);
Vue.use(TimeSelect);
Vue.use(TimePicker);
Vue.use(Popover);
Vue.use(Tooltip);
Vue.use(Breadcrumb);
Vue.use(BreadcrumbItem);
Vue.use(Form);
Vue.use(FormItem);
Vue.use(Tabs);
Vue.use(TabPane);
Vue.use(Tag);
Vue.use(Tree);
Vue.use(Alert);
Vue.use(Slider);
Vue.use(Icon);
Vue.use(Row);
Vue.use(Col);
Vue.use(Upload);
Vue.use(Progress);
Vue.use(Spinner);
Vue.use(Badge);
Vue.use(Card);
Vue.use(Rate);
Vue.use(Steps);
Vue.use(Step);
Vue.use(Carousel);
Vue.use(CarouselItem);
Vue.use(Collapse);
Vue.use(CollapseItem);
Vue.use(Cascader);
Vue.use(ColorPicker);
Vue.use(Transfer);
Vue.use(Container);
Vue.use(Header);
Vue.use(Aside);
Vue.use(Main);
Vue.use(Footer);
Vue.use(Timeline);
Vue.use(TimelineItem);
Vue.use(Link);
Vue.use(Divider);
Vue.use(Image);
Vue.use(Calendar);
Vue.use(Backtop);
Vue.use(PageHeader);
Vue.use(CascaderPanel);

Vue.use(Loading.directive);

Vue.prototype.$loading = Loading.service;
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$prompt = MessageBox.prompt;
Vue.prototype.$notify = Notification;
Vue.prototype.$message = Message;

ego/src/plugins/i18n.js

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import ElementLocale from 'element-ui/lib/locale'
import enLocale from 'element-ui/lib/locale/lang/en'
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'

Vue.use(VueI18n)

const messages = {
    en: {
        message: {
            project: "project",
            params: "params",
            content: "content"
        },
        ...enLocale
    },
    zh: {
        message: {
            project: "商品管理",
            params: "规格参数",
            content: "广告分类管理"
        },
        ...zhLocale
    }
}

const i18n = new VueI18n({
    locale: 'zh', // 设置地区
    messages, // 设置地区信息
})

ElementLocale.i18n((key, value) => i18n.t(key, value))

export default i18n

ego/src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Layout from '../views/Layout.vue'
import Product from "../views/Product"

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Layout',
    component: Layout,
    children: [
      {
        path: "",
        name: "Product",
        component: Product,
        meta: {
          isLogin: true
        }
      },
      {
        path: "params",
        name: "Params",
        component: () => import("../views/Params"),
        meta: {
          isLogin: true
        }
      },
      {
        path: "content",
        name: "Content",
        component: () => import("../views/Content"),
        meta: {
          isLogin: true
        }
      }
    ]
  },
  {
    path: "/login",
    name: "Login",
    component: () => import("../views/Login.vue")
  },
  {
    path: "/user",
    name: "User",
    component: () => import("../views/User"),
    meta: {
      isLogin: true
    }
  }
]

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

export default router

ego/src/router/permission.js

// 路由权限处理

import router from "./index"
import store from "../store"

router.beforeEach((to, from, next) => {
    // 路由设置权限meta.isLogin为true才可进入
    if (to.meta.isLogin) {
        const token = store.state.loginModule.user.token;
        if (token) {
            next();
        } else {
            next({
                path: "/login"
            })
        }
    } else {
        next();
    }
})

ego/src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import loginModule from "./modules/loginModule"
import contentInfoModule from "./modules/contentInfoModule"

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  modules:{
    loginModule,
    contentInfoModule
  }
})

ego/src/store/modules/contentInfoModule.js

import api from "../../api"

export default {
    namespaced: true,
    state: {
        contentInfo:[],
        contentData:{
            id:0,
            name:"",
            pid:0
        }
    },
    mutations: {
        setContentInfo(state,data){
            state.contentInfo = data;
        },
        setContentData(state,data){
            state.contentData = data;
        }

    },
    actions: {
        asyncSetContentInfo({ commit },data){
            commit("setContentData",data)
            api.contentInfoList({
                pid:data.pid
            }).then(res =>{
                if(res.data.status === 200){
                    commit("setContentInfo",res.data.result)
                }else{
                    commit("setContentInfo",[])
                }
            })
        }
    }
}

ego/src/store/modules/loginModule.js

import jwtDecode from "jwt-decode"
import local from "../../utils/lcoalUtils"
import api from "../../api"
import router from "../../router"

export default {
    namespaced: true,
    state: {
        user: {
            username: "",
            isLogined: false,
            token: ""
        }
    },
    mutations: {
        setUser(state, value) {
            state.user = value;
        },
        removeUser(state) {
            state.user = {
                username: "",
                isLogined: false,
                token: ""
            }
        }
    },
    actions: {
        setUserActions({ commit }, user) {
            api.login({
                username: user.username,
                password: user.password,
            })
                .then((res) => {
                    if (res.status === 200) {
                        const temp = {
                            username: jwtDecode(res.data).username,
                            isLogined: Boolean(jwtDecode(res.data).username),
                            token: res.data
                        }
                        commit("setUser", temp)
                        // 本地存储
                        local.setLocal("ego", temp)
                        /**
                         * 跳转到首页
                         */
                        router.push("/")
                    }
                });
        }
    }
}

ego/src/utils/event-bus.js

import Vue from "vue"

const EventBus = new Vue();
Object.defineProperties(Vue.prototype,{
    $bus:{
        get:function(){
            return EventBus
        }
    }
})

ego/src/utils/lcoalUtils.js

import qs from "querystring"

const local = {
    /**
     * 
     * @param { string } key 
     * @param { object } obj 
     */
    setLocal(key,obj){
        /**
         * stringify:{name:'iwen'} -> name=iwen&
         * parse:name=iwen -> {name:"iwen"}
         */
        localStorage.setItem(key,qs.stringify(obj));
    },
    getLocal(key){
        const result = localStorage.getItem(key);
        return qs.parse(result);
    },
    removeLocal(key){
        localStorage.removeItem(key)
    }
}

export default local

ego/src/utils/request.js

import axios from "axios"
import qs from "querystring"
import router from "../router"
import store from "../store"

const toLogin = () =>{
    router.push("/login")
}

const errorHandle = (status,info) =>{
    switch(status){
        case 400:
            console.log("服务器收到客户端通过PUT或者POST请求提交的表示,表示的格式正确,但服务器不懂它什么意思");
            toLogin();
            break;
        case 401:
            console.log("客户端试图对一个受保护的资源进行操作,却又没有提供正确的认证证书");
            toLogin();
            break;
        case 403:
            console.log("客户端请求的结构正确,但是服务器不想处理它");
            toLogin();
            break;
        case 404:
            console.log("资源被围定义(网络请求地址错误)");
            break;
        case 500:
            console.log("执行请求处理代码时遇到了异常,它们就发送此响应代码");
            break;
        case 503:
            console.log("最可能的原因是资源不足:服务器突然收到太多请求,以至于无法全部处理");
            break;
        default:
            console.log(info);
            break;
    }
}

const instance = axios.create({
    timeout:5000
})

instance.all = axios.all;
instance.spread = axios.spread
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

instance.interceptors.request.use(
    config =>{
        if(config.method === 'post'){
            config.data = qs.stringify(config.data);
        }
        // 判断token是否存在,存在就添加到请求头上
        // const token = store.state.loginModule.user.token;
        // if(token){
        //     config.headers.authorization = store.state.loginModule.user.token;
        // }
        return config;
    },
    error => Promise.reject(error)
)

instance.interceptors.response.use(
    response => response.status === 200 ? Promise.resolve(response) : Promise.reject(response) ,
    error =>{
        const { response } = error;
        if(response){
            errorHandle(response.status,response.data);
            return Promise.reject(response);
        }else{
            console.log("请求被中断");
        }
    }
)

export function get(url,params){
    return new Promise((resolve,reject) =>{
        instance.get(url,{
            params
        }).then(res =>{
            resolve(res.data);
        }).catch(err =>{
            reject(err.data);
        })
    })
}

export function post(url,params){
    return new Promise((resolve,reject) =>{
        instance.post(url,params).then(res =>{
            resolve(res.data)
        }).catch(err =>{
            reject(err.data)
        })
    })
}

export default instance

ego/src/views/Content/ContentInfo.vue

<template>
    <div>
        <el-button @click="contentInfoAdd" v-if="contentData.name">添加{{ contentData.name }}</el-button>
        <el-table :data="contentInfo" style="width: 100%">
            <el-table-column show-overflow-tooltip prop="pid" label="PID" width="180"></el-table-column>
            <el-table-column show-overflow-tooltip prop="name" label="名称" width="180"></el-table-column>
            <el-table-column show-overflow-tooltip prop="url" label="访问地址"></el-table-column>
            <el-table-column show-overflow-tooltip prop="image" label="图片地址"></el-table-column>
            <el-table-column label="操作">
                <template slot-scope="scope">
                    <el-button
                        size="mini"
                        type="danger"
                        @click="handleDelete(scope.$index, scope.row)"
                    >删除</el-button>
                </template>
            </el-table-column>
        </el-table>
        <el-dialog
            title="添加数据"
            :visible.sync="dialogInfoVisible"
            width="30%"
            :before-close="handleClose"
        >
            <el-form :model="ruleForm" status-icon ref="ruleForm" label-width="100px">
                <el-form-item label="名称" prop="name">
                    <el-input type="text" v-model="ruleForm.name" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item label="访问地址" prop="url">
                    <el-input type="text" v-model="ruleForm.url" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item label="图片地址" prop="image">
                    <el-input type="text" v-model="ruleForm.image" autocomplete="off"></el-input>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogInfoVisible = false">取 消</el-button>
                <el-button type="primary" @click="contentInfoAddHandle">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
import { mapState, mapActions } from "vuex";
export default {
    data() {
        return {
            dialogInfoVisible: false,
            ruleForm: {
                name: "",
                url: "",
                image: "",
            },
        };
    },
    computed: {
        ...mapState("contentInfoModule", ["contentInfo", "contentData"]),
    },
    methods: {
        ...mapActions("contentInfoModule", ["asyncSetContentInfo"]),
        contentInfoAdd() {
            this.dialogInfoVisible = true;
        },
        contentInfoAddHandle() {
            this.$api
                .contentInfoAdd({
                    pid: this.contentData.pid,
                    name: this.ruleForm.name,
                    url: this.ruleForm.url,
                    image: this.ruleForm.image,
                })
                .then((res) => {
                    if (res.data.status === 200) {
                        this.dialogInfoVisible = false;
                        this.asyncSetContentInfo(this.contentData);
                    } else {
                        console.log("失败了");
                    }
                });
        },
        handleClose() {
            this.dialogInfoVisible = false;
        },
        handleDelete(index, row) {
            this.$api
                .contentInfoDel({
                    id: row.id,
                })
                .then((res) => {
                    this.asyncSetContentInfo(this.contentData);
                });
        },
    },
};
</script>

<style>
</style>

ego/src/views/Content/ContentNav.vue

<template>
    <div>
        <el-tree
            highlight-current
            :props="defaultProps"
            :load="loadNode"
            lazy
            @node-click="handleNodeClick"
            :expand-on-click-node="false"
            :render-content="renderContent"
        ></el-tree>
        <el-dialog
            title="添加子导航"
            :visible.sync="dialogContentAddVisible"
            width="30%"
            :before-close="handleClose"
        >
            <el-input type="text" v-model="addContent"></el-input>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogContentAddVisible = false">取 消</el-button>
                <el-button type="primary" @click="sureContentAddHandle">确 定</el-button>
            </span>
        </el-dialog>
        <el-dialog
            title="修改导航"
            :visible.sync="dialogContentUpdateVisible"
            width="30%"
            :before-close="handleClose"
        >
            <el-input type="text" v-model="updateContent"></el-input>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogContentUpdateVisible = false">取 消</el-button>
                <el-button type="primary" @click="sureContentUpdateHandle">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>

import { mapActions } from "vuex"

export default {
    name: "ContentNav",
    inject:["reload"],
    data() {
        return {
            addContent: "",
            updateContent: "",
            dialogContentAddVisible: false,
            dialogContentUpdateVisible: false,
            defaultProps: {
                children: "children",
                label: "name",
            },
            ContentData: {},
        };
    },
    methods: {
        ...mapActions("contentInfoModule",["asyncSetContentInfo"]),
        loadNode(node, resolve) {
            if (node.level === 0) {
                this.$api.contentList().then((res) => {
                    if (res.data.status === 200) {
                        return resolve(res.data.result);
                    } else {
                        return resolve([]);
                    }
                });
            }
            if (node.level >= 1) {
                this.$api
                    .contentList({
                        id: node.data.pid,
                    })
                    .then((res) => {
                        if (res.data.status === 200) {
                            return resolve(res.data.result);
                        } else {
                            return resolve([]);
                        }
                    })
                    .catch((error) => {
                        resolve([]);
                    });
            }
        },
        handleNodeClick(data) {
            console.log(data);
            this.asyncSetContentInfo(data)
        },
        renderContent(h, { node, data, store }) {
            return (
                <span class="custom-tree-node">
                    <span>{node.label}</span>
                    <span>
                        <el-button
                            size="mini"
                            type="text"
                            on-click={() => this.append(node, data)}
                        >
                            增加子导航
                        </el-button>
                        <el-button
                            size="mini"
                            type="text"
                            on-click={() => this.update(node, data)}
                        >
                            修改
                        </el-button>
                        <el-button
                            size="mini"
                            type="text"
                            on-click={() => this.remove(node, data)}
                        >
                            删除
                        </el-button>
                    </span>
                </span>
            );
        },
        append(node, data) {
            this.ContentData = data;
            this.dialogContentAddVisible = true;
        },
        update(node, data) {
            this.ContentData = data;
            this.dialogContentUpdateVisible = true;
        },
        remove(node, data) {
            this.$api
                .contentDel({
                    pid: data.pid,
                })
                .then((res) => {
                    if (res.data.status === 200) {
                        this.reload();
                        console.log(res.data.msg);
                    } else {
                        console.log(res.data.msg);
                    }
                });
        },
        sureContentAddHandle() {
            this.$api
                .contentAdd({
                    name: this.addContent,
                    pid: this.ContentData.pid,
                })
                .then((res) => {
                    if (res.data.status === 200) {
                        console.log(res.data.msg);
                        this.reload();
                    } else {
                        console.log(res.data.msg);
                    }
                });
        },
        sureContentUpdateHandle() {
            this.$api
                .contentUpdate({
                    name: this.updateContent,
                    pid: this.ContentData.pid,
                })
                .then((res) => {
                    if (res.data.status === 200) {
                        console.log(res.data.msg);
                        this.reload();
                    } else {
                        console.log(res.data.msg);
                    }
                });
        },
        handleClose() {
            this.dialogContentAddVisible = false;
        },
    },
};
</script>

<style>
</style>

ego/src/views/Content/index.vue

<template>
    <div>
        <div class="content-left">
            <ContentNav />
        </div>
        <div class="content-right">
            <ContentInfo />
        </div>
    </div>
</template>

<script>
import ContentNav from "./ContentNav";
import ContentInfo from "./ContentInfo";

export default {
    data() {
        return {
            // isRouterAlive: true,
        };
    },
    // provide() {
    //     return {
    //         reload: this.reload,
    //     };
    // },
    components: {
        ContentNav,
        ContentInfo,
    },
    methods: {
        // reload() {
        //     this.isRouterAlive = false;
        //     this.$nextTick(() => {
        //         // DOM更新
        //         this.isRouterAlive = true;
        //     });
        // },
    },
};
</script>

<style scoped>
.content {
    height: 200px;
    margin: 0 auto;
    margin-top: 10px;
}

.content-left {
    float: left;
    width: 25%;
    height: 100%;
}

.content-right {
    float: left;
    width: 75%;
    height: 100%;
}

.custom-tree-node {
    display: inline-block;
    text-align: right;
    width: 100%;
}
.upload img {
    width: 200px;
}
</style>

ego/src/views/NavMenu/index.vue

<template>
    <el-menu
        :default-active="activeIndex"
        class="el-menu-demo"
        mode="horizontal"
        @select="handleSelect"
        background-color="#545c64"
        text-color="#fff"
        active-text-color="#ffd04b"
        router
    >
        <el-menu-item index="/"><i class="el-icon-menu"></i>{{ $t("message.project") }}</el-menu-item>
        <el-menu-item index="/params"><i class="el-icon-document"></i>{{ $t("message.params") }}</el-menu-item>
        <el-menu-item index="/content"><i class="el-icon-setting"></i>{{ $t("message.content") }}</el-menu-item>
        <div class="user">
            <router-link to="/user" tag="span" class="user-name">{{ user.username }}</router-link>
            <el-button class="logout" @click="logoutHandle">退出</el-button>
        </div>
        <el-menu-item class="set-lang">
            <el-dropdown @command="handleCommand">
                <span class="el-dropdown-link">
                    语言环境
                    <i class="el-icon-arrow-down el-icon--right"></i>
                </span>
                <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item command="zh">中文</el-dropdown-item>
                    <el-dropdown-item command="en">英文</el-dropdown-item>
                </el-dropdown-menu>
            </el-dropdown>
        </el-menu-item>
    </el-menu>
</template>

<script>
import { mapState, mapMutations } from "vuex";
import local from "../../utils/lcoalUtils";
import i18n from "../../plugins/i18n"

export default {
    name: "NavMenu",
    data() {
        return {
            activeIndex: "/",
        };
    },
    computed: {
        ...mapState("loginModule", ["user"]),
    },
    mounted() {
        if (sessionStorage.getItem("path")) {
            this.activeIndex = sessionStorage.getItem("path");
        }
    },
    methods: {
        ...mapMutations("loginModule", ["removeUser"]),
        handleSelect(key, keyPath) {
            if(key){
                sessionStorage.setItem("path", key);
            }
        },
        logoutHandle() {
            /**
             * 本地清除
             * 状态清除
             * 回到登录页
             */
            local.removeLocal("ego");
            this.removeUser();
            this.$router.push("/login");
        },
        /**
         * 切换语言环境
         */
        handleCommand(command){
            i18n.locale = command
        }
    },
};
</script>

<style scoped lang="less">
.user {
    float: right;
    margin-right: 20px;
    line-height: 60px;
    .user-name {
        color: #fff;
        margin-right: 10px;
        font-size: 15px;
        border: 1px solid #fff;
        border-radius: 50%;
        width: 40px;
        height: 40px;
        display: inline-block;
        line-height: 40px;
    }
    .logout {
    }
}

.set-lang {
    float: right !important;
}

.el-dropdown-link {
    color: #fff;
}
</style>

ego/src/views/Params/index.vue

<template>
    <div>
        <ParamsHead />
        <ParamsList />
        <ParamsAdd />
    </div>
</template>

<script>
import ParamsList from "./ParamsList";
import ParamsHead from "./ParamsHead";
import ParamsAdd from "./ParamsAdd"
export default {
    data() {
        return {};
    },
    components: {
        ParamsList,
        ParamsHead,
        ParamsAdd
    },
};
</script>

<style>
</style>

ego/src/views/Params/ParamsAdd.vue

<template>
    <el-dialog
        title="添加规格参数"
        :visible.sync="dialogParamsAddVisible"
        width="60%"
        :before-close="handleClose"
    >
        <ParamsCategory @onParamsCategory="getParamsCategory" />
        <el-dialog width="50%" title="规格参数" :visible.sync="innerParamsAddVisible" append-to-body>
            <el-button @click="addDomain">添加分组</el-button>
            <el-form :model="dynamicValidateForm" ref="dynamicValidateForm">
                <el-form-item
                    v-for="(item,index) in dynamicValidateForm.domains"
                    :key="index"
                    label="规格参数"
                >
                    <el-input v-model="item.value" style="width:80%"></el-input>
                    <el-button @click="addParams(index)">添加参数</el-button>
                    <el-button @click="removeDomain(item)">删除分组</el-button>
                    <div v-for="(childItem,childIndex) in item.children" :key="childIndex">
                        <el-input v-model="childItem.childValue" style="width:60%;margin-left:80px"></el-input>
                        <el-button @click="removeChild(index,childItem)">删除参数</el-button>
                    </div>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="innerParamsAddVisible = false">取 消</el-button>
                <el-button type="primary" @click="paramsSubimt">提 交</el-button>
            </span>
        </el-dialog>
        <span slot="footer" class="dialog-footer">
            <el-button @click="dialogParamsAddVisible = false">取 消</el-button>
            <el-button :disabled="disabled" type="primary" @click="paramsContentHandle">确定并添加分组内容</el-button>
        </span>
    </el-dialog>
</template>

<script>
import ParamsCategory from "./ParamsCategory";
export default {
    data() {
        return {
            dialogParamsAddVisible: false,
            innerParamsAddVisible: false,
            disabled: true,
            categoryData: {},
            dynamicValidateForm: {
                domains: [
                    {
                        value: "",
                        children: [
                            {
                                childValue: "",
                                value: "",
                            },
                            {
                                childValue: "",
                                value: "",
                            },
                        ],
                    },
                ],
            },
        };
    },
    mounted() {
        this.$bus.$on("onParamsAdd", () => {
            this.dialogParamsAddVisible = true;
        });
    },
    components: {
        ParamsCategory,
    },
    methods: {
        getParamsCategory(category) {
            this.disabled = false;
            this.categoryData = category;
        },
        paramsContentHandle() {
            this.innerParamsAddVisible = true;
        },
        handleClose() {
            dialogParamsAddVisible = false;
        },
        /**
         * 添加规格大分类
         */
        addDomain() {
            this.dynamicValidateForm.domains.push({
                value: "",
                children: [
                    {
                        childValue: "",
                        value: "",
                    },
                    {
                        childValue: "",
                        value: "",
                    },
                ],
            });
        },

        /**
         * 删除规格参数大分类
         */
        removeDomain(item) {
            /**
             * React移除, split
             */
            var index = this.dynamicValidateForm.domains.indexOf(item);
            this.dynamicValidateForm.domains.splice(index, 1); // start count
        },
        /**
         * 添加规格小分类
         */
        addParams(index) {
            this.dynamicValidateForm.domains[index].children.push({
                childValue: "",
                value: "",
            });
        },
        /**
         * 删除规格参数小分类
         */
        removeChild(index, childItem) {
            var num = this.dynamicValidateForm.domains[index].children.indexOf(
                childItem
            );
            this.dynamicValidateForm.domains[index].children.splice(num, 1); // start count
        },
        /**
         * 用户添加提示
         */
        openMessage(msg) {
            const h = this.$createElement;
            this.$notify({
                title: "添加提示",
                message: h(
                    "i",
                    { style: "color: teal" },
                    msg
                ),
            });
        },
        /**
         * 提交事件
         */
        paramsSubimt() {
            // 对象类型数据不可以直接传递,以前我们都是字符串
            this.$api.paramsAdd({
                    itemCatId: this.categoryData.cid,
                    content: JSON.stringify(this.dynamicValidateForm.domains)
                })
                .then((res) => {
                    if (res.data.status === 200) {
                        this.dialogParamsAddVisible = false;
                        this.innerParamsAddVisible = false;
                    }
                    this.openMessage(res.data.msg);
                    this.$bus.$emit("addOnFresh")
                });
        },
    },
};
</script>

<style>
</style>

ego/src/views/Params/ParamsCategory.vue

<template>
    <el-tree
        highlight-current
        :props="defaultProps"
        :load="loadNode"
        lazy
        @node-click="handleNodeClick"
    ></el-tree>
</template>

<script>
export default {
    data() {
        return {
            defaultProps: {
                children: "children",
                label: "name",
            },
        };
    },
    methods: {
        loadNode(node, resolve) {
            if (node.level === 0) {
                this.$api.category().then((res) => {
                    if (res.data.status === 200) {
                        return resolve(res.data.result);
                    } else {
                        return resolve([]);
                    }
                });
            }
            if (node.level >= 1) {
                this.$api.category({
                        id: node.data.cid,
                    })
                    .then((res) => {
                        if (res.data.status === 200) {
                            return resolve(res.data.result);
                        } else {
                             return resolve([]);
                        }
                    })
                    .catch((error) => {
                        resolve([]);
                    });
            }
        },
        handleNodeClick(data) {
            this.$emit("onParamsCategory",data)
        },
    },
};
</script>

<style>
</style>

ego/src/views/Params/ParamsHead.vue

<template>
    <div class="head">
        <el-form ref="searchForm" :model="search" @submit.native.prevent>
            <el-form-item>
                <el-input @clear="clearHandle" clearable v-model="search.content" @keyup.enter.native="onSubmitSearch"></el-input>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="onSubmitSearch">查询</el-button>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="onSubmitAdd">添加</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
export default {
    name: "Head",
    data() {
        return {
            search: {
                content: "",
            },
        };
    },
    methods: {
        onSubmitSearch(e) {
            if (e.keyCode === 13) {
                e.preventDefault();
            }
            if (this.search.content !== "") {
                this.$api.paramsSearch({
                    search:this.search.content
                }).then(res =>{
                    if(res.data.status === 200){
                        this.$bus.$emit("onParamsSearch",res.data.result)
                    }else{
                        this.$bus.$emit("onParamsSearch",[])
                    }
                })
            }
        },
        onSubmitAdd() {
            this.$bus.$emit("onParamsAdd")
        },
        clearHandle(){
            this.$bus.$emit("onParamsClear")
        }
    },
};
</script>

<style scoped lang="less">
.el-form {
    overflow: hidden;
    clear: both;
    .el-form-item {
        float: left;
        margin-right: 10px;
        .el-input {
            width: 1230px;
        }
    }
}

.head {
    margin-top: 20px;
    width: 100%;
}
</style>

ego/src/views/Params/ParamsList.vue

<template>
    <div>
        <el-table :data="paramsData">
            <el-table-column prop="id" label="规格参数ID" width="100"></el-table-column>
            <el-table-column prop="itemCatId" label="类目ID" width="100"></el-table-column>
            <el-table-column show-overflow-tooltip prop="paramData" label="规格参数"></el-table-column>
            <el-table-column label="操作" width="80">
                <template slot-scope="scope">
                    <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 {
    name: "ParamsList",
    data() {
        return {
            paramsData: [],
            page: 1,
        };
    },
    mounted() {
        this.$bus.$on("onParamsSearch", (result) => {
            this.paramsData = result;
        });
        this.$bus.$on("onParamsClear", (result) => {
            this.http(this.page);
        });
        this.$bus.$on("addOnFresh", () => {
            this.http(this.page);
        });
    },
    created() {
        this.http(this.page);
    },
    methods: {
        http(page) {
            this.$api
                .paramsList({
                    page: page,
                })
                .then((res) => {
                    if (res.data.status === 200) {
                        this.paramsData = res.data.result;
                    }
                });
        },
        handleDelete(index, row) {
            this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning",
            })
                .then(() => {
                    this.$api.paramsDel({
                            id: row.id,
                        })
                        .then((res) => {
                            if (res.data.status === 200) {
                                this.$message({
                                    type: "success",
                                    message: "删除成功!",
                                });
                                this.http(this.page);
                            } else {
                                this.$message({
                                    type: "error",
                                    message: "删除失败",
                                });
                            }
                        });
                })
                .catch(() => {
                    this.$message({
                        type: "info",
                        message: "已取消删除",
                    });
                });
        },
    },
};
</script>

<style>
</style>

ego/src/views/Product/index.vue

<template>
    <div>
        <ProductHead />
        <ProjectList />
        <Pagination />
        <ProductAdd />
        <ProductPreUpdate />
    </div>
</template>

<script>
import ProductHead from "./ProductHead";
import ProjectList from "./ProjectList";
import Pagination from "./Pagination";
import ProductAdd from "./ProductAdd";
import ProductPreUpdate from "./ProductPreUpdate"
export default {
    components: {
        ProjectList,
        Pagination,
        ProductHead,
        ProductAdd,
        ProductPreUpdate
    }
};
</script>

<style>
</style>

ego/src/views/Product/Pagination.vue

<template>
    <el-pagination class="pagination" layout="prev, pager, next, jumper" :total="total" @current-change="getPageHandle"></el-pagination>
</template>

<script>
export default {
    name:"Pagination",
    data(){
        return{
            total:0
        }
    },
    mounted(){
        this.$api.total().then(res =>{
            this.total = res.data.result[0]["count(*)"];
        })
        this.$bus.$on("onSearch",search =>{
            this.total = search.length;
        })
    },
    methods:{
        getPageHandle(page){
            this.$bus.$emit("onPage",page)
        }
    }
};
</script>

<style scoped lang="less">
.pagination{
    margin-top: 50px;
}
</style>

ego/src/views/Product/ProductAdd.vue

<template>
    <el-dialog
        title="添加商品"
        :visible.sync="dialogAddVisible"
        width="80%"
        :before-close="handleClose"
    >
        <el-form label-width="70px" :label-position="labelPosition" :model="addForm" ref="ruleForm">
            <el-form-item label="类目选择">
                <el-button @click="categoryInnerVisible = true" class="category" type="primary">类目选择</el-button>
                <span class="category">{{ categoryData.name }}</span>
                <el-dialog
                    width="50%"
                    title="类目选择"
                    :visible.sync="categoryInnerVisible"
                    append-to-body
                >
                    <ProductCategory @categoryEvent="getCategroy" />
                    <span slot="footer" class="dialog-footer">
                        <el-button type="primary" @click="getCategoryDataHandle">确 定</el-button>
                    </span>
                </el-dialog>
            </el-form-item>
            <el-form-item label="商品名称" prop="name">
                <el-input v-model="addForm.name"></el-input>
            </el-form-item>
            <el-form-item label="商品卖点" prop="sellPoint">
                <el-input v-model="addForm.sellPoint"></el-input>
            </el-form-item>
            <el-form-item label="商品价格" prop="price">
                <el-input v-model="addForm.price"></el-input>
            </el-form-item>
            <el-form-item label="商品数量" prop="num">
                <el-input v-model="addForm.num"></el-input>
            </el-form-item>
            <el-form-item label="商品图片">
                <el-button @click="uploadInnerVisible = true" class="category" type="primary">图片上传</el-button>
                <img class="upload-img" :src="uploadData.url" alt />
                <el-dialog
                    width="50%"
                    title="图片上传"
                    :visible.sync="uploadInnerVisible"
                    append-to-body
                >
                    <ProductUpload @onUpload="getUpload" />
                    <span slot="footer" class="dialog-footer">
                        <el-button type="primary" @click="uploadInnerVisible = false">确 定</el-button>
                    </span>
                </el-dialog>
            </el-form-item>
            <el-form-item label="商品描述">
                <!-- <ProjectUEditor /> -->
                <ProjectWangEditor @onEditor="getEditor" />
            </el-form-item>
            <!-- 类目选择结构视图 -->
            <div v-for="(item,index) in categoryAddData" :key="index">
                <h3>{{ item.value }}</h3>
                <div v-for="(childItem,childIndex) in item.children" :key="childIndex">
                    <el-form-item label-width="130px" :label="childItem.childValue">
                        <el-input v-model="childItem.value" type="text"></el-input>
                    </el-form-item>
                </div>
            </div>
        </el-form>
        <span slot="footer" class="dialog-footer">
            <el-button @click="dialogAddVisible = false">取 消</el-button>
            <el-button type="primary" @click="sureSubmit">确 定</el-button>
        </span>
    </el-dialog>
</template>

<script>
import ProductCategory from "./ProductCategory";
import ProductUpload from "./ProductUpload";
import ProjectUEditor from "./ProdutUEditor";
import ProjectWangEditor from "./ProductWangeditor";

export default {
    data() {
        return {
            dialogAddVisible: false,
            categoryInnerVisible: false,
            uploadInnerVisible: false,
            categoryAddData: [],
            labelPosition: "left",
            addForm: {
                name: "",
                sellPoint: "",
                price: "",
                num: "",
            },
            categoryData: {},
            uploadData: {},
            editorData: "",
        };
    },
    props: {
        flag: {
            type: Boolean,
            default: false,
        },
    },
    components: {
        ProductCategory,
        ProductUpload,
        ProjectUEditor,
        ProjectWangEditor,
    },
    mounted() {
        this.$bus.$on("productAddVisible", (flag) => {
            this.dialogAddVisible = flag;
        });
    },
    methods: {
        handleClose(done) {
            this.$confirm("确认关闭?")
                .then((_) => {
                    done();
                })
                .catch((_) => {});
        },
        /**
         * 获取类目数据
         */
        getCategroy(data) {
            this.categoryData = data;
        },
        /**
         * 图片资源
         */
        getUpload(data) {
            var url = "http://localhost:3005" + data.url.replace("upload", "");
            this.uploadData = {
                url,
                name: data.name,
            };
        },
        /**
         * 获取富文本编辑器数据
         */
        getEditor(data) {
            this.editorData = data;
        },
        /**
         * 表单提交后清空表单
         */
        clearForm(){
            this.$refs["ruleForm"].resetFields();
            this.categoryData = {};
            this.uploadData = {};
            this.editorData = "";
        },
        /**
         * 添加商品提交
         */
        sureSubmit() {
            this.$api
                .productAdd({
                    title: this.addForm.name,
                    cid: this.categoryData.cid,
                    sellPoint: this.addForm.sellPoint,
                    price: this.addForm.price,
                    num: this.addForm.num,
                    desc: this.editorData,
                    image: this.uploadData.url,
                })
                .then((res) => {
                    if (res.data.status === 200) {
                        this.clearForm();
                        this.dialogAddVisible = false;
                        this.$bus.$emit("onAddSuccess");
                    }
                });
            // 提交规格参数的数据 todo
            this.$api.updateCategory({
                    cid: this.categoryData.cid,
                    content: JSON.stringify(this.categoryAddData),
                })
                .then((res) => {
                    if (res.data.status === 200) {
                        console.log(res.data.msg);
                    } else {
                        console.log(res.data.msg);
                    }
                });
        },
        /**
         *  类目结构数据获取
         */
        getCategoryDataHandle() {
            this.categoryInnerVisible = false;
            this.$api.categoryData({
                    cid: this.categoryData.cid,
                })
                .then((res) => {
                    this.categoryAddData = JSON.parse(
                        res.data.result[0].paramData
                    );
                });
        },
    },
};
</script>

<style scoped lang="less">
.category {
    float: left;
    margin-right: 20px;
}
.upload-img {
    width: 400px;
    float: left;
}
</style>

ego/src/views/Product/ProductCategory.vue

<template>
    <el-tree
        highlight-current
        :props="defaultProps"
        :load="loadNode"
        lazy
        @node-click="handleNodeClick"
    ></el-tree>
</template>

<script>
export default {
    data() {
        return {
            defaultProps: {
                children: "children",
                label: "name",
            },
        };
    },
    methods: {
        loadNode(node, resolve) {
            if (node.level === 0) {
                this.$api.category().then((res) => {
                    if (res.data.status === 200) {
                        return resolve(res.data.result);
                    } else {
                        return resolve([]);
                    }
                });
            }
            if (node.level >= 1) {
                this.$api.category({
                        id: node.data.cid,
                    })
                    .then((res) => {
                        if (res.data.status === 200) {
                            return resolve(res.data.result);
                        } else {
                             return resolve([]);
                        }
                    })
                    .catch((error) => {
                        resolve([]);
                    });
            }
        },
        handleNodeClick(data) {
            this.$emit("categoryEvent",data)
        },
    },
};
</script>

<style>
</style>

ego/src/views/Product/ProductHead.vue

<template>
    <div class="head">
        <el-form ref="searchForm" :model="search" @submit.native.prevent>
            <el-form-item>
                <el-input v-model="search.content" @keyup.enter.native="onSubmitSearch"></el-input>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="onSubmitSearch">查询</el-button>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="onSubmitAdd">添加</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>

<script>
export default {
    name: "Head",
    data() {
        return {
            search: {
                content: "",
            },
        };
    },
    methods: {
        onSubmitSearch(e) {
            if(e.keyCode === 13){
                e.preventDefault();
            }
            if (this.search.content !== "") {
                this.$api.search({
                    search: this.search.content,
                }).then(res =>{
                    if(res.data.status === 200){
                        this.$bus.$emit("onSearch",res.data.result)
                    }
                })
            }
        },
        onSubmitAdd() {
            this.$bus.$emit("productAddVisible", true);
        },
    },
};
</script>

<style scoped lang="less">
.el-form {
    overflow: hidden;
    clear: both;
    .el-form-item {
        float: left;
        margin-right: 10px;
        .el-input {
            width: 1230px;
        }
    }
}

.head {
    margin-top: 20px;
    width: 100%;
}
</style>

ego/src/views/Product/ProductPreUpdate.vue

<template>
    <el-dialog
        title="修改商品"
        :visible.sync="dialogUpdateVisible"
        width="80%"
        :before-close="handleClose"
    >
        <el-form label-width="70px" :label-position="labelPosition" :model="updateForm">
            <el-form-item label="类目选择">
                <el-button @click="categoryInnerVisible = true" class="category" type="primary">类目选择</el-button>
                <span class="category">{{ categoryData.name }}</span>
                <el-dialog
                    width="50%"
                    title="类目选择"
                    :visible.sync="categoryInnerVisible"
                    append-to-body
                >
                    <ProductCategory @categoryEvent="getCategroy" />
                    <span slot="footer" class="dialog-footer">
                        <el-button type="primary" @click="categoryInnerVisible = false">确 定</el-button>
                    </span>
                </el-dialog>
            </el-form-item>
            <el-form-item label="商品名称">
                <el-input v-model="updateForm.name"></el-input>
            </el-form-item>
            <el-form-item label="商品卖点">
                <el-input v-model="updateForm.sellPoint"></el-input>
            </el-form-item>
            <el-form-item label="商品价格">
                <el-input v-model="updateForm.price"></el-input>
            </el-form-item>
            <el-form-item label="商品数量">
                <el-input v-model="updateForm.num"></el-input>
            </el-form-item>
            <el-form-item label="商品图片">
                <el-button @click="uploadInnerVisible = true" class="category" type="primary">图片上传</el-button>
                <img class="upload-img" :src="uploadData.url" alt />
                <el-dialog
                    width="50%"
                    title="图片上传"
                    :visible.sync="uploadInnerVisible"
                    append-to-body
                >
                    <ProductUpload @onUpload="getUpload" />
                    <span slot="footer" class="dialog-footer">
                        <el-button type="primary" @click="uploadInnerVisible = false">确 定</el-button>
                    </span>
                </el-dialog>
            </el-form-item>
            <el-form-item label="商品描述">
                <!-- <ProjectUEditor /> -->
                <ProjectWangEditor @onEditor="getEditor" :onEditorData="onEditorData"/>
            </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
            <el-button @click="dialogUpdateVisible = false">取 消</el-button>
            <el-button type="primary" @click="sureSubmit">确 定</el-button>
        </span>
    </el-dialog>
</template>

<script>
import ProductCategory from "./ProductCategory";
import ProductUpload from "./ProductUpload";
import ProjectUEditor from "./ProdutUEditor";
import ProjectWangEditor from "./ProductWangeditor";

export default {
    data() {
        return {
            dialogUpdateVisible: false,
            categoryInnerVisible: false,
            uploadInnerVisible: false,
            labelPosition: "left",
            updateForm: {
                name: "",
                sellPoint: "",
                price: "",
                num: "",
            },
            categoryData: {},
            uploadData: {},
            editorData: "",
            id: "",
            onEditorData:""
        };
    },
    components: {
        ProductCategory,
        ProductUpload,
        ProjectUEditor,
        ProjectWangEditor,
    },
    mounted() {
        this.$bus.$on("updateFlag", (row) => {
            this.dialogUpdateVisible = true;
            this.id = row.id;
            this.updateForm = {
                name: row.title,
                sellPoint: row.sellPoint,
                price: row.price,
                num: row.num,
            };
            this.categoryHttp(row.cid);
            this.uploadData = {
                url: row.image,
            };
            // todo
            this.onEditorData = row.descs
        });
    },
    methods: {
        categoryHttp(cid) {
            this.$api
                .preCategory({
                    cid: cid,
                })
                .then((res) => {
                    if (res.data.status === 200) {
                        this.categoryData = {
                            name: res.data.result[0].name,
                            cid: res.data.result[0].cid,
                        };
                    }else{
                        console.log("失败");
                    }
                });
        },
        handleClose(done) {
            this.$confirm("确认关闭?")
                .then((_) => {
                    done();
                })
                .catch((_) => {});
        },
        /**
         * 获取类目数据
         */
        getCategroy(data) {
            this.categoryData = data;
        },
        /**
         * 图片资源
         */
        getUpload(data) {
            var url = "http://localhost:3005" + data.url.replace("upload", "");
            this.uploadData = {
                url,
                name: data.name,
            };
        },
        /**
         * 获取富文本编辑器数据
         */
        getEditor(data) {
            this.editorData = data;
        },
        /**
         * 修改商品提交
         */
        sureSubmit() {
            this.$api.updateProject({
                    id: this.id,
                    title: this.updateForm.name,
                    sellPoint: this.updateForm.sellPoint,
                    price: this.updateForm.price,
                    num: this.updateForm.num,
                    desc: this.editorData,
                    image: this.uploadData.url,
                })
                .then((res) => {
                    if (res.data.status === 200) {
                        this.dialogUpdateVisible = false;
                        this.$bus.$emit("onAddSuccess");
                    } else {
                        this.$message({
                            type: "error",
                            message: "修改失败",
                        });
                    }
                });
        },
    },
};
</script>

<style scoped lang="less">
.category {
    float: left;
    margin-right: 20px;
}
.upload-img {
    width: 400px;
    float: left;
}
</style>

ego/src/views/Product/ProductUpload.vue

<template>
    <el-upload
        class="upload"
        ref="upload"
        action="http://localhost:3005/api/upload"
        :on-preview="handlePreview"
        :on-remove="handleRemove"
        :limit="1"
        :auto-upload="false"
        :on-success="uploadHandle"
        :file-list="fileList"
    >
        <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
        <el-button
            style="margin-left: 10px;"
            size="small"
            type="success"
            @click="submitUpload"
        >上传到服务器</el-button>
    </el-upload>
</template>

<script>
export default {
    data() {
        return {
            fileList: [],
        };
    },
    methods: {
        handlePreview(file) {
        },
        handleRemove(file, fileList) {
        },
        uploadHandle(res, file, fileList) {
            this.$emit("onUpload",res)
        },
        submitUpload() {
            this.$refs.upload.submit();
        },
    },
};
</script>

<style>
</style>

ego/src/views/Product/ProductWangeditor.vue

<template>
    <div ref="editorElem" style="text-align:left;">
        <div>{{ onEditorData }}</div>
    </div>
</template>

<script>
import wangeditor from "wangeditor";
export default {
    data() {
        return {
            editor: null,
            editorContent: "",
        };
    },
    props: {
        onEditorData: {
            type: String,
            default: "",
        },
    },
    watch: {
        onEditorData(value) {},
    },
    mounted() {
        this.editor = new wangeditor(this.$refs.editorElem);
        this.editor.customConfig.onchange = (html) => {
            this.editorContent = html;
            this.$emit("onEditor", this.editorContent);
        };
        this.editor.customConfig.menus = [
            // 菜单配置
            "head", // 标题
            "bold", // 粗体
            "fontSize", // 字号
            "fontName", // 字体
            "italic", // 斜体
            "underline", // 下划线
            "strikeThrough", // 删除线
            "foreColor", // 文字颜色
            "backColor", // 背景颜色
            "link", // 插入链接
            "list", // 列表
            "justify", // 对齐方式
            "quote", // 引用
            "emoticon", // 表情
            "image", // 插入图片
            "table", // 表格
            "code", // 插入代码
            "undo", // 撤销
            "redo", // 重复
        ];
        this.editor.create(); // 创建富文本实例
        // this.editor.txt.html(this.onEditorData)
    },
};
</script>

<style>
</style>

ego/src/views/Product/ProdutUEditor.vue

<template>
    <vue-ueditor-wrap v-model="msg" :config="myConfig"></vue-ueditor-wrap>
</template>

<script>
import VueUeditorWrap from "vue-ueditor-wrap";
export default {
    data() {
        return {
            msg: "我是富文本编辑器",
            myConfig: {
                // 编辑器不自动被内容撑高
                autoHeightEnabled: false,
                // 初始容器高度
                initialFrameHeight: 240,
                // 初始容器宽度
                initialFrameWidth: "100%",
                // UEditor 资源文件的存放路径,如果你使用的是 vue-cli 生成的项目,通常不需要设置该选项,vue-ueditor-wrap 会自动处理常见的情况,如果需要特殊配置,参考下方的常见问题2
                UEDITOR_HOME_URL: "/UEditor/",
            },
        };
    },
    components: {
        VueUeditorWrap,
    },
};
</script>

<style>
</style>

ego/src/views/Product/ProjectList.vue

<template>
    <div>
        <el-table
            :data="projectData"
            :cell-style="cellStyle"
            @selection-change="handleSelectionChange"
            ref="multipleTable"
        >
            <el-table-column type="selection" width="55"></el-table-column>
            <el-table-column show-overflow-tooltip prop="id" label="商品ID" width="100"></el-table-column>
            <el-table-column show-overflow-tooltip prop="title" label="商品名称" width="200"></el-table-column>
            <el-table-column show-overflow-tooltip prop="image" label="商品图片" width="100"></el-table-column>
            <el-table-column show-overflow-tooltip prop="sellPoint" label="商品卖点" width="300"></el-table-column>
            <el-table-column show-overflow-tooltip prop="price" label="商品价格" width="100"></el-table-column>
            <el-table-column show-overflow-tooltip prop="num" label="商品数量" width="100"></el-table-column>
            <el-table-column show-overflow-tooltip prop="descs" label="商品描述"></el-table-column>
            <el-table-column label="操作" width="145">
                <template slot-scope="scope">
                    <el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
                    <el-button
                        size="mini"
                        type="danger"
                        @click="handleDelete(scope.$index, scope.row)"
                    >删除</el-button>
                </template>
            </el-table-column>
        </el-table>
        <div class="all">
            <el-button>全部删除</el-button>
            <el-button @click="toggleSelection">取消选择</el-button>
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            projectData: [],
            page: 1,
            multipleSelection: [],
        };
    },
    mounted() {
        this.http(this.page);
        this.$bus.$on("onPage", (page) => {
            this.http(page);
        });
        this.$bus.$on("onAddSuccess", () => {
            this.http(this.page);
        });
        this.$bus.$on("onSearch", (search) => {
            this.projectData = search;
        });
    },
    methods: {
        /**
         * 取消选择
         */
        toggleSelection() {
            this.$refs.multipleTable.clearSelection();
        },
        /**
         * 多选操作
         */
        handleSelectionChange(value) {
            this.multipleSelection = value;
            console.log(value);
        },
        /**
         * 改变列颜色
         */
        cellStyle({ row, column, rowIndex, columnIndex }) {
            if (row.num <= 10) {
                // 指定列号
                return {
                    color: "red",
                };
            }
        },
        http(page) {
            this.$api.projectList({ page: page }).then((res) => {
                if (res.data.status === 200) {
                    this.projectData = res.data.data;
                }
            });
        },
        /**
         * 数据编辑
         */
        handleEdit(index, row) {
            this.$bus.$emit("updateFlag", row);
        },
        /**
         * 数据删除
         */
        handleDelete(index, row) {
            this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning",
            })
                .then(() => {
                    this.$api
                        .deleteProject({
                            id: row.id,
                        })
                        .then((res) => {
                            if (res.data.status === 200) {
                                this.$message({
                                    type: "success",
                                    message: "删除成功!",
                                });
                                this.http(this.page);
                            } else {
                                this.$message({
                                    type: "error",
                                    message: "删除失败",
                                });
                            }
                        });
                })
                .catch(() => {
                    this.$message({
                        type: "info",
                        message: "已取消删除",
                    });
                });
        },
    },
};
</script>

<style scoped>
.all {
    float: left;
    margin-top: 10px;
}
</style>

ego/src/views/User/index.vue

<template>
    <div>
        <h3>个人中心</h3>
        <el-button type="text" @click="dialogVisible = true">查看合同</el-button>
        <el-dialog
            title="合同样本"
            :visible.sync="dialogVisible"
            width="70%"
            :before-close="handleClose"
        >
            <div class="parent">
                <el-button @click="$refs.pdf.print()">打印</el-button>
                <pdf
                    ref="pdf"
                    :src="src"
                    :page="currentPage"
                    @progress="getProgress"
                    @page-loaded="currentPage=$event"
                    @loaded="loadPdfHandler"
                ></pdf>
            </div>
            <el-pagination
                background
                layout="prev, pager, next"
                :page-size="1"
                :total="numPages"
                @current-change="changePage"
            ></el-pagination>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
            </span>
        </el-dialog>
        <div id="line"></div>
    </div>
</template>

<script>
import pdf from "vue-pdf";
var loadingTask = pdf.createLoadingTask("./sxt.pdf");

export default {
    data() {
        return {
            dialogVisible: false,
            src: loadingTask,
            currentPage: 1,
            numPages: 1,
            echartData:{
                color:[],
                water:[]
            }
        };
    },
    components: {
        pdf,
    },
    mounted() {
        this.src.promise.then((pdf) => {
            this.numPages = pdf.numPages;
        });
        const color=['red', 'blue', 'pink']
        const water2015 = [200, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
        this.echartData.color = color;
        this.echartData.water = water2015
        this.$charts.line("line",this.echartData)
    },
    methods: {
        handleClose(done) {
            this.$confirm("确认关闭?")
                .then((_) => {
                    done();
                })
                .catch((_) => {});
        },
        changePage(page) {
            this.currentPage = page;
        },
        getProgress(e) {
            console.log("加载进度:", e);
        },
        loadPdfHandler() {
            console.log("PDF加载完成啦");
        }
    },
};
</script>

<style scoped>

#line{
    width: 400px;
    height: 400px;
}

</style>

ego/src/views/Layout.vue

<template>
    <div class="home">
        <NavMenu />
        <div class="container">
          <router-view></router-view>
        </div>
    </div>
</template>

<script>
import NavMenu from "./NavMenu";

export default {
    name: "Home",
    components: {
        NavMenu,
    },
};
</script>
<style lang="less" scoped>

.container{
  width: 1400px;
  margin: 0 auto;
}

</style>

ego/src/views/Login.vue

<template>
    <div class="login">
        <el-tabs
            v-model="activeName"
            type="border-card"
            class="login-tabs"
            stretch
            @tab-click="handleClick"
        >
            <el-tab-pane label="用户登陆" name="login" class="login-tabs-tab">
                <el-form
                    ref="loginForm"
                    :model="user"
                    status-icon
                    :rules="rules"
                    class="login-form"
                >
                    <el-form-item label="用户名" prop="username">
                        <el-input type="text" v-model="user.username"></el-input>
                    </el-form-item>
                    <el-form-item label="密码" prop="password">
                        <el-input type="password" v-model="user.password"></el-input>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" @click="submitForm('loginForm')">登陆</el-button>
                    </el-form-item>
                </el-form>
            </el-tab-pane>
            <el-tab-pane label="用户注册" name="register">
                <el-form
                    ref="registerForm"
                    :model="user"
                    status-icon
                    :rules="rules"
                    class="login-form"
                >
                    <el-form-item label="用户名" prop="username">
                        <el-input type="text" v-model="user.username"></el-input>
                    </el-form-item>
                    <el-form-item label="密码" prop="password">
                        <el-input type="password" v-model="user.password"></el-input>
                    </el-form-item>
                    <el-form-item label="确认密码" prop="surePassword">
                        <el-input type="password" v-model="user.surePassword"></el-input>
                    </el-form-item>
                    <el-form-item label="邮箱" prop="email">
                        <el-input type="email" v-model="user.email"></el-input>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" @click="submitForm('registerForm')">注册</el-button>
                    </el-form-item>
                </el-form>
            </el-tab-pane>
        </el-tabs>
    </div>
</template>

<script>

import { mapActions } from "vuex"

export default {
    name: "Login",
    data() {
        var validateUsername = (rule, value, callback) => {
            if (value === "") {
                callback(new Error("请输入用户名"));
            }
            callback();
        };

        var validatePassword = (rule, value, callback) => {
            if (value === "") {
                callback(new Error("请输入密码"));
            }
            callback();
        };

        var validateSurePassword = (rule, value, callback) => {
            if (value === "") {
                callback(new Error("请输入密码"));
            }
            callback();
        };

        var validateEmail = (rule, value, callback) => {
            if (value === "") {
                callback(new Error("请输入邮箱"));
            }
            callback();
        };

        return {
            user: {
                username: "",
                password: "",
                surePassword: "",
                email:""
            },
            rules: {
                username: [{ validator: validateUsername, trigger: "blur" }],
                password: [{ validator: validatePassword, trigger: "blur" }],
                email: [{ validator: validateEmail, trigger: "blur" }],
                surePassword: [
                    { validator: validateSurePassword, trigger: "blur" },
                ],
            },
            activeName: "login",
        };
    },
    methods: {
        ...mapActions("loginModule",["setUserActions"]),
        submitForm(formName) {
            this.$refs[formName].validate((valid) => {
                if (valid) {
                    /**
                     * 区分是登陆还是注册
                     */
                    if (this.activeName === "login") {
                        /**
                         * 登陆
                         */
                        this.setUserActions(this.user)
                        
                    }
                    if (this.activeName === "register") {
                        /**
                         * 注册
                         */
                        this.$api.register({
                            username:this.user.username,
                            password:this.user.password,
                            email:this.user.email
                        }).then(res =>{
                            console.log(res.data)
                        })
                    }
                } else {
                    console.log("error submit!!");
                    return false;
                }
            });
        },
        handleClick(tab, event) {},
    },
};
</script>

<style scoped lang="less">
.login {
    width: 500px;
    margin: 0 auto;
    margin-top: 100px;
    .login-form {
        padding: 40px 40px;
    }
    h3 {
        margin-top: 20px;
    }
    .login-tabs {
        border-radius: 5px;
    }
}
</style>

ego/src/App.vue

<template>
  <div id="app">
    <!-- 入口文件 router-view -->
    <router-view v-if="isRouterAlive"></router-view>
  </div>
</template>

<script>

export default {
  name: 'app',
  data(){
    return{
      isRouterAlive:true
    }
  },
  components: {
  },
  // 挂在
  provide(){
    return{
      reload:this.reload
    }
  },
  methods:{
    reload(){
      this.isRouterAlive = false;
      this.$nextTick(() =>{
        // DOM更新
        this.isRouterAlive = true;
      })
    }
  }
}
</script>

<style>

</style>

ego/src/main.js

import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
import './plugins/element.js'
import "./assets/css/common.css"
import "./router/permission.js"
import api from "./api"
import local from "./utils/lcoalUtils"
import "./utils/event-bus.js"
import i18n from "./plugins/i18n"
import Echarts from "./plugins/echarts"

Vue.use(Echarts)
Vue.prototype.$api = api;
Vue.config.productionTip = false

if(local.getLocal("ego")){
  store.commit("loginModule/setUser",local.getLocal("ego"))
}

new Vue({
  router,
  store,
  i18n,
  render: h => h(App)
}).$mount('#app')

ego/src/registerServiceWorker.js

/* eslint-disable no-console */

import { register } from 'register-service-worker'

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready () {
      console.log(
        'App is being served from cache by a service worker.\n' +
        'For more details, visit https://goo.gl/AFskqB'
      )
    },
    registered () {
      console.log('Service worker has been registered.')
    },
    cached () {
      console.log('Content has been cached for offline use.')
    },
    updatefound () {
      console.log('New content is downloading.')
    },
    updated () {
      console.log('New content is available; please refresh.')
    },
    offline () {
      console.log('No internet connection found. App is running in offline mode.')
    },
    error (error) {
      console.error('Error during service worker registration:', error)
    }
  })
}

ego/babel.config.js

module.exports = {
  "presets": [
    "@vue/cli-plugin-babel/preset"
  ],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

ego/vue.config.js

module.exports = {
    devServer: {
        proxy: {
            '/api': {
                target: 'http://localhost:3005',
                changeOrigin: true,
                pathRewrite: {
                    "^/api": ""
                }
            },
            '/iwen_api': {
                target: 'http://iwenwiki.com:3001',
                changeOrigin: true,
                pathRewrite: {
                    "^/iwen_api": ""
                }
            },
        }
    }
}
举报

相关推荐

0 条评论