我很烦
我的上一篇文章LowCode + 团队组件设计规范 = 灵光一闪 ?提到过,我有规范化标准化生产业务基础组件的想法。每次写这样一个组件差异也不是很大,每次都要有同样的 api
,同样的 props
,写多了就产生了厌烦。
没错,我就是一个很容易厌倦的工程师。好烦哦~
厌倦了怎么办呢,想办法解决啊。
没错,虽然我是一个很容易厌倦的工程师,但是我还是有这该死的责任感。好烦哦~
用技术手段,用可视化界面,去产生那些没啥营养的代码。
啊,我这该死的无处安放的魅力与中二气息。好烦哦,我好喜欢我自己「🐶 狗头」
所以,开搞开搞,整个编码过程大约一个小时,比较简单~
一小时编码
网络异常,图片无法展示
|
整体的思路就很简单:
网络异常,图片无法展示
|
在页面进行操作后生成中间数据,之后通过中间数据生成代码。下面我分别介绍 Form 和 Table 我分别写了什么。
Form
网络异常,图片无法展示
|
props:
- disabled
- disabledFileds
methods:
- getData
- setData
- clearData
- validate
- clearValidate
数据结构:
Array.<{ isInline: Boolean, label: String, key: String, type: String, required: Boolean }>
作为表单要包含所有常见表单项:
typeoOtions: [{ type: "RADIO", },{ type: "CHECKBOX", },{ type: "INPUT" }, { type: "INPUTNUMBER" }, { type: "SELECT" },{ type: "CASCADER" },{ type: "SWITCH" }, { type: "TIMEPICKER" }, { type: "DATEPICKER" }, { type: "DATETIMEPICKER" }, { type: "RATE" }, { type: "CUSTMER" } ],
生成代码的工具方法:
const optionTypes = [ 'RADIO', 'CHECKBOX', 'SELECT', 'CASCADER', ]; const getFormItem = (schemaItem) => { switch (schemaItem.type) { case 'RADIO': return `<q-radio-group v-model="formData.${schemaItem.key}"> <q-radio v-for=“(item, index) in ${schemaItem.key}Options” :key="index" :label="item.value" :disabled="disabledFields.includes('${schemaItem.key}')" >{{ item.label }}</q-radio> </q-radio-group>`; case "CHECKBOX": return `<q-checkbox-group v-model="formData.${schemaItem.key}"> <q-checkbox v-for=“(item, index) in ${schemaItem.key}Options” :key="index" :label="item.value" :disabled="disabledFields.includes('${schemaItem.key}')" >{{ item.label }}</q-checkbox> </q-checkbox-group>`; case 'INPUT': return `<q-input v-model="formData.${schemaItem.key}" :placeholder="请输入${schemaItem.label}" :disabled="disabledFields.includes('${schemaItem.key}')" />` case 'INPUTNUMBER': return `<q-input-number v-model="formData.${schemaItem.key}" :disabled="disabledFields.includes('${schemaItem.key}')" />`; case 'SELECT': return `<q-select v-model="formData.${schemaItem.key}" placeholder="请选择${schemaItem.label}" :disabled="disabledFields.includes('${schemaItem.key}')"> <q-option v-for=“(item, index) in ${schemaItem.key}Options” :key="index" :label="item.label" :value="item.value"> </q-option> </q-select> `; case 'CASCADER': return `<q-cascader v-model="formData.${schemaItem.key}" :options="${schemaItem.key}Options" :disabled="disabledFields.includes('${schemaItem.key}')" />`; case 'SWITCH': return `<q-switch v-model="formData.${schemaItem.key}" :disabled="disabledFields.includes('${schemaItem.key}')" />`; case 'TIMEPICKER': return `<q-time-select placeholder="请选择${schemaItem.label}" v-model="formData.${schemaItem.key}" :disabled="disabledFields.includes('${schemaItem.key}')" />` case 'DATEPICKER': return `<q-date-picker type="date" placeholder="请选择${schemaItem.label}" v-model="formData.${schemaItem.key}" :disabled="disabledFields.includes('${schemaItem.key}')" />`; case 'DATETIMEPICKER': return `<q-date-picker type="datetime" placeholder="请选择${schemaItem.label}" v-model="formData.${schemaItem.key}" :disabled="disabledFields.includes('${schemaItem.key}')" />`; case 'RATE': return `<q-rate v-model="formData.${schemaItem.key}" :disabled="disabledFields.includes('${schemaItem.key}')" />`; case 'CUSTMER': default: return `<!-- dom: v-model=“formData.${schemaItem.key}” -->`; } }; export const getFormCode = (schema) => { return `<template> <q-form ref="form" :model="formData" :rules="rules" :disabled="disabled" > ${ schema.map(item => `<q-form-item label="${item.label}" prop="${item.key}" ${item.isInline?'class="inline-form-item"':''}> ${getFormItem(item)} </q-form-item>`).join('\n') } </q-form> </template> <script> const getBaseCustomFormData = () => ({ ${ schema.map(item => `${item.key}: null`).join(',\n') } }) export default { props: { disabled: { type: Boolean, default: false }, // Array.<String> disabledFields: { type: Array, default: () => [] } }, data() { return { formData: getBaseCustomFormData(), ${ schema.filter(item => optionTypes.includes(item.type)).map(item => `${item.key}Options: []`).join(',\n') }, rules: { ${ schema.filter(item => item.required).map(item => ` ${item.key}: [ { required: true, message: '请输入${item.label}', trigger: 'blur' } ] `).join(',\n') } }, }; }, methods: { setData(data) { this.formData = Object.assign(getBaseCustomFormData(), data); }, getData() { return Object.assign({}, this.formData); }, clearData() { this.formData = getBaseCustomFormData(); }, validate() { return this.$refs.form.validate(); }, clearValidate () { this.$refs.form.clearValidate(); }, } }; </script> <style lang="scss" scoped> .inline-form-item { display: inline-block; width: 50%; vertical-align: top; } </style> ` }
Table
网络异常,图片无法展示
|
props:
- filter
- selectable
methods:
- reload
- gotoFirstPage
- getSelectionInfo
- setSelectionInfo
event:
- selectionChange
数据结构:
Array.<{ type: 'normal'|'selection', prop: String, title: String, isCustmer: Boolean }>
生成代码的工具方法:
const getTableColumn = (schemaItem) => { if(schemaItem.type == 'selection') { return `<pro-column type="selection" :selectable="selectable" :enable-cross-page-selection="false" />`; } else if(schemaItem.isCustmer) { return `<pro-column prop="${schemaItem.prop}" title="${schemaItem.title}"> <template #default="{ row }"> {{ row.${schemaItem.prop} }} </template> </pro-column>`; } else { return `<pro-column prop="${schemaItem.prop}" title="${schemaItem.title}" />`; } }; export const getTableCode = (schema) => { return `<template> <pro-table ref="table" :pagination-options="PAGE_OPTIONS" :fetch-data="fetchData" @selection-change="selectionChange" > ${ schema.map(item => `${getTableColumn(item)}`).join('\n') } <pro-column v-if="$slots.operation || $scopedSlots.operation" title="操作" prop="operation" > <template #default="{ row }"> <slot name="operation" :row="row" /> </template> </pro-column> </pro-table> </template> <script> const PAGE_OPTIONS = { defaultPageSize: 20, pageSizeOptions: [10, 20, 50, 100], hideOnSinglePage: false, }; export default { props: { filter: { type: Object, default: null, }, ${ schema[0]?.type == 'selection'? `selectable: { type: Function, default: () => true }`: '' } }, watch: { filter: { deep: true, handler() { this.reload(); }, }, }, data() { return { PAGE_OPTIONS, }; }, methods: { async fetchData({ pagination }) { try { } catch (err) { this.$message.error("获取列表失败"); return { total: 0, items: [], }; } }, selectionChange({selectedRows,isAll,exceptedRows}) { this.$emit('selectionChange', {selectedRows,isAll,exceptedRows}); }, reload() { this.$refs.table.reload(); }, gotoFirstPage() { this.$refs.table.gotoFirstPage(true); }, getSelectionInfo() { return this.$refs.table.getSelectionInfo(); }, setSelectionInfo({ selectedRows, isAll, exceptedRows }) { this.$refs.table.setSelectionInfo({ selectedRows, isAll, exceptedRows }); } }, }; </script> `; }
说不出再见
网络异常,图片无法展示
|
整片文章难度不高,但是可以提升自己的开发效率,就像我在我之前的年终总结「寒草呈献」我的肩上是风,风上是闪烁的星群✨|致直面焦虑与本心的 2021所说的,我们无法避免工作中存在重复,但是我们可以想办法去避免重复的劳作,使自己摆脱西西弗斯式的工作。
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
君不见,黄河之水天上来,奔流到海不复回。
君不见,高堂明镜悲白发,朝如青丝暮成雪。
人生得意须尽欢,莫使金樽空对月。
天生我材必有用,千金散尽还复来。
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
下一篇文章再会~