前端最终规范


plop 生成前端页面

<p>主要配置文件 plopfile.js</p> <pre><code class="language-javascript">const viewGenerator = require('./templates/view/prompt') const curdGenerator = require('./templates/curd/prompt') const componentGenerator = require('./templates/component/prompt') // const mockGenerator = require('./templates/mock/prompt') const vuexGenerator = require('./templates/vuex/prompt') // const routerGenerator = require('./templates/router/prompt') /**************清楚标签*******************/ var fs = require('fs') let configs = require('./configs') function transformTemplate() { configs.views.map((item) =&gt; { let filePath = `./src/views/${item.moduleName}/index.vue` fs.readFile(filePath, 'utf8', function (err, data) { if (err) { return console.log(err) } var result = data.replace(/Template/g, '') console.log(result) fs.writeFile(filePath, result, 'utf8', function (err) { if (err) return console.log(err) }) }) }) } /**************清楚标签*******************/ module.exports = (plop) =&gt; { plop.setGenerator('view', viewGenerator) // plop.setGenerator('mock&amp;api', mockGenerator) // plop.setGenerator('router', routerGenerator) plop.setHelper('properArry', (x1, x2, options) =&gt; { return JSON.stringify(x1) }) // plop.setHelper('properForm', (x1, x2, options) =&gt; { // console.log(x1) // console.log(x2) // console.log(options) // return JSON.stringify( // x1.reduce((prev, next) =&gt; { // if (!prev.hasOwnProperty(next.prop)) { // prev[next.prop] = '' // } // return prev // }, {}) // ) // }) plop.setHelper('ifInput', function (x1, x2, options) { if (x2.type == 'input') { return options.fn(this) } else { return options.inverse(this) } }) plop.setHelper('ifSelect', function (x1, x2, options) { if (x2.type == 'select') { return options.fn(this) } else { return options.inverse(this) } }) plop.setHelper('ifDate', function (x1, x2, options) { if (x2.type == 'date') { return options.fn(this) } else { return options.inverse(this) } }) plop.setHelper('ifSwitch', function (x1, x2, options) { if (x2.type == 'switch') { return options.fn(this) } else { return options.inverse(this) } }) setTimeout(() =&gt; { transformTemplate() }, 2000) // plop.setGenerator('curd', curdGenerator) // plop.setGenerator('component', componentGenerator) // plop.setGenerator('mock&amp;api', mockGenerator) // plop.setGenerator('vuex', vuexGenerator) } </code></pre> <p><img src="https://www.showdoc.com.cn/server/api/attachment/visitfile/sign/b9b9e4d69d0d3b5fee8fbdfce395bf05" alt="" /></p> <p>//prompt.js</p> <pre><code class="language-javascript">let configs = require('../../configs') function createArray(arr, type) { return arr .filter((a) =&gt; a.parentId) .map((item) =&gt; { return { type: 'add', path: `src/views/${item.moduleName}/${type}.vue`, templateFile: `./templates/view/${type}.hbs`, skipIfExists: true, data: { name: item.moduleName, formItems: item.formItems ? item.formItems : [], columns: item.columns ? item.columns : [], }, } }) } function fillArray(arr) { return arr.reduce((prev, next) =&gt; { let obj = {} if (!next.parentId) { prev.push({ path: next.path, title: next.title, id: next.id, name: next.moduleName, parentId: null, children: [], component: 'Layout', }) } else { let index = prev.findIndex((item) =&gt; item.id === next.parentId) if (index &gt; -1) { prev[index]['children'].push({ path: next.path, title: next.title, id: next.id, name: next.moduleName, parentId: next.parentId, component: next.component, }) } } return prev }, []) } module.exports = { description: '创建view', prompts: [], actions: () =&gt; { //生成列表页 let index = createArray(configs.views, 'index') // let index = configs.views // .filter((a) =&gt; a.parentId) // .map((item) =&gt; { // return { // type: 'add', // path: `src/views/${item.moduleName}/index.vue`, // templateFile: './templates/view/index.hbs', // skipIfExists: true, // data: { // name: item.moduleName, // formItems: item.formItems ? item.formItems : [], // columns: item.columns ? item.columns : [], // }, // } // }) ////生成编辑页 // let edit = configs.views // .filter((a) =&gt; a.parentId) // .map((item) =&gt; { // return { // type: 'add', // path: `src/views/${item.moduleName}/edit.vue`, // templateFile: './templates/view/edit.hbs', // skipIfExists: true, // data: { // name: item.moduleName, // }, // } // }) let edit = createArray(configs.views, 'edit') //生成路由配置文件 let createRoute = { type: 'add', path: `src/router/routerTest/index.js`, templateFile: './templates/router/index.hbs', skipIfExists: true, data: { routers: fillArray(configs.views), }, } //生成 mock api 文件 let controller = configs.views.map((item) =&gt; { return { type: 'add', path: `mock/controller/${item.moduleName}.js`, templateFile: './templates/mock/index.hbs', data: { name: item.moduleName, columns: item.columns, form: item.formItems, }, } }) let api = configs.views.map((item) =&gt; { return { type: 'add', path: `src/api/testApi/${item.moduleName}.js`, templateFile: './templates/api/index.hbs', data: { name: item.moduleName }, } }) return [...index, ...edit, createRoute, ...controller, ...api] }, } </code></pre> <p>//生成的 页面的模板</p> <ol> <li>views/index.hbs</li> </ol> <pre><code class="language-javascript"> &lt;template&gt; &lt;div class="{{ dashCase name }}-container"&gt; &lt;!-- 查询表单 --&gt; &lt;el-form :inline="true" ref="form" :model="form"&gt; {{#each formItems}} &lt;el-form-item label="{{label}}" prop="{{prop}}"&gt;      {{#ifInput ...}} &lt;el-input v-model="form.{{prop}}" placeholder="请输入{{label}}" &gt;&lt;/el-input&gt;      {{else}} {{#ifSelect ...}} &lt;el-select v-model="form.{{prop}}" placeholder="请选择"&gt; &lt;el-option v-for="item in [ { label: '待结算', value: 0 }, { label: '已结算', value: 1 }, ]" :key="item.value" :label="item.label" :value="item.value" &gt;&lt;/el-option&gt; &lt;/el-select&gt; {{else}} {{#ifDate}} &lt;el-date-picker type="date" placeholder="选择{{label}}" v-model="form.{{prop}}" style="width: 100%;"&gt;&lt;/el-date-picker&gt; {{else}} {{#ifSwitch}} &lt;el-switch v-model="form.{{prop}}"&gt;&lt;/el-switch&gt; {{else}} {{/ifSwitch}} {{/ifDate}} {{/ifSelect}}     {{/ifInput}} &lt;/el-form-item&gt; {{/each}} &lt;el-form-item&gt; &lt;el-button type="primary" icon="el-icon-search" @click="search"&gt; 查询 &lt;/el-button&gt; &lt;el-button plain @click="reset" icon="el-icon-refresh"&gt; 重置 &lt;/el-button&gt; &lt;/el-form-item&gt; &lt;/el-form&gt; &lt;!-- 查询表单 --&gt; &lt;!-- 列表组件 --&gt; &lt;DyTable ref="myDyTable" :tableListeners="tableListeners" :tableConfig="tableConfig" :columns="columns" :url="url" &gt; &lt;template v-slot:control="{ row }"&gt; &lt;el-button type="text" @click.stop="handlerControl('edit', row)"&gt; 修改 &lt;/el-button&gt; &lt;el-button type="text" class="danger Line" @click.stop="deleteCost(row)" &gt; 删除 &lt;/el-button&gt; &lt;/template&gt; &lt;/DyTable&gt; &lt;/div&gt; &lt;/template&gt; &lt;scriptTemplate&gt; import {getList,doEdit,doDelete} from '@/api/testApi/{{properCase name}}.js' export default { name:'{{ properCase name }}', components: {}, data() { return { form:{ {{#each formItems}} {{#if prop}} '{{prop}}':'', {{/if}} {{/each}} }, url:'/{{ properCase name }}/getList',//获取表格数据 columns:[{{#each columns}} { {{#if type}} type:'{{type}}', {{/if}} {{#if label}} label:'{{label}}', {{/if}} {{#if prop}} prop:'{{prop}}', {{/if}} {{#if slot}} slot:'{{slot}}', {{/if}} {{#if action}} action:'{{action}}' {{/if}} }, {{/each}}], tableConfig: { // Dytable配置 'key': 'myDyTable', 'row-key': 'id', }, tableListeners: { // Dytable监听事件 'select': (selection, row) =&gt; { }, 'select-all': (selection) =&gt; { }, 'row-click': (row, column, event) =&gt; { }, }, } }, created() {}, mounted() {}, methods: { //重置 reset() { this.$refs['form'].resetFields(); this.search(); }, //删除 deleteCost(row){ this.$baseConfirm( '确定删除吗?', '提示', () =&gt; { try { doDelete({id:row.id}).then(res=&gt;{ this.$refs.myDyTable.deleteOne(row) return this.$message.success('删除成功') }) } catch (error) { return this.$message.error(error) } }, () =&gt; {} ) }, //表单查询 search(){ const parames={...this.form} this.$refs.myDyTable.fetchTable(parames) } }, handlerControl(type,row={}){ if(type==='add'){ //新增 this.$router.push({ path:'{{ properCase name }}/edit', }) }else{//编辑 this.$router.push({ path:'{{ properCase name }}/edit', query:{ id:row.id } }) } } } &lt;/scriptTemplate&gt; </code></pre> <p>2: 路由文件配置数据 router/index.hbs</p> <pre><code class="language-javascript"> const list= [ {{#each routers }} { name: '{{name}}', id: '{{id}}', path: '{{path}}', component: '{{component}}', parentId: '{{parentId}}', meta: { title: '{{title}}', icon: 'archive-line', }, children:[ {{#each children}} { name: '{{name}}', id: '{{id}}', path: '{{path}}', component: '{{component}}', parentId: '{{parentId}}', meta: { title: '{{title}}', icon: 'archive-line', }, }, {{/each}} ] }, {{/each}} ] export default list;</code></pre> <p>3: mock/index.hbs mock 数据模板</p> <pre><code class="language-javascript">const { mock } = require('mockjs') const List = [] const count = 50; let props={}; {{#each columns}} {{#if prop}} {{#if mock}} props['{{prop}}']='{{mock}}' {{/if}} {{/if}} {{/each}} for (let i = 0; i &lt; count; i++) { List.push(mock(props)) } module.exports = [ { url: '/{{name}}/getList', type: 'get', response: (config) =&gt; { const { name,password, pageNo = 1, pageSize = 20 } = config.query let mockList = List.filter((item) =&gt; { return !(name &amp;&amp; item.name.indexOf(name) &lt; 0 || password &amp;&amp; item.password.indexOf(password) &lt; 0) }) const list = mockList.filter( (item, index) =&gt; index &lt; pageSize * pageNo &amp;&amp; index &gt;= pageSize * (pageNo - 1) ) return { code: 200, msg: 'success', data: { list, ...{ total: mockList.length } }, } }, }, { url: '/{{name}}/doEdit', type: 'post', response: () =&gt; { return { code: 200, msg: '模拟保存成功', } }, }, { url: '/{{name}}/doDelete', type: 'post', response: () =&gt; { return { code: 200, msg: '模拟删除成功', } }, }, ] </code></pre>

页面列表

ITEM_HTML