Skip to content

一、项目结构

运行环境:

  • 前端框架:Vue 3

  • Vue写法:Options API,把数据、方法、生命周期分开写

  • 组件库:element-plus ,框架已经全局内置,无需再引入

  • 构建工具:Webpack 5

  • Node 版本:18 及以上版本

代码结构:

python
vue/
├─ package.json
├─ webpack.config.js
├─ public/
│  └─ lib/                     # 通用前端库(qrcode/address/tiptap/echarts)
└─ src/
   ├─ app.js                   # 前端启动入口
   ├─ layout/                  # 全局布局
   ├─ pages/                   # 业务页面
   │  ├─ routes.js             # 路由生成
   │  ├─ index.js              # 页面模块聚合
   │  ├─ dict.js               # 全局业务字典
   │  └─ */*                   # 具体页面
   ├─ components/              # 全局业务组件
   └─ app.js

1. package.json 初始化

json
{
    "name": "erp",
    "version": "0.0.1",
    "private": true,
    "scripts": {
        "start": "webpack-dev-server --mode=development --host=127.0.0.1",
        "dist": "npm run lint && webpack --mode=production",
        "local": "npm run lint && webpack --mode=production --env target=local && npm run java",
        "java": "cd ../erp && mvn clean package -DskipTests -Dlocal=true",
        "deploy": "npm run lint && webpack --mode=production --env target=tos && npm run java",
        "lint": "eslint --fix --ext .js,.vue ./src"
    },
    "dependencies": {
        "core-js": "^3.6.5"
    },
    "devDependencies": {
        "@babel/core": "^7.23.5",
        "@babel/plugin-syntax-jsx": "^7.23.3",
        "@babel/plugin-transform-runtime": "^7.17.0",
        "@babel/preset-env": "^7.23.5",
        "@vue/babel-plugin-jsx": "^1.1.5",
        "@vue/babel-preset-app": "^5.0.8",
        "@vue/compiler-sfc": "^3.4.15",
        "babel-eslint": "^10.1.0",
        "babel-loader": "^8.2.4",
        "css-loader": "^3.5.3",
        "eslint": "^7.28.0",
        "eslint-plugin-vue": "^8.4.1",
        "fs-extra": "^10.0.0",
        "prettier": "^2.5.1",
        "prismjs": "^1.22.0",
        "sass": "^1.89.0",
        "sass-loader": "^16.0.5",
        "style-loader": "^3.3.4",
        "terser-webpack-plugin": "^5.3.1",
        "vue": "^3.4.21",
        "vue-loader": "^17.3.1",
        "webpack": "^5.99.9",
        "webpack-cli": "^6.0.1",
        "webpack-dev-server": "^4.15.2",
        "zen-app-icon": "^0.1.0",
        "zen-app-plugin": "^0.5.10"
    },
    "eslintIgnore": [
        "public/*",
        "dist/*"
    ],
    "eslintConfig": {
        "root": true,
        "env": {
            "node": true
        },
        "extends": [
            "plugin:vue/vue3-essential",
            "eslint:recommended"
        ],
        "plugins": [
            "vue"
        ],
        "parserOptions": {
            "parser": "babel-eslint",
            "sourceType": "module"
        },
        "globals": {
            "zen": true,
            "$": true,
            "Vue": true
        },
        "rules": {
            "no-useless-escape": 0,
            "no-debugger": 0,
            "vue/multi-word-component-names": 0,
            "no-case-declaration": 0,
            "vue/no-mutating-props": 0
        }
    },
    "browserslist": [
        "last 1 chrome version",
        "last 1 firefox version",
        "last 1 safari version"
    ]
}

若项目包含移动端,scripts部分需要调衡,如:

json
"scripts": {
    "start": "webpack-dev-server --mode=development --host=127.0.0.1",
    "wap": "cd ../wap && npm install -d && npm run lint && webpack --mode=production && cd ../vue",
    "dist": "npm run lint && webpack --mode=production",
    "local": "npm run wap && npm run lint && webpack --mode=production --env target=local && npm run java",
    "java": "cd ../erp_cust && mvn clean package -DskipTests -Dlocal=true",
    "deploy": "npm run wap && npm run lint && webpack --mode=production --env target=tos && npm run java",
    "lint": "eslint --fix --ext .js,.vue ./src"
},

2. webpack.config.js 初始化

javascript
const path = require("path");
const ZenPlugin = require("zen-app-plugin");

module.exports = (env, argv) => {
    const target = env && env.target ? env.target : "";
    let mode = argv.mode;
    return ZenPlugin({
        target,
        mode,
        ROOT: path.resolve("./"),
        port: "7100",
        name: "erp_cust",
        apps: { cms: 7057, openpl: 7076 },
    });
};

配置apps: { cms: 7057, openpl: 7076 },后前端可以调用其他应用的接口,如:配置了cms可以调用cms的接口,调用方法:/cms/api/home/test

3. 具体页面目录

例:

python
finance/                         # 一级目录
├─ pay/                            # 二级目录
   ├─ .lowcode/                    # 低代码目录,仅低代码生成的有,在代码中手动建的页面没有
       ├─ configs.jsx              # 
       └─ data                     # 
   ├─ blocks/                      # 局部组件
       └─ select.vue
   └─ pay.vue                      # 主页面
├─ incomeOrExpenditure/            # 二级目录
    ├─ category/                       # 三级目录
        ├─ .lowcode/                   # 低代码目录,仅低代码生成的有,在代码中手动建的页面没有
           ├─ configs.jsx              # 
           └─ data                     # 
        ├─ blocks/                     # 局部组件
           └─ test.vue
        └─ category.vue                # 主页面
     └─ index.js                       # 路由
├─ receive/                        # 其他二级目录
└─ index.js                    # 路由

一级目录下的路由:

javascript
import FinancePay from "./pay/pay";
import incomeOrExpenditure from "./incomeOrExpenditure/index.js";
import FinanceReceive from "./receive/receive";

export default {
    'finance/pay': FinancePay,
    ...incomeOrExpenditure,
    'finance/receive': FinanceReceive,
}

二级目录下的路由:

javascript
import FinanceIncomeOrExpenditureCategory from "./category/category";

export default {
    'finance/incomeOrExpenditure/category': FinanceIncomeOrExpenditureCategory,
}

注意:路由必须严格遵循这种格式

4. app.js

示例:

python
import Layout from './layout/index.vue'
import dict from './pages/dict'
import Routes from './pages/routes'
import components from './components/index'
zen.path('erp_cust')

zen.setup({ com: Layout, routes: Routes, dict, components })

5. routes.js 路由

示例:

javascript
import pages from "./index";
let routes = [{ path: "/", redirect: "/welcome" }];
let isExist;

Object.keys(pages).forEach((pagePath) => {
    isExist = false;
    for (let index = 0; index < routes.length; index++) {
        const route = routes[index];
        if (route.path === "/" + pagePath) {
            isExist = true;
            break;
        }
    }
    if (!isExist) {
        routes.push({ path: "/" + pagePath, component: pages[pagePath] });
    }
});
export default routes;

6. pages 下 index.js

示例:

javascript
import settings from './settings/index';
import template from './template/index';
import users from './users/index';

export default {
  ...settings,
        ...template,
        ...users
};

7. dict.js 字典

示例:

json
export default {"outStatus":{"t":1,"v":[{"value":1,"label":"未出库","color":"#ff4500"},{"value":3,"label":"已出库","color":"#90ee90"},{"value":5,"label":"部分出库","color":"#1e90ff"}]},"inStatus":{"t":1,"v":[{"value":1,"label":"未入库","color":""},{"value":3,"label":"已入库","color":""},{"value":5,"label":"部分入库","color":""}]},"purchBookStatus":{"t":1,"v":[{"value":0,"label":"未审核","color":"#d40001"},{"value":1,"label":"未入库","color":"#ff4500"},{"value":3,"label":"已入库","color":"#90ee90"},{"value":5,"label":"部分入库","color":"#1e90ff"}]},"posDocType":{"t":1,"v":[{"value":1,"label":"零售收银单","color":""},{"value":3,"label":"零售退货单","color":""}]},"saleDocType":{"t":1,"v":[{"value":1,"label":"销售单","color":""},{"value":3,"label":"销售预定单","color":""},{"value":5,"label":"销售退货单","color":""}]},"salespersonStatus":{"t":1,"v":[{"value":1,"label":"启用","color":"#90ee90"},{"value":3,"label":"禁用","color":"#ff4500"}]},"incomeAndExpenseType":{"t":1,"v":[{"value":1,"label":"收入","color":""},{"value":3,"label":"支出","color":""}]},"inAndOutProject":{"t":1,"v":[{"value":1,"label":"账户开账","color":""},{"value":3,"label":"期初余额调整","color":""},{"value":5,"label":"进货预定定金","color":""},{"value":7,"label":"进货支出","color":""},{"value":9,"label":"进货退货","color":""},{"value":11,"label":"销售预定定金","color":""},{"value":13,"label":"销售收入","color":""},{"value":15,"label":"销售退货","color":""},{"value":17,"label":"收款","color":""},{"value":19,"label":"付款","color":""},{"value":21,"label":"其它收入","color":""},{"value":23,"label":"其它支出","color":""},{"value":25,"label":"资金调拨","color":""}]},"posPriceMode":{"t":1,"v":[{"value":1,"label":"零售价","color":""},{"value":2,"label":"批发价","color":""}]},"inoutProject":{"t":1,"v":[{"value":1,"label":"账户开账","color":""},{"value":3,"label":"期初余额调整","color":""},{"value":5,"label":"进货预定定金","color":""},{"value":7,"label":"进货支出","color":""},{"value":9,"label":"进货退货","color":""},{"value":11,"label":"销售预定定金","color":""},{"value":13,"label":"销售收入","color":""},{"value":15,"label":"销售退货","color":""},{"value":17,"label":"收款","color":""},{"value":19,"label":"付款","color":""},{"value":21,"label":"其它收入","color":""},{"value":23,"label":"其它支出","color":""},{"value":25,"label":"资金调拨","color":""}]},"payeeType":{"t":1,"v":[{"value":1,"label":"客户","color":""},{"value":6,"label":"供应商","color":""}]},"paymentType":{"t":1,"v":[{"value":1,"label":"客户","color":""},{"value":6,"label":"供应商","color":""}]},"logAction":{"t":1,"v":[{"value":1,"label":"插入","color":""},{"value":2,"label":"更新","color":""},{"value":3,"label":"删除","color":""}]},"docExpendType":{"t":1,"v":[{"value":1,"label":"人工费","color":"#1e90ff"},{"value":3,"label":"搬运费","color":"#f8d03f"},{"value":5,"label":"运费","color":"#90ee90"}]},"cfg_levelPrice":{"t":4,"v":[{"value":"1","label":"零售价","color":""},{"value":"3","label":"批发价","color":""},{"value":"5","label":"等级价一","color":""},{"value":"7","label":"等级价二","color":""},{"value":"9","label":"等级价三","color":""}]},"businessType":{"t":1,"v":[{"value":1,"label":"进货","color":""},{"value":3,"label":"销售","color":""},{"value":5,"label":"进货退货","color":""},{"value":7,"label":"销售退货","color":""},{"value":9,"label":"进货预定","color":""},{"value":11,"label":"销售预定","color":""},{"value":13,"label":"收款","color":""},{"value":15,"label":"付款","color":""},{"value":17,"label":"其它入库","color":""},{"value":19,"label":"其它出库","color":""},{"value":21,"label":"零售","color":""},{"value":23,"label":"零售退货","color":""},{"value":25,"label":"资金调拨","color":""},{"value":29,"label":"库存调拨","color":""},{"value":31,"label":"库存盘点","color":""},{"value":33,"label":"对账","color":""},{"value":34,"label":"财务对账","color":""},{"value":35,"label":"标签","color":""},{"value":37,"label":"积分兑换","color":""}]},"printSize":{"t":1,"v":[{"value":1,"label":"A4","color":""},{"value":2,"label":"二等分241*140mm","color":""},{"value":3,"label":"三等份241*93mm","color":""},{"value":4,"label":"190*130mm","color":""},{"value":5,"label":"小票(58mm)","color":""},{"value":6,"label":"自定义","color":""}]},"guild":{"t":1,"v":[{"value":1,"label":"服饰类","color":"#d40001"},{"value":5,"label":"数码类","color":"#0e7bf8"},{"value":10,"label":"五金类","color":"#999000"},{"value":20,"label":"其它类","color":""}]},"inventoryStatus":{"t":1,"v":[{"value":1,"label":"盘盈","color":"#90ee90"},{"value":3,"label":"盘亏","color":"#ff4500"},{"value":5,"label":"无盈亏","color":""}]},"salesStatus":{"t":1,"v":[{"value":1,"label":"未销售","color":"#ff8c00"},{"value":3,"label":"已销售","color":"#90ee90"}]},"verificationType":{"t":1,"v":[{"value":1,"label":"预收抵扣应收","color":""},{"value":6,"label":"预付抵扣应付","color":""}]},"supplierDebtType":{"t":1,"v":[{"value":1,"label":"供应商初次欠款单","color":""},{"value":6,"label":"进货单","color":""},{"value":11,"label":"进货退货单","color":""},{"value":16,"label":"付款单","color":""}]},"receiveType":{"t":1,"v":[{"value":1,"label":"客户收款","color":""},{"value":6,"label":"供应商收款","color":""}]},"purchDocType":{"t":1,"v":[{"value":1,"label":"进货单","color":"#ff6900"},{"value":3,"label":"进货预定单","color":"#f8d03f"},{"value":5,"label":"进货退货单","color":"#1e90ff"}]},"stockDocType":{"t":1,"v":[{"value":1,"label":"入库单","color":""},{"value":3,"label":"出库单","color":""},{"value":5,"label":"串码调价单","color":""},{"value":7,"label":"库存调拨单","color":""}]},"outstockDocType":{"t":1,"v":[{"value":1,"label":"其它出库单","color":"#999000"},{"value":3,"label":"盘亏单","color":"#ffd700"}]},"instockDocType":{"t":1,"v":[{"value":1,"label":"其它入库单","color":"#999000"},{"value":3,"label":"盘盈单","color":"#ffd700"}]},"balanceActionType":{"t":1,"v":[{"value":1,"label":"资金增加","color":"#90ee90"},{"value":6,"label":"资金减少","color":"#ff4500"}]},"debtType":{"t":1,"v":[{"value":1,"label":"客户期初欠款单","color":""},{"value":6,"label":"销售单","color":""},{"value":9,"label":"销售退货单","color":""},{"value":11,"label":"收款单","color":""},{"value":13,"label":"零售退货单","color":""}]},"documentType":{"t":1,"v":[{"value":1,"label":"进货单"},{"value":3,"label":"销售单"},{"value":5,"label":"进货退货单"},{"value":7,"label":"销售退货单","color":""},{"value":9,"label":"进货预订单","color":""},{"value":11,"label":"销售预订单","color":""},{"value":13,"label":"收款单","color":""},{"value":15,"label":"付款单","color":""},{"value":17,"label":"其他收入单","color":""},{"value":19,"label":"其他支出单","color":""},{"value":21,"label":"零售收银单","color":""},{"value":23,"label":"零售退货单","color":""},{"value":24,"label":"资金调拨单","color":""},{"value":25,"label":"资金调拨单-出","color":""},{"value":27,"label":"资金调拨单-入","color":""},{"value":29,"label":"库存调拨单","color":""},{"value":31,"label":"库存盘点单","color":""},{"value":33,"label":"进货单据支出","color":""},{"value":35,"label":"销售单据支出","color":""},{"value":37,"label":"客户储值单","color":""},{"value":39,"label":"积分兑换单","color":""},{"value":41,"label":"串码调价单","color":""},{"value":43,"label":"其他出库单","color":""},{"value":45,"label":"其他入库单","color":""},{"value":47,"label":"核销单","color":""}]},"refundStatus":{"t":1,"v":[{"value":1,"label":"未处理","color":"#ff4500"},{"value":3,"label":"已全部退款","color":"#90ee90"},{"value":5,"label":"部分退款","color":"#ff4500"}]},"verifiedStatus":{"t":1,"v":[{"value":1,"label":"已核销","color":"#90ee90"},{"value":3,"label":"未核销","color":"#ff4500"},{"value":5,"label":"部分核销","color":"#999000"}]},"verifiedType":{"t":1,"v":[{"value":1,"label":"手动核销","color":""}]},"bookStatus":{"t":1,"v":[{"value":0,"label":"未审核","color":"#d40001"},{"value":1,"label":"未出库","color":"#ff4500"},{"value":3,"label":"已出库","color":"#90ee90"},{"value":5,"label":"部分出库","color":"#1e90ff"}]},"invoiceStatus":{"t":1,"v":[{"value":1,"label":"未开票","color":""},{"value":3,"label":"已开票","color":"#90ee90"},{"value":5,"label":"无需发票","color":"#cccccc"}]},"reviewStatus":{"t":1,"v":[{"value":1,"label":"未审核","color":""},{"value":3,"label":"已审核","color":"#90ee90"}]},"salesPayStatus":{"t":1,"v":[{"value":1,"label":"未付款","color":"#d40001"},{"value":3,"label":"已付款","color":"#90ee90"},{"value":5,"label":"部分付款","color":""}]},"cfg_customerLevel":{"t":4,"v":[{"value":"1","label":"散客","color":""},{"value":"3","label":"普通客户","color":""},{"value":"5","label":"一级客户","color":""},{"value":"7","label":"二级客户","color":""},{"value":"9","label":"三级客户","color":""}]},"stockLogType":{"t":1,"v":[{"value":1,"label":"入库","color":"#90ee90"},{"value":2,"label":"出库","color":""}]},"productStatus":{"t":1,"v":[{"value":1,"label":"待上架","color":"#999000"},{"value":3,"label":"已上架","color":"#90ee90"},{"value":5,"label":"未发布","color":"#cccccc"}]}}

8. layout

layout下的index.vue/index.js,如果app.js中引入,那么每次进入都会先经过,可以做一些登录校验