12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820 |
- ---
- description: cl-form 组件示例
- globs: *.tsx, *.ts, *.vue
- ---
- ## 层级显示 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>children</el-tag>
- <span>层级显示</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/children.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form"></cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '层级显示',
- items: [
- {
- label: '姓名',
- prop: 'name',
- component: {
- name: 'el-input'
- }
- },
- {
- label: '年龄',
- prop: 'age',
- value: 18,
- component: {
- name: 'el-input-number'
- }
- },
- // 基础信息
- {
- component: {
- //【很重要】使用 cl-form-card 组件渲染,也可以使用自定义
- name: 'cl-form-card',
- props: {
- // 标题
- label: '基础信息',
- // 是否展开,默认 true
- expand: true
- }
- },
- children: [
- {
- label: '账号',
- prop: 'account',
- component: {
- name: 'el-input'
- }
- },
- {
- label: '密码',
- prop: 'password',
- component: {
- name: 'el-input'
- }
- }
- ]
- },
- // 其他信息
- {
- component: {
- name: 'cl-form-card',
- props: {
- label: '其他信息',
- expand: false
- }
- },
- children: [
- {
- label: '身份证',
- prop: 'idcard',
- component: {
- name: 'el-input'
- }
- },
- {
- label: '学校',
- prop: 'school',
- component: {
- name: 'el-input'
- }
- },
- {
- label: '专业',
- prop: 'major',
- component: {
- name: 'el-input'
- }
- }
- ]
- }
- ],
- on: {
- submit(data, { close }) {
- close();
- }
- }
- });
- }
- </script>
- ```
- ## 组件渲染 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>component</el-tag>
- <span>组件渲染</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code
- :files="[
- 'form/component/index.vue',
- 'form/component/select-labels.vue',
- 'form/component/select-status.vue',
- 'form/component/select-work.vue',
- 'form/component/select-work2.vue'
- ]"
- />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form">
- <!-- 年龄插槽 -->
- <template #slot-age="{ scope }">
- <!-- scope 为表单值 -->
- <el-input-number v-model="scope.age" :min="18" :max="100"></el-input-number>
- </template>
- </cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- import { ElMessage } from 'element-plus';
- import SelectWork from './select-work2.vue';
- import SelectLabels from './select-labels.vue';
- import SelectStatus from './select-status.vue';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '组件配置',
- items: [
- {
- label: '昵称',
- prop: 'name',
- // 组件配置方式1:标签名(方便,但是不建议组件全局注册)
- value: '神仙',
- component: {
- // 必须是“全局注册”的组件名,如 element-plus 的 el-input、el-date-picker 等
- name: 'el-input'
- }
- },
- {
- label: '手机号',
- prop: 'phone',
- value: '13255022000',
- component: {
- name: 'el-input',
- // 自定义插槽
- slots: {
- prepend() {
- return '+86';
- }
- }
- }
- },
- {
- label: '年龄',
- prop: 'age',
- // 组件配置方式2:插槽(万能,就是代码多写点)
- value: 18,
- component: {
- // 必须是 "slot-" 开头
- name: 'slot-age'
- }
- },
- // -- start 组件配置方式3:组件实例(不想全局注册,但又想组件化)
- {
- label: '工作',
- prop: 'work',
- value: '设计',
- component: {
- // 双向绑定
- vm: SelectWork
- }
- },
- {
- label: '标签',
- prop: 'labels',
- value: ['多金', '深情'],
- component: {
- // scope[prop]绑定
- vm: SelectLabels
- }
- },
- {
- label: '状态',
- prop: 'status',
- value: 1,
- component: {
- // useForm 绑定
- vm: SelectStatus
- }
- }
- // -- end
- ],
- on: {
- submit(data, { close }) {
- ElMessage.info(
- `${data.name || '无名'}(${data.age || 18}岁)工作:${data.work || '无'}`
- );
- close();
- }
- }
- });
- }
- </script>
- ```
- ## select-labels 示例
- ```vue
- <template>
- <!--【很重要】直接绑定表单值 scope[prop] -->
- <!-- !符号,只是为了类型提示不错误 -->
- <el-select v-model="scope[prop!]" multiple>
- <el-option
- v-for="(item, index) in list"
- :key="index"
- :label="item.label"
- :value="item.label"
- />
- </el-select>
- </template>
- <!--【很重要】必须要有name,避免注册后和其他冲突 -->
- <script setup lang="ts">
- defineOptions({
- name: 'select-labels'
- });
- import { ref } from 'vue';
- const props = defineProps({
- scope: null, // 表单值
- prop: String // 表单项配置的 prop
- });
- // 选项列表
- const list = ref<{ label: string; value: string }[]>([
- {
- label: '帅气',
- value: '帅气' // 测试直接使用label,真实情况可能是1,2,3,4或者id
- },
- {
- label: '多金',
- value: '多金'
- },
- {
- label: '深情',
- value: '深情'
- }
- ]);
- </script>
- ```
- ## select-status 示例
- ```vue
- <template>
- <!--【很重要】直接绑定status,或者使用 form[prop!] -->
- <el-radio-group v-model="form.status">
- <el-radio v-for="(item, index) in list" :key="index" :value="item.value">
- {{ item.label }}
- </el-radio>
- </el-radio-group>
- </template>
- <!--【很重要】必须要有name,避免注册后和其他冲突 -->
- <script setup lang="ts">
- defineOptions({
- name: 'select-status'
- });
- import { useForm } from '@cool-vue/crud';
- import { computed, ref } from 'vue';
- const props = defineProps({
- scope: null, // 表单值
- prop: String // 表单项配置的 prop
- });
- // 使用 useForm,能直接获取到上级的表单实例,
- // 比如操作表单的 Form.value?.submit、Form.value?.close等
- // 获取表单值,Form.value?.form
- const Form = useForm();
- // 表单值,包一层不会太难受
- const form = computed(() => Form.value?.form || {});
- // 选项列表
- const list = ref<{ label: string; value: number }[]>([
- {
- label: '很好',
- value: 1
- },
- {
- label: '不舒服',
- value: 2
- },
- {
- label: '要嘎了',
- value: 3
- }
- ]);
- </script>
- ```
- ## select-work 示例
- ```vue
- <template>
- <el-select v-model="active" @change="onChange">
- <el-option
- v-for="(item, index) in list"
- :key="index"
- :label="item.label"
- :value="item.label"
- />
- </el-select>
- </template>
- <!-- 【很重要】必须要有name,避免注册后和其他冲突 -->
- <script setup lang="ts">
- defineOptions({
- name: 'select-work'
- });
- import { ref, watch } from 'vue';
- const props = defineProps({
- modelValue: String
- });
- const emit = defineEmits(['update:modelValue', 'change']);
- //【很重要】绑定值
- // 这种方式虽然麻烦,但是可扩展性高,一些复杂的数据结构可以按这种方式绑定值
- const active = ref();
- // 选项列表
- const list = ref<{ label: string; value: string }[]>([
- {
- label: '倒茶',
- value: '倒茶' // 测试直接使用label,真实情况可能是1,2,3,4或者id
- },
- {
- label: '设计',
- value: '设计'
- },
- {
- label: '开发',
- value: '开发'
- }
- ]);
- //【很重要】更新绑定值,表单提交才能得到选择后的
- function onChange(val: string) {
- emit('update:modelValue', val);
- emit('change', val);
- }
- //【很重要】使用监听的方式,避免表单打开数据是异步获取的情况
- watch(
- () => props.modelValue,
- val => {
- // 设置选中的值
- active.value = val;
- },
- {
- immediate: true
- }
- );
- </script>
- ```
- ## select-work2 示例
- ```vue
- <template>
- <el-select v-model="active">
- <el-option
- v-for="(item, index) in list"
- :key="index"
- :label="item.label"
- :value="item.label"
- />
- </el-select>
- </template>
- <!-- 【很重要】必须要有name,避免注册后和其他冲突 -->
- <script setup lang="ts">
- defineOptions({
- name: 'select-work2'
- });
- import { ref, useModel } from 'vue';
- const props = defineProps({
- modelValue: String
- });
- //【很重要】绑定值,使用 useModel 的方式双向绑定
- const active = useModel(props, 'modelValue');
- // 选项列表
- const list = ref<{ label: string; value: string }[]>([
- {
- label: '倒茶',
- value: '倒茶' // 测试直接使用label,真实情况可能是1,2,3,4或者id
- },
- {
- label: '设计',
- value: '设计'
- },
- {
- label: '开发',
- value: '开发'
- }
- ]);
- </script>
- ```
- ## 参数配置 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>config</el-tag>
- <span>参数配置</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/config.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form">
- <!-- 按钮插槽 -->
- <template #slot-btns>
- <el-button type="danger">按钮插槽</el-button>
- </template>
- </cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- import { ElMessage } from 'element-plus';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '参数配置',
- // 打开是否重置表单
- isReset: false,
- // 默认表单值
- form: {
- nickName: '神仙都没用'
- },
- // 表单配置
- props: {
- // 标签宽度
- labelWidth: '120px',
- // 标签位置
- labelPosition: 'top'
- },
- // 窗口的高。配置后,在窗口内部滚动。默认整个页面滚动
- height: '60vh',
- // 窗口的宽,默认 50%
- width: '60%',
- // 窗口设置
- dialog: {
- // 是否隐藏头部
- hideHeader: false,
- // 顶部操作按钮,默认["fullscreen", "close"]
- // fullscreen 全屏
- // close 关闭
- controls: ['close']
- },
- // 底部操作按钮
- op: {
- // 默认靠右布局
- justify: 'flex-end',
- // 保存按钮文字
- saveButtonText: '提交',
- // 关闭按钮文字
- closeButtonText: '关闭',
- // 是否隐藏
- hidden: false,
- // 按钮配置
- buttons: [
- // 自定义
- {
- label: '自定义按钮',
- onClick() {
- ElMessage.success('自定义按钮点击');
- }
- },
- // close 关闭
- 'close',
- // save 保存
- 'save',
- // 插槽使用,配合 template,往上看 cl-form 组件
- 'slot-btns'
- ]
- },
- // 表单项配置
- items: [
- {
- label: '昵称',
- prop: 'nickName',
- component: {
- name: 'el-input'
- }
- }
- ],
- // 事件
- on: {
- submit(data, { close }) {
- close();
- }
- }
- });
- }
- </script>
- ```
- ## 内嵌CRUD 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>crud</el-tag>
- <span>内嵌CRUD</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/crud.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form">
- <template #slot-crud>
- <cl-crud ref="Crud" border>
- <cl-row>
- <!-- 刷新按钮 -->
- <cl-refresh-btn />
- <!-- 新增按钮 -->
- <cl-add-btn />
- <!-- 删除按钮 -->
- <cl-multi-delete-btn />
- <cl-flex1 />
- <!-- 关键字搜索 -->
- <cl-search-key placeholder="搜索姓名、手机号" />
- </cl-row>
- <cl-row>
- <!-- 数据表格 -->
- <cl-table ref="Table" />
- </cl-row>
- <cl-row>
- <cl-flex1 />
- <!-- 分页控件 -->
- <cl-pagination />
- </cl-row>
- <!-- 新增、编辑 -->
- <cl-upsert ref="Upsert" />
- </cl-crud>
- </template>
- </cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useCrud, useForm, useTable, useUpsert } from '@cool-vue/crud';
- // cl-upsert
- const Upsert = useUpsert({
- items: [
- {
- label: '姓名',
- prop: 'name',
- component: {
- name: 'el-input'
- }
- },
- {
- label: '创建时间',
- prop: 'createTime',
- component: {
- name: 'el-date-picker'
- }
- }
- ]
- });
- // cl-table
- const Table = useTable({
- autoHeight: false,
- columns: [
- {
- type: 'selection'
- },
- {
- label: '姓名',
- prop: 'name',
- minWidth: 140
- },
- {
- label: '手机号',
- prop: 'phone',
- minWidth: 140
- },
- {
- type: 'op'
- }
- ]
- });
- // cl-crud
- const Crud = useCrud(
- {
- service: 'test'
- },
- app => {
- app.refresh({
- size: 10
- });
- }
- );
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '内嵌CRUD',
- props: {
- labelPosition: 'top'
- },
- dialog: {
- height: '70vh',
- width: '1000px'
- },
- items: [
- {
- label: '姓名',
- prop: 'name',
- component: {
- name: 'el-input',
- props: {
- placeholder: '请填写姓名'
- }
- },
- rules: {
- required: true,
- message: '姓名不能为空'
- }
- },
- {
- label: '内嵌 cl-crud',
- component: {
- name: 'slot-crud'
- }
- }
- ],
- on: {
- submit() {
- Form.value?.close();
- }
- }
- });
- }
- </script>
- ```
- ## 组件禁用 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>disabled</el-tag>
- <span>组件禁用</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/disabled.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form"></cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '组件禁用',
- items: [
- {
- label: '账号',
- prop: 'account',
- component: {
- name: 'el-input',
- props: {
- // 设置 boolean 值控制组件的禁用状态(前提是组件支持这个参数,element 的组件几乎都有)
- disabled: true
- }
- }
- },
- {
- label: '密码',
- prop: 'password',
- component: {
- name: 'el-input'
- }
- }
- ],
- on: {
- open() {
- // 通用 setProps 方法去设置 disabled, 1.5s后禁用
- setTimeout(() => {
- Form.value?.setProps('password', { disabled: true });
- }, 1500);
- },
- submit(data, { close }) {
- close();
- }
- }
- });
- }
- </script>
- ```
- ## 组件事件 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>event</el-tag>
- <span>组件事件</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/event.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form"></cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- import { ElMessage } from 'element-plus';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '组件事件',
- items: [
- {
- label: '账号',
- prop: 'account',
- component: {
- name: 'el-input',
- props: {
- // 组件内 emit 的用 on[name] 接收,如 onChange、onInput、onBlur 等
- // 前提是组件内有触发事件
- onBlur() {
- ElMessage.info('账号检查中');
- }
- }
- }
- },
- {
- label: '是否实名',
- prop: 'status',
- value: 1,
- component: {
- name: 'el-radio-group',
- options: [
- {
- label: '关闭',
- value: 0
- },
- {
- label: '开启',
- value: 1
- }
- ],
- props: {
- // 值改变事件
- onChange(val: number) {
- if (val == 1) {
- // 显示表单项
- Form.value?.showItem('idcard');
- } else {
- // 隐藏表单项
- Form.value?.hideItem('idcard');
- // 清空值
- Form.value?.setForm('idcard', undefined);
- }
- }
- }
- }
- },
- {
- label: '身份证',
- prop: 'idcard',
- component: {
- name: 'el-input'
- }
- }
- ],
- on: {
- submit(data, { close }) {
- close();
- }
- }
- });
- }
- </script>
- ```
- ## 分组显示 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>group</el-tag>
- <span>分组显示</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/group.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form"></cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '分组显示',
- items: [
- {
- //【很重要】必须为 tabs
- type: 'tabs',
- props: {
- // 分组样式
- type: 'card',
- // 分组列表,必须是 { label, value } 的数组格式
- labels: [
- {
- label: '基础信息', // 标题
- value: 'base' // 唯一标识
- },
- {
- label: '认证信息',
- value: 'auth'
- }
- ]
- }
- },
- // 基础信息
- {
- group: 'base', // 标识
- label: '账号',
- prop: 'account',
- required: true,
- component: {
- name: 'el-input'
- }
- },
- {
- group: 'base', // 标识
- label: '密码',
- prop: 'password',
- required: true,
- component: {
- name: 'el-input'
- }
- },
- // 其他信息 group = other
- {
- group: 'auth', // 标识
- label: '身份证',
- prop: 'idcard',
- required: true,
- component: {
- name: 'el-input'
- }
- },
- {
- group: 'auth', // 标识
- label: '学校',
- prop: 'school',
- component: {
- name: 'el-input'
- }
- },
- {
- group: 'auth', // 标识
- label: '专业',
- prop: 'major',
- component: {
- name: 'el-input'
- }
- }
- ],
- on: {
- //【提示】当第一组验证通过后,会自动切换到下一组展示,直到全部通过才可提交
- submit(data, { close }) {
- close();
- }
- }
- });
- }
- </script>
- ```
- ## 隐藏/显示 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>hidden</el-tag>
- <span>隐藏/显示</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/hidden.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form"></cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '隐藏/显示',
- items: [
- {
- label: '状态',
- prop: 'status',
- value: 0,
- component: {
- name: 'el-radio-group',
- options: [
- {
- label: '关闭',
- value: 0
- },
- {
- label: '开启',
- value: 1
- }
- ]
- }
- },
- {
- label: '账号',
- prop: 'account',
- component: {
- name: 'el-input'
- }
- },
- {
- //【很重要】是否隐藏
- hidden({ scope }) {
- // scope 为表单值
- // 返回一个 boolean 来控制当前表单项的隐藏/显示
- return scope.status != 1;
- },
- label: '密码',
- prop: 'password',
- component: {
- name: 'el-input'
- }
- }
- ],
- on: {
- submit(data, { close }) {
- close();
- }
- }
- });
- }
- </script>
- ```
- ## 布局 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>layout</el-tag>
- <span>布局</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/layout.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form"></cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '布局',
- items: [
- {
- //【span】参考文档:https://element-plus.gitee.io/zh-CN/component/layout.html
- // 使用 1/24 分栏,默认 24
- span: 12,
- label: '昵称',
- prop: 'nickname',
- component: {
- name: 'el-input'
- }
- },
- {
- span: 12,
- label: '手机号',
- prop: 'phone',
- component: {
- name: 'el-input',
- props: {
- maxlength: 11
- }
- }
- },
- {
- //【flex】使宽度不填充满
- flex: false,
- label: '标签',
- prop: 'label',
- component: {
- name: 'el-input'
- }
- },
- {
- label: '状态',
- prop: 'status',
- value: 1,
- component: {
- name: 'el-radio-group',
- options: [
- {
- label: '开启',
- value: 1
- },
- {
- label: '关闭',
- value: 0
- }
- ]
- }
- },
- {
- label: '备注',
- prop: 'remark',
- component: {
- name: 'el-input',
- props: {
- type: 'textarea',
- rows: 4
- }
- }
- }
- ],
- on: {
- submit(data, { close }) {
- close();
- }
- }
- });
- }
- </script>
- ```
- ## 起步 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>open</el-tag>
- <span>起步</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/open.vue']" />
- <!-- 自定义表单组件 -->
- <!--【很重要】ref 一定要对应 useForm 定义的值 -->
- <cl-form ref="Form"></cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="tsx">
- import { useForm } from '@cool-vue/crud';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '起步',
- items: [
- {
- label: '昵称',
- // 绑定值的标识,表单提交及回显会自动根据 prop 获取对应的值
- prop: 'nickname',
- // 组件绑定
- component: {
- // 必须是“全局注册”的组件名,如 element-plus 的 el-input、el-date-picker 等
- name: 'el-input',
- // 绑定的组件参数配置,如 clearable、placeholder 等
- // 组件内 emit 的用 on[name] 接收,如 onChange、onInput、onBlur 等
- props: {
- placeholder: '请输入昵称',
- clearable: true,
- onChange(value: string) {}
- }
- }
- },
- {
- prop: 'age',
- component: {
- name: 'el-input-number'
- },
- // 默认值,第一次打开有效
- value: 18
- }
- ],
- on: {
- // 打开时触发
- open() {
- console.log(Form.value?.validateField);
- },
- // 关闭时触发。当配置该方法时,关闭事件会被阻断,使用 done() 关闭窗口
- close(action, done) {
- // action 为关闭窗口的触发动作 "save" | "close"
- // done 关闭事件
- done();
- },
- // 提交时触发
- submit(data, { done, close }) {
- // data 为表单值
- // done 关闭加载事件、但不关闭窗口
- // close 关闭窗口
- close();
- }
- }
- });
- }
- </script>
- ```
- ## 选项框配置 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>options</el-tag>
- <span>选项框配置</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/options.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form"></cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- import { computed, reactive } from 'vue';
- const Form = useForm();
- // 觉得麻烦就 any,如 { user: [] as any[] }
- const options = reactive<{ [key: string]: { label: string; value: any }[] }>({
- user: []
- });
- function open() {
- Form.value?.open({
- title: '选项框配置',
- items: [
- {
- label: '下拉框',
- prop: 'select',
- component: {
- name: 'el-select',
- props: {
- clearable: true // 可清除
- },
- options: [
- {
- label: 'javascript',
- value: 1
- },
- {
- label: 'vue',
- value: 2
- },
- {
- label: 'html',
- value: 3
- },
- {
- label: 'css',
- value: 4
- }
- ]
- }
- },
- {
- label: '单选框',
- prop: 'radio',
- value: 1,
- component: {
- name: 'el-radio-group',
- options: [
- {
- label: '手机',
- value: 1
- },
- {
- label: '电脑',
- value: 2
- },
- {
- label: '电视',
- value: 3
- }
- ]
- }
- },
- {
- label: '多选框',
- prop: 'checkbox',
- value: [2, 3],
- component: {
- name: 'el-checkbox-group',
- options: [
- {
- label: '咖啡',
- value: 1
- },
- {
- label: '汉堡',
- value: 2
- },
- {
- label: '炸鸡',
- value: 3
- },
- {
- label: '奶茶',
- value: 4
- }
- ]
- }
- },
- {
- label: '动态配置1',
- prop: 'd1',
- component: {
- name: 'el-select',
- // 动态设置方法1,在 on.open 事件配置 options
- options: []
- }
- },
- {
- label: '动态配置2',
- prop: 'd2',
- component: {
- name: 'el-select',
- // 动态设置方法2,使用 computed 更新 options
- options: computed(() => options.user)
- }
- }
- ],
- on: {
- open() {
- // 模拟 1.5s 后取的数据
- setTimeout(() => {
- // 动态设置方法1,使用 setOptions 方法设置
- // d1 为 prop 值
- Form.value?.setOptions('d1', [
- {
- label: '😊',
- value: 1
- },
- {
- label: '😭',
- value: 2
- },
- {
- label: '😘',
- value: 3
- }
- ]);
- // 动态设置方法2,直接设置 options.user,由 computed 更新
- options.user = [
- {
- label: '💰',
- value: 1
- },
- {
- label: '🚗',
- value: 2
- }
- ];
- }, 1500);
- },
- submit(data, { close }) {
- close();
- }
- }
- });
- }
- </script>
- ```
- ## 插件的使用 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>plugin</el-tag>
- <span>插件的使用</span>
- </div>
- <div class="c">
- <el-button @click="open('manager')">管理者</el-button>
- <el-button @click="open('user')">用户</el-button>
- <demo-code :files="['form/plugin/index.vue', 'form/plugin/role.ts']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form"></cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- import { setRole } from './role';
- const Form = useForm();
- function open(role: string) {
- Form.value?.open(
- {
- title: '插件的使用',
- items: [
- {
- label: '姓名',
- prop: 'name',
- required: true,
- component: {
- name: 'el-input'
- }
- },
- {
- // 自定义参数 role,匹配插件传入的角色
- role: 'user',
- label: '面试职位',
- prop: 'work',
- value: 1,
- component: {
- name: 'el-radio-group',
- options: [
- {
- label: '前端开发',
- value: 1
- },
- {
- label: '后端开发',
- value: 2
- },
- {
- label: 'UI设计',
- value: 3
- }
- ]
- }
- },
- {
- role: 'user',
- label: '期望薪资',
- prop: 'salary',
- value: 5000,
- component: {
- name: 'el-input-number',
- props: {
- min: 2000,
- max: 100000
- }
- }
- },
- {
- role: 'manager',
- label: '入职时间',
- prop: 'date',
- component: {
- name: 'el-date-picker'
- }
- },
- {
- role: 'manager',
- label: '负责人',
- prop: 'head',
- component: {
- name: 'el-input'
- }
- }
- ],
- on: {
- submit(data, { done, close }) {
- close();
- }
- }
- },
- [
- // 自定义插件,角色权限控制
- setRole(role)
- ]
- );
- }
- </script>
- ```
- ## 必填项配置 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>required</el-tag>
- <span>必填项配置</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/required.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form"></cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '必填项配置',
- items: [
- {
- label: '昵称',
- prop: 'nickname',
- component: {
- name: 'el-input'
- },
- // 是否必填,默认判断绑定值是否空
- required: true
- },
- {
- label: '手机号',
- prop: 'phone',
- component: {
- name: 'el-input',
- props: {
- maxlength: 11
- }
- },
- // 自定义规则
- // 基础用法可参考:https://element-plus.gitee.io/zh-CN/component/form.html
- // 高级用法可参考:https://github.com/yiminghe/async-validator
- rules: [
- {
- required: true,
- validator: (rule, value, callback) => {
- if (value === '') {
- callback(new Error('手机号不能为空'));
- } else if (!/^1[3456789]\d{9}$/.test(value)) {
- callback(new Error('手机号格式错误'));
- } else {
- callback();
- }
- }
- }
- ]
- }
- ],
- on: {
- submit(data, { close }) {
- close();
- }
- }
- });
- }
- </script>
- ```
- ## 添加/删除表单项 示例
- ```vue
- <template>
- <div class="scope">
- <div class="h">
- <el-tag size="small" effect="dark" disable-transitions>rules</el-tag>
- <span>添加/删除表单项</span>
- </div>
- <div class="c">
- <el-button @click="open">预览</el-button>
- <demo-code :files="['form/rules.vue']" />
- <!-- 自定义表单组件 -->
- <cl-form ref="Form">
- <template #slot-cert="{ scope }">
- <div class="cert">
- <!--【很重要】prop、rules 配置格式如下 -->
- <el-form-item
- v-for="(item, index) in scope.cert"
- :key="index"
- :label="`证书${index + 1}`"
- :prop="`cert.${index}.label`"
- :rules="{
- message: `请填写证书${index + 1}`,
- required: true
- }"
- >
- <div class="row">
- <!-- 输入框 -->
- <el-input v-model="item.label" placeholder="请填写证书"></el-input>
- <!-- 删除行 -->
- <el-icon @click="rowDel(index)">
- <delete />
- </el-icon>
- </div>
- </el-form-item>
- <!-- 添加行 -->
- <el-row type="flex" justify="end">
- <el-button @click="rowAdd()">添加证书</el-button>
- </el-row>
- </div>
- </template>
- </cl-form>
- </div>
- <div class="f">
- <span class="date">2024-01-01</span>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { useForm } from '@cool-vue/crud';
- import { Delete } from '@element-plus/icons-vue';
- const Form = useForm();
- function open() {
- Form.value?.open({
- title: '添加/删除表单项',
- items: [
- {
- label: '昵称',
- prop: 'nickname',
- component: {
- name: 'el-input'
- },
- required: true
- },
- {
- prop: 'cert',
- //【很重要】默认数据格式,以实际业务为主。
- value: [
- {
- label: ''
- }
- ],
- component: {
- name: 'slot-cert'
- }
- }
- ],
- on: {
- submit(data, { close }) {
- close();
- }
- }
- });
- }
- function rowAdd() {
- Form.value?.form.cert.push({
- label: ''
- });
- }
- function rowDel(index: number) {
- Form.value?.form.cert.splice(index, 1);
- }
- </script>
- <style lang="scss" scoped>
- .cert {
- .row {
- display: flex;
- align-items: center;
- .el-input {
- flex: 1;
- margin-right: 10px;
- }
- .el-icon {
- cursor: pointer;
- &:hover {
- color: red;
- }
- }
- }
- }
- </style>
- ```
|