This commit is contained in:
2022-12-09 16:41:41 +08:00
parent c1cce5a7c2
commit ff7aa8774f
2003 changed files with 156639 additions and 140 deletions

View File

@@ -0,0 +1,16 @@
<script lang="ts">
export default {
name: "LeftIcon",
};
</script>
<script setup lang="ts">
import LayIcon from "../component/icon/index";
const props = defineProps<{
color?: string;
size?: string;
}>();
</script>
<template>
<lay-icon :color="props.color" :size="props.size" type="layui-icon-left" />
</template>

View File

@@ -0,0 +1,6 @@
.lay-tooltip-content{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}

View File

@@ -0,0 +1 @@
export type CheckboxSize = "lg" | "md" | "sm" | "xs";

View File

@@ -0,0 +1,4 @@
export declare const TAG_COLORS: readonly ["primary", "normal", "warm", "danger"];
export declare type TagType = typeof TAG_COLORS[number];
export declare type TagShape = "square" | "round";
export declare type TagVariant = "dark" | "light" | "plain";

View File

@@ -0,0 +1,20 @@
<script lang="ts">
export default {
name: "ScreenFullIcon",
};
</script>
<script setup lang="ts">
import LayIcon from "../component/icon/index";
const props = defineProps<{
color?: string;
size?: string;
}>();
</script>
<template>
<lay-icon
:color="props.color"
:size="props.size"
type="layui-icon-screen-full"
/>
</template>

View File

@@ -0,0 +1 @@
.layui-form-item{margin-bottom:20px;clear:both}.layui-form-item-right .layui-form-label{text-align:right}.layui-form-item-left .layui-form-label{text-align:left}.layui-form-item-top .layui-form-label{text-align:left;float:none}.layui-form-item-top>div{margin-left:0}.layui-form-item:after{content:" ";clear:both;display:block;height:0}.layui-form-label{float:left;display:block;width:95px;padding-right:15px;line-height:38px;font-weight:400}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#ff5722!important}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-required{color:#ff5722;font-size:12px;line-height:1}.layui-form .layui-form-item .layui-input-block .layui-form-danger,.layui-form .layui-form-item .layui-input-inline .layui-form-danger,.layui-form .layui-form-item .layui-input-block .layui-form-danger .layui-textarea,.layui-form .layui-form-item .layui-input-inline .layui-form-danger .layui-textarea,.layui-form .layui-form-item .layui-input-block .layui-form-danger .layui-tag-input,.layui-form .layui-form-item .layui-input-inline .layui-form-danger .layui-tag-input,.layui-form .layui-form-item .layui-input-block .layui-form-danger .layui-input,.layui-form .layui-form-item .layui-input-inline .layui-form-danger .layui-input{border-color:#ff5722!important}.layui-error-message{color:#ff5722;font-size:12px;line-height:1;padding-top:5px;position:absolute;top:100%;left:0}.layui-error-message-anim{-ms-transform-origin:0 0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-animation:layui-top-show-anim .3s ease 1;animation:layui-top-show-anim .3s ease 1}@keyframes layui-top-show-anim{0%{opacity:.3;transform:rotateX(45deg)}to{opacity:1;transform:rotateX(0)}}

View File

@@ -0,0 +1,674 @@
::: anchor
:::
::: title 基础使用
:::
::: demo
<template>
<lay-form :model="model">
<lay-form-item label="账户" prop="username">
<lay-input v-model="model.username"></lay-input>
</lay-form-item>
<lay-form-item label="密码" prop="password">
<lay-input v-model="model.password" type="password"></lay-input>
</lay-form-item>
<lay-form-item label="爱好" prop="hobby">
<lay-select v-model="model.hobby">
<lay-select-option value="1" label="学习"></lay-select-option>
<lay-select-option value="2" label="编码"></lay-select-option>
<lay-select-option value="3" label="运动"></lay-select-option>
</lay-select>
</lay-form-item>
<lay-form-item label="特长" prop="specialty">
<lay-radio v-model="model.specialty" name="specialty" value="1">写作</lay-radio>
<lay-radio v-model="model.specialty" name="specialty" value="2">画画</lay-radio>
<lay-radio v-model="model.specialty" name="specialty" value="3">编码</lay-radio>
</lay-form-item>
<lay-form-item label="描述" prop="desc">
<lay-textarea placeholder="请输入描述" v-model="model.desc"></lay-textarea>
</lay-form-item>
<lay-form-item label="时间" prop="datetime" required>
<lay-date-picker v-model="model.datetime" range type="datetime"></lay-date-picker>
</lay-form-item>
<lay-form-item>
<lay-button @click="submitClick">提交</lay-button>
</lay-form-item>
</lay-form>
</template>
<script>
import { ref, reactive } from 'vue'
import {layer} from '@layui/layer-vue'
export default {
setup() {
const model = reactive({
username: "admin",
password: "123456",
specialty: "1"
})
const submitClick = function(){
layer.open({
type: 1,
title:"表单结果",
content: `<div style="padding: 10px">${JSON.stringify(model)}</div>`,
shade: false,
isHtmlFragment: true,
btn : [{ text: '确认', callback(index) { layer.close(index) }}],
area : '500px'
});
};
return {
model,
submitClick
}
}
}
</script>
:::
::: title 对齐方式
:::
::: demo 通过设置 label-position 属性可以改变表单域标签的位置,可选值为 top、left 当设为 top 时标签会置于表单域的顶部
<template>
<lay-form :model="model">
<lay-form-item label="账户" :label-position="labelPosition" prop="username">
<lay-input v-model="model.username"></lay-input>
</lay-form-item>
<lay-form-item label="密码" :label-position="labelPosition" prop="password">
<lay-input v-model="model.password" type="password"></lay-input>
</lay-form-item>
<lay-form-item label="爱好" :label-position="labelPosition" prop="hobby">
<lay-select v-model="model.hobby">
<lay-select-option value="1" label="学习"></lay-select-option>
<lay-select-option value="2" label="编码"></lay-select-option>
<lay-select-option value="3" label="运动"></lay-select-option>
</lay-select>
</lay-form-item>
<lay-form-item label="特长" :label-position="labelPosition" prop="specialty">
<lay-radio v-model="labelPosition" name="labelPosition" value="left">左</lay-radio>
<lay-radio v-model="labelPosition" name="labelPosition" value="top">上</lay-radio>
<lay-radio v-model="labelPosition" name="labelPosition" value="right">右</lay-radio>
</lay-form-item>
<lay-form-item label="描述" :label-position="labelPosition" prop="desc">
<lay-textarea placeholder="请输入描述" v-model="model.desc"></lay-textarea>
</lay-form-item>
<lay-form-item>
<lay-button @click="submitClick">提交</lay-button>
</lay-form-item>
</lay-form>
</template>
<script>
import { ref, reactive } from 'vue'
import {layer} from '@layui/layer-vue'
export default {
setup() {
const model = reactive({
username: "admin",
password: "123456",
specialty: "1"
})
const labelPosition = ref('right');
const submitClick = function(){
layer.open({
type: 1,
title:"表单结果",
content: `<div style="padding: 10px">${JSON.stringify(model)}</div>`,
shade: false,
isHtmlFragment: true,
btn : [{ text: '确认', callback(index) { layer.close(index) }}],
area : '500px'
});
};
return {
model,
submitClick,
labelPosition
}
}
}
</script>
:::
::: title 表单验证
:::
::: demo
<template>
{{ validateModel }}
<lay-form :model="validateModel" ref="layFormRef" required>
<lay-form-item label="账户" prop="username">
<lay-input v-model="validateModel.username"></lay-input>
</lay-form-item>
<lay-form-item label="密码" prop="password">
<lay-input v-model="validateModel.password" type="password">></lay-input>
</lay-form-item>
<lay-form-item label="爱好" prop="hobby">
<lay-select v-model="validateModel.hobbys">
<lay-select-option value="1" label="学习"></lay-select-option>
<lay-select-option value="2" label="编码"></lay-select-option>
<lay-select-option value="3" label="运动"></lay-select-option>
</lay-select>
</lay-form-item>
<lay-form-item label="特长" prop="specialty">
<lay-radio v-model="validateModel.specialty" name="specialty" value="1">写作</lay-radio>
<lay-radio v-model="validateModel.specialty" name="specialty" value="2">画画</lay-radio>
<lay-radio v-model="validateModel.specialty" name="specialty" value="3">编码</lay-radio>
</lay-form-item>
<lay-form-item label="描述" prop="desc">
<lay-textarea placeholder="请输入描述" v-model="validateModel.desc"></lay-textarea>
</lay-form-item>
<lay-form-item label="文件" prop="file">
<lay-upload v-model="validateModel.file" acceptMime="image/*" :auto="false"/>
</lay-form-item>
<lay-form-item>
<lay-button @click="validate3">提交</lay-button>
<lay-button @click="clearValidate">清除校验</lay-button>
<lay-button @click="reset">重置表单</lay-button>
</lay-form-item>
</lay-form>
</template>
<script>
import { ref, reactive } from 'vue'
import {layer} from '@layui/layer-vue'
export default {
setup() {
const validateModel = reactive({
username: "",
password: "",
specialty: "1",
hobbys: "",
file: null,
})
const layFormRef = ref(null);
// 校验
const validate3= function() {
layFormRef.value.validate((isValidate, model, errors) => {
console.log(JSON.stringify(model.file))
layer.open({
type: 1,
title:"表单提交结果",
content: `<div style="padding: 10px"><p>是否通过 : ${isValidate}</p> <p>表单数据 : ${JSON.stringify(model)} </p> <p>错误信息 : ${JSON.stringify(errors)}</p></div>`,
shade: false,
isHtmlFragment: true,
btn : [{ text: '确认', callback(index) { layer.close(index) }}],
area : '500px'
});
});
}
// 清除校验
const clearValidate = function() {
layFormRef.value.clearValidate();
}
// 重置表单
const reset = function() {
layFormRef.value.reset();
validateModel.specialty = "1"
}
return {
validateModel,
layFormRef,
validate3,
clearValidate,
reset
}
}
}
</script>
:::
::: title 校验规则
:::
::: demo
<template>
<lay-form :model="ruleDemo1" ref="layFormRef1" :rules="rules" required initValidate>
<lay-form-item prop="email" requiredMessage="你得输入邮箱">
<lay-input v-model="ruleDemo1.email"></lay-input>
</lay-form-item>
<lay-form-item label="url路径" prop="url">
<lay-input v-model="ruleDemo1.url"></lay-input>
</lay-form-item>
<lay-form-item label="日期" prop="date">
<lay-input v-model="ruleDemo1.date"></lay-input>
</lay-form-item>
<lay-form-item label="用户名" prop="username">
<lay-input v-model="ruleDemo1.username"></lay-input>
</lay-form-item>
<lay-form-item label="年龄" prop="age">
<lay-input v-model="ruleDemo1.age"></lay-input>
</lay-form-item>
<lay-form-item>
<lay-button @click="validate1">提交</lay-button>
</lay-form-item>
</lay-form>
</template>
<script>
import { ref, reactive } from 'vue'
import {layer} from '@layui/layer-vue'
export default {
setup() {
const ruleDemo1 = reactive({
email: "",
url: "",
date: "",
username: "",
age: null,
})
const rules = ref({
email : {
type : 'email',
},
url : {
type : 'url'
},
date : {
type : 'date'
},
username : {
type : 'string',
min : 8,
max : 16
},
age : {
validator(rule, value, callback, source, options){
if (value < 18) {
callback(new Error(`${rule.field}太过于年轻`));
} else {
return true;
}
}
}
})
const layFormRef1 = ref(null);
// 校验
const validate1 = function() {
layFormRef1.value.validate((isValidate, model, errors) => {
layer.open({
type: 1,
title:"表单提交结果",
content: `<div style="padding: 10px"><p>是否通过 : ${isValidate}</p> <p>表单数据 : ${JSON.stringify(model)} </p> <p>错误信息 : ${JSON.stringify(errors)}</p></div>`,
shade: false,
isHtmlFragment: true,
btn : [{ text: '确认', callback(index) { layer.close(index) }}],
area : '500px'
});
});
}
return {
ruleDemo1,
layFormRef1,
validate1,
rules
}
}
}
</script>
:::
::: title 校验规则 - 通过表单子项配置
:::
::: demo
<template>
<lay-form :model="ruleDemo2" ref="layFormRef2" required initValidate>
<lay-form-item label="邮箱" prop="email" :rules="{type : 'email'}">
<lay-input v-model="ruleDemo2.email"></lay-input>
</lay-form-item>
<lay-form-item label="url路径" prop="url" :rules="{type : 'url'}">
<lay-input v-model="ruleDemo2.url"></lay-input>
</lay-form-item>
<lay-form-item label="日期" prop="date" :rules="{type : 'date'}">
<lay-input v-model="ruleDemo2.date"></lay-input>
</lay-form-item>
<lay-form-item label="用户名" prop="username"
:rules="{
type : 'string',
min : 8,
max : 16
}">
<lay-input v-model="ruleDemo2.username"></lay-input>
</lay-form-item>
<lay-form-item label="年龄" prop="age" :rules="ageRules">
<lay-input v-model="ruleDemo2.age"></lay-input>
</lay-form-item>
<lay-form-item label="自定义提示" prop="myEmail"
:rules="{
type : 'email',
message : '必须为邮箱'
}">
<lay-input v-model="ruleDemo2.myEmail"></lay-input>
</lay-form-item>
<lay-form-item>
<lay-button @click="validate2">提交</lay-button>
</lay-form-item>
</lay-form>
</template>
<script>
import { ref, reactive } from 'vue'
import {layer} from '@layui/layer-vue'
export default {
setup() {
const ruleDemo2 = reactive({
email: "",
url: "",
date: "",
username: "",
age: null,
myEmail: "",
});
const ageRules = {
validator(rule, value, callback, source, options){
if (value < 18) {
callback(new Error(`${rule.field}太过于年轻`));
return false;
}
return true;
}
};
const layFormRef2 = ref(null);
// 校验
const validate2 = function() {
layFormRef2.value.validate((isValidate, model, errors) => {
layer.open({
type: 1,
title:"表单提交结果",
content: `<div style="padding: 10px"><p>是否通过 : ${isValidate}</p> <p>表单数据 : ${JSON.stringify(model)} </p> <p>错误信息 : ${JSON.stringify(errors)}</p></div>`,
shade: false,
isHtmlFragment: true,
btn : [{ text: '确认', callback(index) { layer.close(index) }}],
area : '500px'
});
});
}
return {
ruleDemo2,
layFormRef2,
validate2,
ageRules
}
}
}
</script>
:::
::: title 原生submit方式校验 -- 校验通过将提交表单 -- 不推荐使用
:::
::: demo
<template>
<lay-form @submit="submit" :model="submitModel" requiredIcons="layui-icon-heart-fill" :use-CN="false" required>
<lay-form-item label="账户" prop="username">
<template #label>
<i class="layui-icon layui-icon-username"></i>
账户
</template>
<lay-input v-model="submitModel.username"></lay-input>
</lay-form-item>
<lay-form-item label="密码" prop="password">
<lay-input v-model="submitModel.password"></lay-input>
</lay-form-item>
<lay-form-item>
<lay-button native-type="submit">提交</lay-button>
</lay-form-item>
</lay-form>
</template>
<script>
import { ref, reactive } from 'vue'
import {layer} from '@layui/layer-vue'
export default {
setup() {
const submitModel = reactive({
username: "",
password: ""
})
const submit = function(isValidate, model, errors) {
layer.open({
type: 1,
title:"表单提交结果",
content: `<div style="padding: 10px"><p>是否通过 : ${isValidate}</p> <p>表单数据 : ${JSON.stringify(model)} </p> <p>错误信息 : </br>${JSON.stringify(errors)}</p></div>`,
shade: false,
isHtmlFragment: true,
btn : [{ text: '确认', callback(index) { layer.close(index) }}],
area : '500px'
})
}
return {
submitModel
}
}
}
</script>
:::
::: title 表单(form)属性
:::
::: table
| 属性 | 描述 | 类型 | 可选值 | 默认值 |
| ------------- | -------------------------------------------------------------- | --------- | -------------- | ------- |
| v-model | 表单绑定值 | `object` | - | {} |
| required | 是否必填 | `boolean` | `true` `false` | `false` |
| rules | 表单校验规则; <br>可查看[async-validator](https://github.com/yiminghe/async-validator) | `object` | - | - |
| initValidate | 是否一开始就校验表单 | `boolean` | `true` `false` | `false` |
| useCN | 是否使用中文错误提示 | `boolean` | `true` `false` | `false` |
| requiredIcons | 必填前缀图标`class` | `string` | - | `*` |
| required-erroer-message | 必填错误提示信息 | `string` | - | `%s不能为空`|
| validate-message | 自定义校验错误提示信息; <br>由于内置了中文错误提示,可按需求增量增加<br>可查看 [async-validator 内置错误提示](https://github.com/yiminghe/async-validator/blob/master/src/messages.ts)<br>也可参考 [layui-vue 内置中文错误提示](https://gitee.com/layui/layui-vue/blob/next/package/component/src/component/formItem/cnValidateMessage.ts) | `string` | - | `%s不能为空`|
:::
::: title 表单(form)事件
:::
::: table
| 属性 | 描述 | 回调参数 |
| ------------- | ------------------------------- | -------------- |
| submit | 提交事件`(不推荐使用)` | (`isValidate`, `model`, `errors`)<br><br> `isValidate`: (`boolean`)是否校验通过<br><br> `model`: (`object`)表单绑定的值<br><br> `errors`: (`Array`)校验结果的错误信息 |
:::
::: title 表单(form)方法
:::
::: table
| 属性 | 描述 | 入参 |
| ------------- | -------------- | -------------- |
| validate | 表单校验; <br>如果没有`callback`回调,会返回`Promise`, <br> `Promise`参数为{`isValidate`, `model`, `errors`}<br> 参数具体描述请看上面表单`submit`提交事件 | (`fields` `[可选]`, `callback` `[可选]`)<br><br> `fields`: (`string` / `string[]` / `function`)<br>单独校验的字段,<br>该字段如果为`function`, <br>则认为`callback`入参,校验全部字段;<br><br> `callback`: (`function`)校验之后的回调,<br>回调参数为(`isValidate`, `model`, `errors`)<br>参数具体描述请看上面表单`submit`提交事件|
| clearValidate | 清除表单校验 | (`fields`[可选])<br><br> `fields`: (`string` / `string[]`)<br>需要进行清除校验的表单字段, 如果该字段为空则清除全部校验|
| reset | 重置表单所有值 | - |
:::
::: title 表单项(form-item)属性
:::
::: table
| 属性 | 描述 | 类型 | 可选值 | 默认值 |
| ------------- | -------------------------------------------------------------- | --------- | -------------- | ------- |
| prop | 在表单绑定值(`model`)中字段`key` | `string` | - | - |
| label | 子项前边描述值,**尽量填写**,中文校验错误需要用到 | `string` | - | - |
| label-position| 子项前边描述值的位置 | `string` | `left` `top` `right` |`right` |
| label-width | 子项前边描述值的宽度 | `string` `number` | - | `95` |
| required | 表单必填 | `boolean` | `true` `false` | `false` |
| required-error-message | 表单必填校验失败固定提示语 | `string` | -- | -- |
| rules | 表单校验规则; <br>可查看[async-validator](https://github.com/yiminghe/async-validator) | `object` | - | - |
| error-message | 表单校验失败固定提示语 | `string` | -- | -- |
| mode | 表单项显示的模式,`块元素` / `行元素` | `string` |`block` `inline`| `block` |
:::
::: title 表单项(form-item)方法
:::
::: table
| 属性 | 描述 | 入参 |
| ------------- | -------------- | -------------- |
| validate | 表单校验; | (`callback` `[可选]`)<br><br> `callback`: (`function`)校验之后的回调,<br>回调参数为(`errors`, `fields`)<br><br> `errors`: (`Array`)校验结果的错误信息;<br><br> `fields`: (`Array`)当前校验的字段信息|
| clearValidate | 清除表单校验 | - |
:::
::: title 表单项(form-item)插槽
:::
::: table
| 属性 | 描述 | 可使用参数 |
| ------------- | ---------------------------------------------------------------- | --------------------------------------- |
| - | 默认插槽 | 传递进来的`props`和表单绑定的值(`model`) |
| label | 子项前边描述插槽<br>如果使用此插槽,`props`**尽量**也传递`label`参数 | 传递进来的`props`和表单绑定的值(`model`) |
| required | 必填前缀插槽 | `*` / `表单props` 中的 `requiredIcons` |
:::
::: title 关于 async-validator 的使用
:::
::: describe 查看: https://github.com/yiminghe/async-validator。
:::
::: describe 翻译: ttps://www.cnblogs.com/wozho/p/10955525.html。
:::
::: title async-validator 基本校验类型
:::
::: table
| 属性 | 描述 | 使用方式 |
| -------------| ----------------- | ------------------- |
| number | 数字 | `{type : 'number'}` |
| boolean | 布尔类型 | `{type : 'boolean'}` |
| method | 方法 | `{type : 'method'}` |
| regexp | 正则表达式 | `{type : 'regexp'}` |
| integer | 整型数字 | `{type : 'integer'}` |
| float | 浮点小数 | `{type : 'float'}` |
| array | 数组 | `{type : 'array'}` |
| object | 对象 | `{type : 'object'}` |
| enum | 枚举 | `{type : 'enum'}` |
| date | 日期 | `{type : 'date'}` |
| url | url | `{type : 'url'}` |
| hex | 十六进制 | `{type : 'hex'}` |
| email | 邮箱 | `{type : 'email'}` |
:::
::: title async-validator 中 validator参数使用
:::
```javascript
{
validator: (rule, value) => value === 'root'
}
```
::: title async-validator 中 asyncValidator参数使用
:::
```javascript
{
asyncValidator: (rule, value) => {
return new Promise((resolve, reject) => {
if (value < 18) {
reject('too young'); // reject with error message
} else {
resolve();
}
});
}
}
```
::: title form 配置 async-validator 的使用
:::
```javascript
{
key : rule // key为表单子项需要校验的对应key名称 rule为校验规则格式为{}
}
// 例如 表单绑定值为 {email : 'xxx', username: 'xxxxx'}
// 需要校验邮箱,而邮箱输入框在表单绑定的值中key为email
// 需要校验用户名长度为8到16之间,而用户名输入框在表单绑定的值中key为username
{
email : {
type : 'email'
},
username : {
type : 'string',
min : 8,
max : 16
}
}
```
::: title form-item 配置 async-validator 的使用
:::
```javascript
// 例如 表单绑定值为 {email : 'xxx', phone: 'xxxxx'}
// 需要校验邮箱,而邮箱输入框在表单绑定的值中key为email
{
type : 'email'
}
```
::: contributor form
:::
::: previousNext form
:::