This commit is contained in:
castleiMac 2022-01-08 11:27:25 +08:00
commit d5c10257fe
27 changed files with 1995 additions and 547 deletions

View File

@ -70,7 +70,7 @@ createApp(App).use(Layui).mount('#app')
### 使用趋势 ### 使用趋势
[![Giteye chart](https://images.gitee.com/uploads/images/2021/1222/233241_e13a5449_4835367.png)](https://giteye.net/chart/5ZQ67WWS) [![Giteye chart](https://chart.giteye.net/gitee/layui-vue/layui-vue/5ZQ67WWS.png)](https://giteye.net/chart/5ZQ67WWS)
### 贡献代码 ### 贡献代码

View File

@ -11,15 +11,15 @@
<lay-menu-item title="首页" id="1"></lay-menu-item> <lay-menu-item title="首页" id="1"></lay-menu-item>
<lay-menu-item title="用户" id="2"></lay-menu-item> <lay-menu-item title="用户" id="2"></lay-menu-item>
<lay-menu-item title="角色" id="3"></lay-menu-item> <lay-menu-item title="角色" id="3"></lay-menu-item>
<lay-menu-item title="目录" id="7"> <lay-sub-menu title="目录" id="7">
<lay-menu-item title="菜单一" id="8"></lay-menu-item> <lay-menu-item title="菜单一" id="8"></lay-menu-item>
<lay-menu-item title="菜单二" id="9"></lay-menu-item> <lay-menu-item title="菜单二" id="9"></lay-menu-item>
<lay-menu-item title="菜单三" id="10"> <lay-sub-menu title="菜单三" id="10">
<lay-menu-item title="菜单一" id="11"></lay-menu-item> <lay-menu-item title="菜单一" id="11"></lay-menu-item>
<lay-menu-item title="菜单二" id="12"></lay-menu-item> <lay-menu-item title="菜单二" id="12"></lay-menu-item>
<lay-menu-item title="菜单三" id="13"></lay-menu-item> <lay-menu-item title="菜单三" id="13"></lay-menu-item>
</lay-menu-item> </lay-sub-menu>
</lay-menu-item> </lay-sub-menu>
</lay-menu> </lay-menu>
</template> </template>
@ -48,20 +48,68 @@ export default {
<template> <template>
<lay-menu v-model:selectedKey="selectedKey" v-model:openKeys="openKeys" v-model:tree="isTree"> <lay-menu v-model:selectedKey="selectedKey" v-model:openKeys="openKeys" v-model:tree="isTree">
<lay-menu-item title="首页" id="1"> <lay-menu-item title="首页" id="1"></lay-menu-item>
<template v-slot:title>
<router-link to="">无感</router-link>
</template>
</lay-menu-item>
<lay-menu-item title="用户" id="2"></lay-menu-item> <lay-menu-item title="用户" id="2"></lay-menu-item>
<lay-menu-item title="角色" id="3"></lay-menu-item> <lay-menu-item title="角色" id="3"></lay-menu-item>
<lay-menu-item title="目录" id="7"> <lay-sub-menu title="目录" id="7">
<lay-menu-item title="菜单一" id="8"></lay-menu-item> <lay-menu-item title="菜单一" id="8"></lay-menu-item>
<lay-menu-item title="菜单二" id="9"></lay-menu-item> <lay-menu-item title="菜单二" id="9"></lay-menu-item>
<lay-menu-item title="菜单三" id="10"> <lay-sub-menu title="菜单三" id="10">
<lay-menu-item title="菜单一" id="11"></lay-menu-item> <lay-menu-item title="菜单一" id="11"></lay-menu-item>
<lay-menu-item title="菜单二" id="12"></lay-menu-item> <lay-menu-item title="菜单二" id="12"></lay-menu-item>
<lay-menu-item title="菜单三" id="13"></lay-menu-item> <lay-menu-item title="菜单三" id="13"></lay-menu-item>
</lay-sub-menu>
</lay-sub-menu>
</lay-menu>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const isTree = ref(true)
const selectedKey = ref("5")
const openKeys = ref(["7"])
return {
isTree,
openKeys,
selectedKey
}
}
}
</script>
:::
::: title 菜单插槽
:::
::: demo
<template>
<lay-menu v-model:selectedKey="selectedKey" v-model:openKeys="openKeys" v-model:tree="isTree">
<lay-menu-item id="1">
<template v-slot:title>
<router-link to="">首页</router-link>
</template>
</lay-menu-item>
<lay-menu-item id="7">
<template v-slot:title>
<router-link to="">目录</router-link>
</template>
<lay-menu-item id="8">
<template v-slot:title>
<router-link to="">菜单一</router-link>
</template>
</lay-menu-item>
<lay-menu-item id="9">
<template v-slot:title>
<router-link to="">菜单二</router-link>
</template>
</lay-menu-item> </lay-menu-item>
</lay-menu-item> </lay-menu-item>
</lay-menu> </lay-menu>

View File

@ -319,7 +319,7 @@ export default {
::: table ::: table
| 备注 | 描述 | 默认值 | | 备注 | 描述 | 默认值 |
| --------------- | ------------- | -------------------------- | | --------------- | ------------- | --------------------------|
| title | 标题 | -- | | title | 标题 | -- |
| move | 允许拖拽 | `false` | | move | 允许拖拽 | `false` |
| maxmin | 最小化 最大化 | `false` | | maxmin | 最小化 最大化 | `false` |

View File

@ -1,6 +1,3 @@
::: anchor
:::
::: title 横向 ::: title 横向
::: :::
@ -56,7 +53,7 @@ export default {
::: demo ::: demo
<template> <template>
<lay-slider v-model="value3" :range="true"></lay-slider> <lay-slider v-model:standardrange="value3" :range="true"></lay-slider>
</template> </template>
<script> <script>
@ -78,14 +75,14 @@ export default {
::: demo ::: demo
<template> <template>
<lay-slider v-model="value3" :range="true" :vertical="true"></lay-slider> <lay-slider v-model:verticalrange="value4" :range="true" :vertical="true"></lay-slider>
</template> </template>
<script> <script>
import { ref } from 'vue' import { ref } from 'vue'
export default { export default {
setup() { setup() {
const value4 = ref([20,50]) const value4 = ref([23,56])
return { return {
value4 value4
} }
@ -94,5 +91,20 @@ export default {
</script> </script>
::: :::
::: title slider 属性
:::
::: table
| 属性 | 描述 | 类型 | 可选值 | 默认值 |
| ------------ | --------------------- | ------------------------- | -------------- | -------- |
| v-model | 选中值 | `number` | - | - |
| vertical | 是否垂直 | `Boolean` | - | - |
| range | 是否区间 | `Boolean` | - | - |
| verticalrange | 垂直区间值 | `Array` | - | - |
| standardrange | 水平区间值 | `Array` | - | - |
:::
::: comment ::: comment
::: :::

View File

@ -0,0 +1,473 @@
::: anchor
:::
::: title 基础使用
:::
::: demo
<template>
<div>
<lay-step :active="active">
<lay-step-item></lay-step-item>
<lay-step-item></lay-step-item>
<lay-step-item></lay-step-item>
<lay-step-item></lay-step-item>
</lay-step>
<div style="margin-top: 10px">
<lay-button size="xs" @click="previous">上一步</lay-button>
<lay-button size="xs" @click="nexts">下一步</lay-button>
</div>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const loading = ref(true);
const active = ref(-1);
const nexts = () => {
if (active.value++ >=3) active.value = 0
};
const previous = () => {
if (active.value-- ===0) active.value = 0
};
return {
loading,
active
}
}
}
</script>
:::
::: title composition 为row 的排版
:::
::: demo
<template>
<div>
<lay-step :active="active" composition="row">
<lay-step-item title="First" content="First step"></lay-step-item>
<lay-step-item title="Second" content="Second step"></lay-step-item>
<lay-step-item title="Third" content="Third step"></lay-step-item>
<lay-step-item title="Fourth" content="Fourth step"></lay-step-item>
</lay-step>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const loading = ref(true);
const active = ref(-1);
const nexts = () => {
if (active.value++ >=3) active.value = 0
};
const previous = () => {
if (active.value-- ===0) active.value = 0
};
return {
loading,
active
}
}
}
</script>
:::
::: title 带标题带描述
:::
::: demo
<template>
<div>
<lay-step :active="active">
<lay-step-item title="First" content="First step"></lay-step-item>
<lay-step-item title="Second" content="Second step"></lay-step-item>
<lay-step-item title="Third" content="Third step"></lay-step-item>
<lay-step-item title="Fourth" content="Fourth step"></lay-step-item>
</lay-step>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const loading = ref(true);
const active = ref(-1);
const nexts = () => {
if (active.value++ >=3) active.value = 0
};
const previous = () => {
if (active.value-- ===0) active.value = 0
};
return {
loading,
active
}
}
}
</script>
:::
::: title 设置当前选中状态
:::
::: demo
<template>
<div>
<lay-step :active="active" current-status="primary">
<lay-step-item title="First" content="First step"></lay-step-item>
<lay-step-item title="Second" content="Second step"></lay-step-item>
<lay-step-item title="Third" content="Third step"></lay-step-item>
</lay-step>
<lay-button size="xs" @click="previous">上一步</lay-button>
<lay-button size="xs" @click="next">下一步</lay-button>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const loading = ref(true);
const active = ref(-1);
const next = () => {
if (active.value++ >=2) active.value = 0
};
const previous = () => {
if (active.value-- ===0) active.value = 0
};
return {
loading,
active
}
}
}
</script>
:::
::: title 设置第几步状态
:::
这里设置`status` 会覆盖掉`current-status`
::: demo
<template>
<div>
<lay-step :active="active" current-status="warning">
<lay-step-item title="First" content="First step"></lay-step-item>
<lay-step-item status="fail" title="Second" content="Second step"></lay-step-item>
<lay-step-item title="Third" content="Third step"></lay-step-item>
<lay-step-item title="Fourth" content="Fourth step"></lay-step-item>
</lay-step>
<lay-button size="xs" @click="previous">上一步</lay-button>
<lay-button size="xs" @click="nexts">下一步</lay-button>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const loading = ref(true);
const active = ref(-1);
const nexts = () => {
if (active.value++ >=3) active.value = 0
};
const previous = () => {
if (active.value-- ===0) active.value = 0
};
return {
loading,
active
}
}
}
</script>
:::
::: title 自定义宽度
:::
::: demo
<template>
<div>
<lay-step :active="active" space="200px">
<lay-step-item title="First" content="First step"></lay-step-item>
<lay-step-item title="Second" content="Second step"></lay-step-item>
<lay-step-item title="Third" content="Third step"></lay-step-item>
</lay-step>
<lay-button size="xs" @click="previous">上一步</lay-button>
<lay-button size="xs" @click="next">下一步</lay-button>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const loading = ref(true);
const active = ref(-1);
const next = () => {
if (active.value++ >=2) active.value = 0
};
const previous = () => {
if (active.value-- ===0) active.value = 0
};
return {
loading,
active
}
}
}
</script>
:::
::: title 自定义图标
:::
::: demo
<template>
<div>
<lay-step :active="active">
<lay-step-item title="First" content="First step" icon="layui-icon-release"></lay-step-item>
<lay-step-item title="Second" content="Second step" icon="layui-icon-tree"></lay-step-item>
<lay-step-item title="Third" content="Third step" icon="layui-icon-share"></lay-step-item>
</lay-step>
<lay-button size="xs" @click="previous">上一步</lay-button>
<lay-button size="xs" @click="next">下一步</lay-button>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const loading = ref(true);
const active = ref(-1);
const next = () => {
if (active.value++ >=2) active.value = 0
};
const previous = () => {
if (active.value-- ===0) active.value = 0
};
return {
loading,
active
}
}
}
</script>
:::
::: title 居中
:::
::: demo
<template>
<div>
<lay-step :active="active" center>
<lay-step-item title="First" content="First step">
<template #pace>
<lay-icon type="layui-icon-ok"></lay-icon>
</template>
</lay-step-item>
<lay-step-item title="Second" content="Second step"></lay-step-item>
<lay-step-item title="Third" content="Third step"></lay-step-item>
</lay-step>
<lay-button size="xs" @click="previous">上一步</lay-button>
<lay-button size="xs" @click="next">下一步</lay-button>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const loading = ref(true);
const active = ref(-1);
const next = () => {
if (active.value++ >=2) active.value = 0
};
const previous = () => {
if (active.value-- ===0) active.value = 0
};
return {
loading,
active
}
}
}
</script>
:::
::: title 垂直
:::
::: demo
<template>
<div style="height: 300px">
<lay-step :active="active" direction="vertical">
<lay-step-item title="First" content="First step">
<template #pace>
<lay-icon type="layui-icon-ok"></lay-icon>
</template>
</lay-step-item>
<lay-step-item title="Second" content="Second step"></lay-step-item>
<lay-step-item title="Third" content="Third step"></lay-step-item>
</lay-step>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const loading = ref(true);
const active = ref(-1);
const next = () => {
if (active.value++ >=2) active.value = 0
};
const previous = () => {
if (active.value-- ===0) active.value = 0
};
return {
loading,
active
}
}
}
</script>
:::
::: title 简洁版
:::
简洁版不支持`垂直``横向``描述``排版`
::: demo
<template>
<div>
<lay-step :active="active" simple @onChange="onChange">
<lay-step-item title="First"></lay-step-item>
<lay-step-item title="Second"></lay-step-item>
<lay-step-item title="Third"></lay-step-item>
</lay-step>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
setup() {
const loading = ref(true);
const active = ref(0);
const next = () => {
if (active.value++ >=2) active.value = 0
};
const previous = () => {
if (active.value-- ===0) active.value = 0
};
const onChange = (index) => {
active.value = index
};
return {
loading,
active
}
}
}
</script>
:::
::: title step步骤条属性
:::
::: table
| 属性 | 描述 | 类型 |可选值 | 默认值|
| ----- | ---- | ------ | ---| ---|
| active | 第几步 | number |-| 0 |
| center | 居中布局 | boolean | `true` `false` | `false` |
| direction | 垂直/平行布局 | string |`horizontal` `vertical` | `horizontal` |
| space | 宽度 | string | - | `auto` |
| currentStatus | 当前状态显示 | string | `primary` `success` `fail` `warning` | `success` |
| composition | 排版 | string | `default` `row` | `default` |
| simple | 简洁版 | boolean | `true` `false` |`false`|
| onChange | 点击切换时监听 | function | - |function(index){}|
:::
::: title stepItem步骤条属性
:::
::: table
| 属性 | 描述 | 类型 |可选值 | 默认值|
| ----- | ---- | ------ | ---| ---|
| title| 标题 | string | - | - |
| content | 内容描述 | string | - | -|
| icon | 图标 | string | - | -|
| status | 状态 | string | `primary` `success` `fail` `warning` | `primary`|
:::
::: title stepItem步骤条slot
:::
::: table
| 属性 | 描述 |
| ----- | ---- |
| pace | 圆圈内容自定义 |
| default | 内容区域自定义 |
:::
::: comment
:::

View File

@ -75,7 +75,40 @@ export default {
::: :::
::: title timeline-item attributes
::: title 节点插槽
:::
::: demo
<template>
<lay-timeline>
<lay-timeline-item title="2021年layui vue 里程碑版本 1.0 发布" simple></lay-timeline-item>
<lay-timeline-item title="2017年layui 里程碑版本 2.0 发布" simple></lay-timeline-item>
<lay-timeline-item title="2016年layui 首个版本发布" simple></lay-timeline-item>
<lay-timeline-item title="2015年layui 孵化" simple>
<template #dot>
<lay-icon type="layui-icon-face-smile" color="red"></lay-icon>
</template>
</lay-timeline-item>
</lay-timeline>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
return {
}
}
}
</script>
:::
::: title Timeline Item 属性
::: :::
::: table ::: table
@ -87,5 +120,16 @@ export default {
::: :::
::: title Timeline Item 属性
:::
::: table
| | | |
| ------ | -------- | --- |
| dot | 节点 | -- |
:::
::: comment ::: comment
::: :::

View File

@ -11,6 +11,19 @@
<template> <template>
<lay-timeline> <lay-timeline>
<lay-timeline-item title="0.3.x"> <lay-timeline-item title="0.3.x">
<ul>
<a name="0-3-3"> </a>
<li>
<h3>0.3.3 <span class="layui-badge-rim">2022-01-05</span></h3>
<ul>
<li>[新增] setup 步骤条组件。</li>
<li>[新增] slider 滑块组件 vertical 属性, 支持垂直布局。</li>
<li>[新增] timeline-item 时间线组件 dot 插槽, 支持自定义节点内容。</li>
<li>[新增] sub-menu 目录组件, 与 menu-item 组合使用。</li>
<li>[修复] menu 组件 layui-nav-more 切换动画。</li>
</ul>
</li>
</ul>
<ul> <ul>
<a name="0-3-2"> </a> <a name="0-3-2"> </a>
<li> <li>

View File

@ -3,7 +3,7 @@
<p> <p>
<a href="http://layui-vue.pearadmin.com"> <a href="http://layui-vue.pearadmin.com">
<img src="https://sentsin.gitee.io/res/images/layui/layui.png" alt="layui" width="500"> <img src="../../../src/assets/logo-new.png" alt="layui" width="500">
</a> </a>
</p> </p>

View File

@ -3,13 +3,13 @@
<lay-card> <lay-card>
<lay-row> <lay-row>
<lay-col md="1"> <lay-col md="2">
<lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/1611/4835367_Jmysy_1578975358.png"></lay-avatar> <lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/1611/4835367_Jmysy_1578975358.png"></lay-avatar>
</lay-col> </lay-col>
<lay-col md="2"> <lay-col md="3">
就眠仪式 就眠仪式
</lay-col> </lay-col>
<lay-col md="10"> <lay-col md="8">
焦点layui-vue 焦点layui-vue
</lay-col> </lay-col>
<lay-col md="4"> <lay-col md="4">
@ -22,13 +22,13 @@
</lay-card> </lay-card>
<lay-card> <lay-card>
<lay-row> <lay-row>
<lay-col md="1"> <lay-col md="2">
<lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/1755/5267877_jobin_jia_1608578025.png"></lay-avatar> <lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/1755/5267877_jobin_jia_1608578025.png"></lay-avatar>
</lay-col> </lay-col>
<lay-col md="2"> <lay-col md="3">
落小梅 落小梅
</lay-col> </lay-col>
<lay-col md="10"> <lay-col md="8">
焦点tree table 焦点tree table
</lay-col> </lay-col>
<lay-col md="4"> <lay-col md="4">
@ -42,13 +42,13 @@
<lay-card> <lay-card>
<lay-row> <lay-row>
<lay-col md="1"> <lay-col md="2">
<lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/702/2106738_wanglin300_1639442830.png"></lay-avatar> <lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/702/2106738_wanglin300_1639442830.png"></lay-avatar>
</lay-col> </lay-col>
<lay-col md="2"> <lay-col md="3">
halo halo
</lay-col> </lay-col>
<lay-col md="10"> <lay-col md="8">
焦点slider 焦点slider
</lay-col> </lay-col>
<lay-col md="4"> <lay-col md="4">
@ -62,13 +62,13 @@
<lay-card> <lay-card>
<lay-row> <lay-row>
<lay-col md="1"> <lay-col md="2">
<lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/1871/5614379_xumisky_1607057214.png"></lay-avatar> <lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/1871/5614379_xumisky_1607057214.png"></lay-avatar>
</lay-col> </lay-col>
<lay-col md="2"> <lay-col md="3">
须弥 须弥
</lay-col> </lay-col>
<lay-col md="10"> <lay-col md="8">
焦点layui-vue 焦点layui-vue
</lay-col> </lay-col>
<lay-col md="4"> <lay-col md="4">
@ -82,13 +82,13 @@
<lay-card> <lay-card>
<lay-row> <lay-row>
<lay-col md="1"> <lay-col md="2">
<lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/2469/7407590_wcg666_1640528494.png"></lay-avatar> <lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/2469/7407590_wcg666_1640528494.png"></lay-avatar>
</lay-col> </lay-col>
<lay-col md="2"> <lay-col md="3">
Sight Sight
</lay-col> </lay-col>
<lay-col md="10"> <lay-col md="8">
焦点count-up backtop 焦点count-up backtop
</lay-col> </lay-col>
<lay-col md="4"> <lay-col md="4">
@ -102,13 +102,13 @@
<lay-card> <lay-card>
<lay-row> <lay-row>
<lay-col md="1"> <lay-col md="2">
<lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/2596/7789823_finalsummer_1613993823.png"></lay-avatar> <lay-avatar src="https://portrait.gitee.com/uploads/avatars/user/2596/7789823_finalsummer_1613993823.png"></lay-avatar>
</lay-col> </lay-col>
<lay-col md="2"> <lay-col md="3">
finalsummer finalsummer
</lay-col> </lay-col>
<lay-col md="10"> <lay-col md="8">
焦点layer-vue 焦点layer-vue
</lay-col> </lay-col>
<lay-col md="4"> <lay-col md="4">
@ -122,20 +122,20 @@
<lay-card> <lay-card>
<lay-row> <lay-row>
<lay-col md="1"> <lay-col md="2">
<lay-avatar src="http://mms0.baidu.com/it/u=1690972933,1482111264&fm=253&app=138&f=JPEG&fmt=auto&q=75?w=500&h=500"></lay-avatar> <lay-avatar src="http://mms0.baidu.com/it/u=1690972933,1482111264&fm=253&app=138&f=JPEG&fmt=auto&q=75?w=500&h=500"></lay-avatar>
</lay-col> </lay-col>
<lay-col md="2"> <lay-col md="3">
莫名点 莫名点
</lay-col> </lay-col>
<lay-col md="10"> <lay-col md="8">
焦点skeleton 焦点skeleton step
</lay-col> </lay-col>
<lay-col md="4"> <lay-col md="4">
地点:中国 未知 地点:中国 上海
</lay-col> </lay-col>
<lay-col md="6"> <lay-col md="6">
其他Gitee Github 其他:<a href="https://gitee.com/dingyongya">Gitee</a> <a href="https://github.com/dyywork">Github</a>
</lay-col> </lay-col>
</lay-row> </lay-row>
</lay-card> </lay-card>

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,52 +1,52 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck // @ts-nocheck
import { createApp } from './main' import { createApp } from "./main";
import { renderToString } from '@vue/server-renderer' import { renderToString } from "@vue/server-renderer";
export async function render(url, manifest): Promise<string[]> { export async function render(url, manifest): Promise<string[]> {
const { app, router } = createApp() const { app, router } = createApp();
// set the router to the desired URL before rendering // set the router to the desired URL before rendering
router.push(url) router.push(url);
await router.isReady() await router.isReady();
// passing SSR context object which will be available via useSSRContext() // passing SSR context object which will be available via useSSRContext()
// @vitejs/plugin-vue injects code into a component's setup() that registers // @vitejs/plugin-vue injects code into a component's step() that registers
// itself on ctx.modules. After the render, ctx.modules would contain all the // itself on ctx.modules. After the render, ctx.modules would contain all the
// components that have been instantiated during this render call. // components that have been instantiated during this render call.
const ctx = {} const ctx = {};
const html = await renderToString(app, ctx) const html = await renderToString(app, ctx);
// the SSR manifest generated by Vite contains module -> chunk/asset mapping // the SSR manifest generated by Vite contains module -> chunk/asset mapping
// which we can then use to determine what files need to be preloaded for this // which we can then use to determine what files need to be preloaded for this
// request. // request.
const preloadLinks = renderPreloadLinks(ctx.modules, manifest) const preloadLinks = renderPreloadLinks(ctx.modules, manifest);
return [html, preloadLinks] return [html, preloadLinks];
} }
function renderPreloadLinks(modules, manifest) { function renderPreloadLinks(modules, manifest) {
let links = '' let links = "";
const seen = new Set() const seen = new Set();
modules.forEach((id) => { modules.forEach((id) => {
const files = manifest[id] const files = manifest[id];
if (files) { if (files) {
files.forEach((file) => { files.forEach((file) => {
if (!seen.has(file)) { if (!seen.has(file)) {
seen.add(file) seen.add(file);
links += renderPreloadLink(file) links += renderPreloadLink(file);
} }
}) });
} }
}) });
return links return links;
} }
function renderPreloadLink(file) { function renderPreloadLink(file) {
if (file.endsWith('.js')) { if (file.endsWith(".js")) {
return `<link rel="modulepreload" crossorigin href="${file}">` return `<link rel="modulepreload" crossorigin href="${file}">`;
} else if (file.endsWith('.css')) { } else if (file.endsWith(".css")) {
return `<link rel="stylesheet" href="${file}">` return `<link rel="stylesheet" href="${file}">`;
} else { } else {
return '' return "";
} }
} }

View File

@ -1,362 +1,373 @@
import BaseLayout from '../layouts/Layout.vue' import BaseLayout from "../layouts/Layout.vue";
import Component from '../view/component.vue' import Component from "../view/component.vue";
import Hooks from '../view/hooks.vue' import Hooks from "../view/hooks.vue";
import Guide from '../view/guide.vue' import Guide from "../view/guide.vue";
import Index from '../view/index.vue' import Index from "../view/index.vue";
import Ecology from '../view/ecology.vue' import Ecology from "../view/ecology.vue";
const zhCN = [ const zhCN = [
{ {
path: '/', path: "/",
redirect: '/zh-CN/index', redirect: "/zh-CN/index",
component: BaseLayout, component: BaseLayout,
meta: { title: '首页' }, meta: { title: "首页" },
children: [ children: [
{ {
path: '/zh-CN/index', path: "/zh-CN/index",
component: Index, component: Index,
meta: { title: '指南' }, meta: { title: "指南" },
}, },
{ {
path: '/zh-CN/ecology', path: "/zh-CN/ecology",
component: Ecology, component: Ecology,
meta: { title: '生态' }, meta: { title: "生态" },
}, },
{ {
path: '/zh-CN/guide', path: "/zh-CN/guide",
redirect: '/zh-CN/guide/introduce', redirect: "/zh-CN/guide/introduce",
component: Guide, component: Guide,
meta: { title: '指南' }, meta: { title: "指南" },
children: [ children: [
{ {
path: '/zh-CN/guide/introduce', path: "/zh-CN/guide/introduce",
component: () => import('../../docs/zh-CN/guide/introduce.md'), component: () => import("../../docs/zh-CN/guide/introduce.md"),
meta: { title: '介绍' }, meta: { title: "介绍" },
}, },
{ {
path: '/zh-CN/guide/getStarted', path: "/zh-CN/guide/getStarted",
component: () => import('../../docs/zh-CN/guide/getStarted.md'), component: () => import("../../docs/zh-CN/guide/getStarted.md"),
meta: { title: '安装' }, meta: { title: "安装" },
}, },
{ {
path: '/zh-CN/guide/changelog', path: "/zh-CN/guide/changelog",
component: () => import('../../docs/zh-CN/guide/changelog.md'), component: () => import("../../docs/zh-CN/guide/changelog.md"),
meta: { title: '更新' }, meta: { title: "更新" },
}, },
{ {
path: '/zh-CN/guide/problem', path: "/zh-CN/guide/problem",
component: () => import('../../docs/zh-CN/guide/problem.md'), component: () => import("../../docs/zh-CN/guide/problem.md"),
meta: { title: '问题' }, meta: { title: "问题" },
}, },
{ {
path: '/zh-CN/guide/member', path: "/zh-CN/guide/member",
component: () => import('../../docs/zh-CN/guide/member.md'), component: () => import("../../docs/zh-CN/guide/member.md"),
meta: { title: '团队' }, meta: { title: "团队" },
}, },
{ {
path: '/zh-CN/guide/norms', path: "/zh-CN/guide/norms",
component: () => import('../../docs/zh-CN/guide/norms.md'), component: () => import("../../docs/zh-CN/guide/norms.md"),
meta: { title: '规范' }, meta: { title: "规范" },
}, },
{ {
path: '/zh-CN/guide/theme', path: "/zh-CN/guide/theme",
component: () => import('../../docs/zh-CN/guide/theme.md'), component: () => import("../../docs/zh-CN/guide/theme.md"),
meta: { title: '主题' }, meta: { title: "主题" },
}, },
{ {
path: '/zh-CN/guide/sponsor', path: "/zh-CN/guide/sponsor",
component: () => import('../../docs/zh-CN/guide/sponsor.md'), component: () => import("../../docs/zh-CN/guide/sponsor.md"),
meta: { title: '赞助' }, meta: { title: "赞助" },
}, },
], ],
}, },
{ {
path: '/zh-CN/components', path: "/zh-CN/components",
redirect: '/zh-CN/components/color', redirect: "/zh-CN/components/color",
component: Component, component: Component,
meta: { title: '组件' }, meta: { title: "组件" },
children: [ children: [
{ {
path: '/zh-CN/components/skeleton', path: "/zh-CN/components/skeleton",
component: () => import('../../docs/zh-CN/components/skeleton.md'), component: () => import("../../docs/zh-CN/components/skeleton.md"),
meta: { title: '骨架屏' }, meta: { title: "骨架屏" },
}, },
{ {
path: '/zh-CN/components/layout', path: "/zh-CN/components/layout",
component: () => import('../../docs/zh-CN/components/layout.md'), component: () => import("../../docs/zh-CN/components/layout.md"),
meta: { title: '布局' }, meta: { title: "布局" },
}, },
{ {
path: '/zh-CN/components/color', path: "/zh-CN/components/color",
component: () => import('../../docs/zh-CN/components/color.md'), component: () => import("../../docs/zh-CN/components/color.md"),
meta: { title: '颜色' }, meta: { title: "颜色" },
}, },
{ {
path: '/zh-CN/components/container', path: "/zh-CN/components/container",
component: () => import('../../docs/zh-CN/components/container.md'), component: () => import("../../docs/zh-CN/components/container.md"),
meta: { title: '容器' }, meta: { title: "容器" },
}, },
{ {
path: '/zh-CN/components/breadcrumb', path: "/zh-CN/components/breadcrumb",
component: () => component: () =>
import('../../docs/zh-CN/components/breadcrumb.md'), import("../../docs/zh-CN/components/breadcrumb.md"),
meta: { title: '面包屑' }, meta: { title: "面包屑" },
}, },
{ {
path: '/zh-CN/components/button', path: "/zh-CN/components/button",
component: () => import('../../docs/zh-CN/components/button.md'), component: () => import("../../docs/zh-CN/components/button.md"),
meta: { title: '按钮' }, meta: { title: "按钮" },
}, },
{ {
path: '/zh-CN/components/icon', path: "/zh-CN/components/icon",
component: () => import('../../docs/zh-CN/components/icon.md'), component: () => import("../../docs/zh-CN/components/icon.md"),
meta: { title: '图标' }, meta: { title: "图标" },
}, },
{ {
path: '/zh-CN/components/panel', path: "/zh-CN/components/panel",
component: () => import('../../docs/zh-CN/components/panel.md'), component: () => import("../../docs/zh-CN/components/panel.md"),
meta: { title: '面板' }, meta: { title: "面板" },
}, },
{ {
path: '/zh-CN/components/animation', path: "/zh-CN/components/animation",
component: () => import('../../docs/zh-CN/components/animation.md'), component: () => import("../../docs/zh-CN/components/animation.md"),
meta: { title: '动画' }, meta: { title: "动画" },
}, },
{ {
path: '/zh-CN/components/card', path: "/zh-CN/components/card",
component: () => import('../../docs/zh-CN/components/card.md'), component: () => import("../../docs/zh-CN/components/card.md"),
meta: { title: '卡片' }, meta: { title: "卡片" },
}, },
{ {
path: '/zh-CN/components/grid', path: "/zh-CN/components/grid",
component: () => import('../../docs/zh-CN/components/grid.md'), component: () => import("../../docs/zh-CN/components/grid.md"),
meta: { title: '栅格' }, meta: { title: "栅格" },
}, },
{ {
path: '/zh-CN/components/form', path: "/zh-CN/components/form",
component: () => import('../../docs/zh-CN/components/form.md'), component: () => import("../../docs/zh-CN/components/form.md"),
meta: { title: '表单' }, meta: { title: "表单" },
}, },
{ {
path: '/zh-CN/components/badge', path: "/zh-CN/components/badge",
component: () => import('../../docs/zh-CN/components/badge.md'), component: () => import("../../docs/zh-CN/components/badge.md"),
meta: { title: '徽章' }, meta: { title: "徽章" },
}, },
{ {
path: '/zh-CN/components/block', path: "/zh-CN/components/block",
component: () => import('../../docs/zh-CN/components/block.md'), component: () => import("../../docs/zh-CN/components/block.md"),
meta: { title: '辅助' }, meta: { title: "辅助" },
}, },
{ {
path: '/zh-CN/components/line', path: "/zh-CN/components/line",
component: () => import('../../docs/zh-CN/components/line.md'), component: () => import("../../docs/zh-CN/components/line.md"),
meta: { title: '分割' }, meta: { title: "分割" },
}, },
{ {
path: '/zh-CN/components/progress', path: "/zh-CN/components/progress",
component: () => import('../../docs/zh-CN/components/progress.md'), component: () => import("../../docs/zh-CN/components/progress.md"),
meta: { title: '进度' }, meta: { title: "进度" },
}, },
{ {
path: '/zh-CN/components/menu', path: "/zh-CN/components/menu",
component: () => import('../../docs/zh-CN/components/menu.md'), component: () => import("../../docs/zh-CN/components/menu.md"),
meta: { title: '菜单' }, meta: { title: "菜单" },
}, },
{ {
path: '/zh-CN/components/timeline', path: "/zh-CN/components/timeline",
component: () => import('../../docs/zh-CN/components/timeline.md'), component: () => import("../../docs/zh-CN/components/timeline.md"),
meta: { title: '时间线' }, meta: { title: "时间线" },
}, },
{ {
path: '/zh-CN/components/collapse', path: "/zh-CN/components/collapse",
component: () => import('../../docs/zh-CN/components/collapse.md'), component: () => import("../../docs/zh-CN/components/collapse.md"),
meta: { title: '折叠面板' }, meta: { title: "折叠面板" },
}, },
{ {
path: '/zh-CN/components/table', path: "/zh-CN/components/step",
component: () => import('../../docs/zh-CN/components/table.md'), component: () => import("../../docs/zh-CN/components/step.md"),
meta: { title: '表格' }, meta: { title: "分步" },
}, },
{ {
path: '/zh-CN/components/avatar', path: "/zh-CN/components/table",
component: () => import('../../docs/zh-CN/components/avatar.md'), component: () => import("../../docs/zh-CN/components/table.md"),
meta: { title: '头像' }, meta: { title: "表格" },
}, },
{ {
path: '/zh-CN/components/field', path: "/zh-CN/components/avatar",
component: () => import('../../docs/zh-CN/components/field.md'), component: () => import("../../docs/zh-CN/components/avatar.md"),
meta: { title: '字段' }, meta: { title: "头像" },
}, },
{ {
path: '/zh-CN/components/empty', path: "/zh-CN/components/field",
component: () => import('../../docs/zh-CN/components/empty.md'), component: () => import("../../docs/zh-CN/components/field.md"),
meta: { title: '空' }, meta: { title: "字段" },
}, },
{ {
path: '/zh-CN/components/rate', path: "/zh-CN/components/empty",
component: () => import('../../docs/zh-CN/components/rate.md'), component: () => import("../../docs/zh-CN/components/empty.md"),
meta: { title: '评分' }, meta: { title: "空" },
}, },
{ {
path: '/zh-CN/components/dropdown', path: "/zh-CN/components/rate",
component: () => import('../../docs/zh-CN/components/dropdown.md'), component: () => import("../../docs/zh-CN/components/rate.md"),
meta: { title: '下拉' }, meta: { title: "评分" },
}, },
{ {
path: '/zh-CN/components/tab', path: "/zh-CN/components/dropdown",
component: () => import('../../docs/zh-CN/components/tab.md'), component: () => import("../../docs/zh-CN/components/dropdown.md"),
meta: { title: '选项卡' }, meta: { title: "下拉" },
}, },
{ {
path: '/zh-CN/components/iconPicker', path: "/zh-CN/components/tab",
component: () => import("../../docs/zh-CN/components/tab.md"),
meta: { title: "选项卡" },
},
{
path: "/zh-CN/components/iconPicker",
component: () => component: () =>
import('../../docs/zh-CN/components/iconPicker.md'), import("../../docs/zh-CN/components/iconPicker.md"),
meta: { title: '图标选择' }, meta: { title: "图标选择" },
}, },
{ {
path: '/zh-CN/components/tree', path: "/zh-CN/components/tree",
component: () => import('../../docs/zh-CN/components/tree.md'), component: () => import("../../docs/zh-CN/components/tree.md"),
meta: { title: '树形组件' }, meta: { title: "树形组件" },
}, },
{ {
path: '/zh-CN/components/page', path: "/zh-CN/components/page",
component: () => import('../../docs/zh-CN/components/page.md'), component: () => import("../../docs/zh-CN/components/page.md"),
meta: { title: '分页' }, meta: { title: "分页" },
}, },
{ {
path: '/zh-CN/components/transfer', path: "/zh-CN/components/transfer",
component: () => import('../../docs/zh-CN/components/transfer.md'), component: () => import("../../docs/zh-CN/components/transfer.md"),
meta: { title: '穿梭框' }, meta: { title: "穿梭框" },
}, },
{ {
path: '/zh-CN/components/checkbox', path: "/zh-CN/components/checkbox",
component: () => import('../../docs/zh-CN/components/checkbox.md'), component: () => import("../../docs/zh-CN/components/checkbox.md"),
meta: { title: '复选框' }, meta: { title: "复选框" },
}, },
{ {
path: '/zh-CN/components/radio', path: "/zh-CN/components/radio",
component: () => import('../../docs/zh-CN/components/radio.md'), component: () => import("../../docs/zh-CN/components/radio.md"),
meta: { title: '单选框' }, meta: { title: "单选框" },
}, },
{ {
path: '/zh-CN/components/input', path: "/zh-CN/components/input",
component: () => import('../../docs/zh-CN/components/input.md'), component: () => import("../../docs/zh-CN/components/input.md"),
meta: { title: '输入框' }, meta: { title: "输入框" },
}, },
{ {
path: '/zh-CN/components/inputNumber', path: "/zh-CN/components/inputNumber",
component: () => import('../../docs/zh-CN/components/inputNumber.md'),
meta: { title: '数字输入框' },
},
{
path: '/zh-CN/components/textarea',
component: () => import('../../docs/zh-CN/components/textarea.md'),
meta: { title: '文本域' },
},
{
path: '/zh-CN/components/switch',
component: () => import('../../docs/zh-CN/components/switch.md'),
meta: { title: '开关' },
},
{
path: '/zh-CN/components/slider',
component: () => import('../../docs/zh-CN/components/slider.md'),
meta: { title: '滑块' },
},
{
path: '/zh-CN/components/carousel',
component: () => import('../../docs/zh-CN/components/carousel.md'),
meta: { title: '轮播' },
},
{
path: '/zh-CN/components/select',
component: () => import('../../docs/zh-CN/components/select.md'),
meta: { title: '下拉选择' },
},
{
path: '/zh-CN/components/colorPicker',
component: () => component: () =>
import('../../docs/zh-CN/components/colorPicker.md'), import("../../docs/zh-CN/components/inputNumber.md"),
meta: { title: '颜色选择器' }, meta: { title: "数字输入框" },
},{
path: '/zh-CN/components/layer',
component: () => import('../../docs/zh-CN/components/layer.md'),
meta: { title: '简介' },
}, },
{ {
path: '/zh-CN/components/tooltip', path: "/zh-CN/components/textarea",
component: () => import('../../docs/zh-CN/components/tooltip.md'), component: () => import("../../docs/zh-CN/components/textarea.md"),
meta: { title: '文字提示' }, meta: { title: "文本域" },
}, },
{ {
path: '/zh-CN/components/modal', path: "/zh-CN/components/switch",
component: () => import('../../docs/zh-CN/components/modal.md'), component: () => import("../../docs/zh-CN/components/switch.md"),
meta: { title: '弹层' }, meta: { title: "开关" },
},{
path: '/zh-CN/components/load',
component: () => import('../../docs/zh-CN/components/load.md'),
meta: { title: '加载' },
},{
path: '/zh-CN/components/confirm',
component: () => import('../../docs/zh-CN/components/confirm.md'),
meta: { title: '询问' },
},{
path: '/zh-CN/components/msg',
component: () => import('../../docs/zh-CN/components/msg.md'),
meta: { title: '信息' },
},{
path: '/zh-CN/components/backtop',
component: () => import('../../docs/zh-CN/components/backtop.md'),
meta: { title: '返回顶部' },
}, },
{ {
path: '/zh-CN/components/countup', path: "/zh-CN/components/slider",
component: () => import('../../docs/zh-CN/components/countup.md'), component: () => import("../../docs/zh-CN/components/slider.md"),
meta: { title: '数字滚动' }, meta: { title: "滑块" },
},
{
path: "/zh-CN/components/carousel",
component: () => import("../../docs/zh-CN/components/carousel.md"),
meta: { title: "轮播" },
},
{
path: "/zh-CN/components/select",
component: () => import("../../docs/zh-CN/components/select.md"),
meta: { title: "下拉选择" },
},
{
path: "/zh-CN/components/colorPicker",
component: () =>
import("../../docs/zh-CN/components/colorPicker.md"),
meta: { title: "颜色选择器" },
},
{
path: "/zh-CN/components/layer",
component: () => import("../../docs/zh-CN/components/layer.md"),
meta: { title: "简介" },
},
{
path: "/zh-CN/components/tooltip",
component: () => import("../../docs/zh-CN/components/tooltip.md"),
meta: { title: "文字提示" },
},
{
path: "/zh-CN/components/modal",
component: () => import("../../docs/zh-CN/components/modal.md"),
meta: { title: "弹层" },
},
{
path: "/zh-CN/components/load",
component: () => import("../../docs/zh-CN/components/load.md"),
meta: { title: "加载" },
},
{
path: "/zh-CN/components/confirm",
component: () => import("../../docs/zh-CN/components/confirm.md"),
meta: { title: "询问" },
},
{
path: "/zh-CN/components/msg",
component: () => import("../../docs/zh-CN/components/msg.md"),
meta: { title: "信息" },
},
{
path: "/zh-CN/components/backtop",
component: () => import("../../docs/zh-CN/components/backtop.md"),
meta: { title: "返回顶部" },
},
{
path: "/zh-CN/components/countup",
component: () => import("../../docs/zh-CN/components/countup.md"),
meta: { title: "数字滚动" },
}, },
], ],
}, },
{ {
path: '/zh-CN/hooks', path: "/zh-CN/hooks",
redirect: '/zh-CN/hooks/useStarted', redirect: "/zh-CN/hooks/useStarted",
component: Hooks, component: Hooks,
meta: { title: 'hooks' }, meta: { title: "hooks" },
children: [ children: [
{ {
path: '/zh-CN/hooks/useStarted', path: "/zh-CN/hooks/useStarted",
component: () => import("../../docs/zh-CN/hooks/useStarted.md"),
meta: { title: "useStarted" },
},
{
path: "/zh-CN/hooks/useClickOutside",
component: () => component: () =>
import('../../docs/zh-CN/hooks/useStarted.md'), import("../../docs/zh-CN/hooks/useClickOutside.md"),
meta: { title: 'useStarted' }, meta: { title: "useClickOutside" },
}, },
{ {
path: '/zh-CN/hooks/useClickOutside', path: "/zh-CN/hooks/useFullScreen",
component: () => component: () => import("../../docs/zh-CN/hooks/useFullScreen.md"),
import('../../docs/zh-CN/hooks/useClickOutside.md'), meta: { title: "useFullScreen" },
meta: { title: 'useClickOutside' },
}, },
{ {
path: '/zh-CN/hooks/useFullScreen', path: "/zh-CN/hooks/useMove",
component: () => import('../../docs/zh-CN/hooks/useFullScreen.md'), component: () => import("../../docs/zh-CN/hooks/useMove.md"),
meta: { title: 'useFullScreen' }, meta: { title: "useMove" },
}, },
{ {
path: '/zh-CN/hooks/useMove', path: "/zh-CN/hooks/useState",
component: () => import('../../docs/zh-CN/hooks/useMove.md'), component: () => import("../../docs/zh-CN/hooks/useState.md"),
meta: { title: 'useMove' }, meta: { title: "useState" },
}, {
path: '/zh-CN/hooks/useState',
component: () => import('../../docs/zh-CN/hooks/useState.md'),
meta: { title: 'useState' },
}, },
{ {
path: '/zh-CN/hooks/useBoolean', path: "/zh-CN/hooks/useBoolean",
component: () => import('../../docs/zh-CN/hooks/useBoolean.md'), component: () => import("../../docs/zh-CN/hooks/useBoolean.md"),
meta: { title: 'useBoolean' }, meta: { title: "useBoolean" },
}, },
], ],
}, },
], ],
}, },
] ];
export default zhCN export default zhCN;

View File

@ -50,362 +50,371 @@
</lay-layout> </lay-layout>
</template> </template>
<script> <script>
import { ref, watch } from 'vue' import { ref, watch } from "vue";
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from "vue-router";
export default { export default {
setup() { setup() {
const route = useRoute() const route = useRoute();
const router = useRouter() const router = useRouter();
const currentPath = ref('/zh-CN/guide') const currentPath = ref("/zh-CN/guide");
watch( watch(
() => route.path, () => route.path,
(val) => { (val) => {
currentPath.value = val currentPath.value = val;
}, },
{ {
immediate: true, immediate: true,
deep: true, deep: true,
} }
) );
const menus = [ const menus = [
{ {
id: 1, id: 1,
title: '通用', title: "通用",
children: [ children: [
{ {
id: 20, id: 20,
title: '颜色', title: "颜色",
subTitle: 'color', subTitle: "color",
path: '/zh-CN/components/color', path: "/zh-CN/components/color",
}, },
{ {
id: 6, id: 6,
title: '按钮', title: "按钮",
subTitle: 'button', subTitle: "button",
path: '/zh-CN/components/button', path: "/zh-CN/components/button",
}, },
{ {
id: 7, id: 7,
title: '图标', title: "图标",
subTitle: 'iconfont', subTitle: "iconfont",
path: '/zh-CN/components/icon', path: "/zh-CN/components/icon",
}, },
{ {
id: 10, id: 10,
title: '动画', title: "动画",
subTitle: 'animation', subTitle: "animation",
path: '/zh-CN/components/animation', path: "/zh-CN/components/animation",
}, },
], ],
}, },
{ {
id: 1, id: 1,
title: '布局', title: "布局",
children: [ children: [
{
id: 111,
title: '骨架屏',
subTitle: 'skeleton',
path: '/zh-CN/components/skeleton',
},
{ {
id: 4, id: 4,
title: '布局', title: "布局",
subTitle: 'layout', subTitle: "layout",
path: '/zh-CN/components/layout', path: "/zh-CN/components/layout",
}, },
{ {
id: 5, id: 5,
title: '容器', title: "容器",
subTitle: 'container', subTitle: "container",
path: '/zh-CN/components/container', path: "/zh-CN/components/container",
}, },
{ {
id: 11, id: 11,
title: '栅格', title: "栅格",
subTitle: 'grid', subTitle: "grid",
path: '/zh-CN/components/grid', path: "/zh-CN/components/grid",
}, },
{ {
id: 8, id: 8,
title: '面板', title: "面板",
subTitle: 'panel', subTitle: "panel",
path: '/zh-CN/components/panel', path: "/zh-CN/components/panel",
}, },
{ {
id: 9, id: 9,
title: '卡片', title: "卡片",
subTitle: 'card', subTitle: "card",
path: '/zh-CN/components/card', path: "/zh-CN/components/card",
},
{
id: 10,
title: "骨架",
subTitle: "skeleton",
path: "/zh-CN/components/skeleton",
}, },
], ],
}, },
{ {
id: 1, id: 1,
title: '导航', title: "导航",
children: [ children: [
{ {
id: 16, id: 16,
title: '菜单', title: "菜单",
subTitle: 'nav', subTitle: "nav",
path: '/zh-CN/components/menu', path: "/zh-CN/components/menu",
}, },
{ {
id: 17, id: 17,
title: '面包屑', title: "面包屑",
subTitle: 'breadcrumb', subTitle: "breadcrumb",
path: '/zh-CN/components/breadcrumb', path: "/zh-CN/components/breadcrumb",
}, },
{ {
id: 28, id: 28,
title: '选项卡', title: "选项卡",
subTitle: 'tab', subTitle: "tab",
path: '/zh-CN/components/tab', path: "/zh-CN/components/tab",
}, },
{ {
id: 27, id: 27,
title: '下拉菜单', title: "下拉菜单",
subTitle: 'dropdown', subTitle: "dropdown",
path: '/zh-CN/components/dropdown', path: "/zh-CN/components/dropdown",
}, },
{ {
id: 42, id: 42,
title: '返回顶部', title: "返回顶部",
subTitle: 'backtop', subTitle: "backtop",
path: '/zh-CN/components/backtop', path: "/zh-CN/components/backtop",
}, },
], ],
}, },
{ {
id: 1, id: 1,
title: '表单', title: "表单",
children: [ children: [
{ {
id: 36, id: 36,
title: '开关', title: "开关",
subTitle: 'switch', subTitle: "switch",
path: '/zh-CN/components/switch', path: "/zh-CN/components/switch",
}, },
{ {
id: 32, id: 32,
title: '复选框', title: "复选框",
subTitle: 'checkbox', subTitle: "checkbox",
path: '/zh-CN/components/checkbox', path: "/zh-CN/components/checkbox",
}, },
{ {
id: 33, id: 33,
title: '单选框', title: "单选框",
subTitle: 'radio', subTitle: "radio",
path: '/zh-CN/components/radio', path: "/zh-CN/components/radio",
}, },
{ {
id: 34, id: 34,
title: '输入框', title: "输入框",
subTitle: 'input', subTitle: "input",
path: '/zh-CN/components/input', path: "/zh-CN/components/input",
}, },
{ {
id: 341, id: 341,
title: '数字输入框', title: "数字输入框",
subTitle: 'inputNumber', subTitle: "inputNumber",
path: '/zh-CN/components/inputNumber', path: "/zh-CN/components/inputNumber",
}, },
{ {
id: 35, id: 35,
title: '文本域', title: "文本域",
subTitle: 'textarea', subTitle: "textarea",
path: '/zh-CN/components/textarea', path: "/zh-CN/components/textarea",
}, },
{ {
id: 39, id: 39,
title: '下拉选择', title: "下拉选择",
subTitle: 'select', subTitle: "select",
path: '/zh-CN/components/select', path: "/zh-CN/components/select",
}, },
{ {
id: 40, id: 40,
title: '颜色选择器', title: "颜色选择器",
subTitle: 'colorPicker', subTitle: "colorPicker",
path: '/zh-CN/components/colorPicker', path: "/zh-CN/components/colorPicker",
}, },
{ {
id: 29, id: 29,
title: '图标选择器', title: "图标选择器",
subTitle: 'iconPicker', subTitle: "iconPicker",
path: '/zh-CN/components/iconPicker', path: "/zh-CN/components/iconPicker",
}, },
{ {
id: 26, id: 26,
title: '评分', title: "评分",
subTitle: 'rate', subTitle: "rate",
path: '/zh-CN/components/rate', path: "/zh-CN/components/rate",
}, },
{ {
id: 37, id: 37,
title: '滑块', title: "滑块",
subTitle: 'slider', subTitle: "slider",
path: '/zh-CN/components/slider', path: "/zh-CN/components/slider",
}, },
{ {
id: 12, id: 12,
title: '表单', title: "表单",
subTitle: 'form', subTitle: "form",
path: '/zh-CN/components/form', path: "/zh-CN/components/form",
}, },
], ],
}, },
{ {
id: 1, id: 1,
title: '展示', title: "展示",
children: [ children: [
{ {
id: 18, id: 18,
title: '进度', title: "进度",
subTitle: 'progress', subTitle: "progress",
path: '/zh-CN/components/progress', path: "/zh-CN/components/progress",
}, },
{ {
id: 19, id: 19,
title: '时间线', title: "时间线",
subTitle: 'timeline', subTitle: "timeline",
path: '/zh-CN/components/timeline', path: "/zh-CN/components/timeline",
}, },
{ {
id: 21, id: 21,
title: '折叠面板', title: "折叠面板",
subTitle: 'collapse', subTitle: "collapse",
path: '/zh-CN/components/collapse', path: "/zh-CN/components/collapse",
}, },
{ {
id: 22, id: 22,
title: '表格', title: "表格",
subTitle: 'table', subTitle: "table",
path: '/zh-CN/components/table', path: "/zh-CN/components/table",
}, },
{ {
id: 23, id: 23,
title: '头像', title: "头像",
subTitle: 'avatar', subTitle: "avatar",
path: '/zh-CN/components/avatar', path: "/zh-CN/components/avatar",
}, },
{ {
id: 25, id: 25,
title: '空', title: "空",
subTitle: 'empty', subTitle: "empty",
path: '/zh-CN/components/empty', path: "/zh-CN/components/empty",
}, },
{ {
id: 29, id: 29,
title: '分页', title: "分页",
subTitle: 'page', subTitle: "page",
path: '/zh-CN/components/page', path: "/zh-CN/components/page",
}, },
{ {
id: 30, id: 30,
title: '树形组件', title: "树形组件",
subTitle: 'tree', subTitle: "tree",
path: '/zh-CN/components/tree', path: "/zh-CN/components/tree",
}, },
{ {
id: 31, id: 31,
title: '穿梭框', title: "穿梭框",
subTitle: 'transfer', subTitle: "transfer",
path: '/zh-CN/components/transfer', path: "/zh-CN/components/transfer",
}, },
{ {
id: 38, id: 38,
title: '轮播', title: "轮播",
subTitle: 'carousel', subTitle: "carousel",
path: '/zh-CN/components/carousel', path: "/zh-CN/components/carousel",
}, },
{ {
id: 43, id: 43,
title: '数字滚动', title: "数字滚动",
subTitle: 'countUp', subTitle: "countUp",
path: '/zh-CN/components/countup', path: "/zh-CN/components/countup",
}, },
], ],
}, },
{ {
id: 1, id: 1,
title: '辅助', title: "辅助",
children: [ children: [
{ {
id: 13, id: 13,
title: '徽章', title: "徽章",
subTitle: 'badge', subTitle: "badge",
path: '/zh-CN/components/badge', path: "/zh-CN/components/badge",
}, },
{ {
id: 14, id: 14,
title: '区块', title: "区块",
subTitle: 'block', subTitle: "block",
path: '/zh-CN/components/block', path: "/zh-CN/components/block",
}, },
{ {
id: 15, id: 15,
title: '分割', title: "分割",
subTitle: 'line', subTitle: "line",
path: '/zh-CN/components/line', path: "/zh-CN/components/line",
}, },
{ {
id: 24, id: 24,
title: '字段', title: "字段",
subTitle: 'field', subTitle: "field",
path: '/zh-CN/components/field', path: "/zh-CN/components/field",
}, },
{ {
id: 25, id: 25,
title: '文字提示', title: "文字提示",
subTitle: 'tooltip', subTitle: "tooltip",
path: '/zh-CN/components/tooltip', path: "/zh-CN/components/tooltip",
},
{
id: 99,
title: "分步",
subTitle: "step",
path: "/zh-CN/components/step",
}, },
], ],
}, },
{ {
id: 1, id: 1,
title: '反馈', title: "反馈",
children: [ children: [
{ {
id: 90, id: 90,
title: '弹层', title: "弹层",
subTitle: 'modal', subTitle: "modal",
path: '/zh-CN/components/modal', path: "/zh-CN/components/modal",
},{ },
{
id: 91, id: 91,
title: '加载', title: "加载",
subTitle: 'modal', subTitle: "modal",
path: '/zh-CN/components/load', path: "/zh-CN/components/load",
},{ },
{
id: 92, id: 92,
title: '询问', title: "询问",
subTitle: 'confirm', subTitle: "confirm",
path: '/zh-CN/components/confirm', path: "/zh-CN/components/confirm",
},{ },
{
id: 93, id: 93,
title: '消息', title: "消息",
subTitle: 'msg', subTitle: "msg",
path: '/zh-CN/components/msg', path: "/zh-CN/components/msg",
}, },
], ],
}, },
] ];
const selected = ref(1) const selected = ref(1);
const handleClick = function (menu) { const handleClick = function (menu) {
selected.value = menu.id selected.value = menu.id;
router.push(menu.path) router.push(menu.path);
} };
return { return {
menus, menus,
selected, selected,
currentPath, currentPath,
handleClick, handleClick,
} };
}, },
} };
</script> </script>

View File

@ -2885,12 +2885,10 @@ body .layui-table-tips .layui-layer-content {
line-height: 60px; line-height: 60px;
} }
.layui-nav .layui-nav-item a { .layui-nav .layui-nav-item > a {
display: block; display: block;
padding: 0 30px; padding: 0 30px;
color: #fff;
color: rgba(255, 255, 255, 0.7); color: rgba(255, 255, 255, 0.7);
-webkit-transition: all 0.3s;
} }
.layui-nav .layui-this:after, .layui-nav .layui-this:after,
@ -3010,18 +3008,18 @@ body .layui-table-tips .layui-layer-content {
line-height: 42px; line-height: 42px;
} }
.layui-nav-tree .layui-nav-item a { .layui-nav-tree .layui-nav-item > a {
position: relative; position: relative;
height: 42px; height: 42px;
line-height: 42px; line-height: 42px;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
padding: 5px 30px 5px 30px;
} }
.layui-nav-tree .layui-nav-item > a { .layui-nav-tree .layui-nav-item * {
padding-top: 5px; color: rgba(255, 255, 255, 0.7);
padding-bottom: 5px;
} }
.layui-nav-tree .layui-nav-more { .layui-nav-tree .layui-nav-more {

View File

@ -66,8 +66,11 @@ import LayCarouselItem from "./module/carouselItem/index";
import LayColorPicker from "./module/colorPicker/index"; import LayColorPicker from "./module/colorPicker/index";
import LayTooltip from "./module/tooltip/index"; import LayTooltip from "./module/tooltip/index";
import LayInputNumber from "./module/inputNumber/index"; import LayInputNumber from "./module/inputNumber/index";
import LaySkeleton from './module/skeleton/index'; import LaySkeleton from "./module/skeleton/index";
import LaySkeletonItem from './module/skeletonItem/index'; import LaySkeletonItem from "./module/skeletonItem/index";
import LayStep from "./module/step/index";
import LayStepItem from "./module/stepItem/index";
import LaySubMenu from "./module/subMenu/index"
export const components: Record<string, IDefineComponent> = { export const components: Record<string, IDefineComponent> = {
LayRadio, LayRadio,
@ -132,6 +135,9 @@ export const components: Record<string, IDefineComponent> = {
LaySkeleton, LaySkeleton,
LaySkeletonItem, LaySkeletonItem,
LayCountUp, LayCountUp,
LayStep,
LayStepItem,
LaySubMenu
}; };
const install = (app: App, options?: InstallOptions): void => { const install = (app: App, options?: InstallOptions): void => {
@ -206,6 +212,9 @@ export {
LaySkeleton, LaySkeleton,
LaySkeletonItem, LaySkeletonItem,
LayCountUp, LayCountUp,
LayStep,
LayStepItem,
LaySubMenu
}; };
export { layer }; export { layer };

View File

@ -1,39 +1,12 @@
<template> <script lang="ts">
<li export default {
v-if="slots.default" name: "LayMenuItem"
class="layui-nav-item" }
:class="[openKeys.includes(id) && isTree ? 'layui-nav-itemed' : '']" </script>
>
<a href="javascript:void(0)" @click="openHandle">
{{ title }}
<i class="layui-icon layui-icon-down layui-nav-more"></i>
</a>
<dl
class="layui-nav-child"
:class="[
openKeys.includes(id) && !isTree ? 'layui-show' : '',
!isTree ? 'layui-anim layui-anim-upbit' : '',
]"
>
<slot></slot>
</dl>
</li>
<li <script setup lang="ts">
v-else import { defineProps, inject, Ref, useSlots } from "vue";
class="layui-nav-item"
:class="[selectedKey === id ? 'layui-this' : '']"
@click="selectHandle()"
>
<slot v-if="slots.title" name="title"></slot>
<a v-else href="javascript:void(0)">
{{ title }}
</a>
</li>
</template>
<script setup name="LayMenuItem" lang="ts">
import { defineProps, inject, Ref, ref, useSlots } from "vue";
const slots = useSlots(); const slots = useSlots();
const props = defineProps<{ const props = defineProps<{
@ -41,19 +14,22 @@ const props = defineProps<{
title: string; title: string;
}>(); }>();
const isTree = inject("isTree");
const selectedKey: Ref<string> = inject("selectedKey") as Ref<string>; const selectedKey: Ref<string> = inject("selectedKey") as Ref<string>;
const openKeys: Ref<string[]> = inject("openKeys") as Ref<string[]>;
const openHandle = function () {
if (openKeys.value.includes(props.id)) {
openKeys.value.splice(openKeys.value.indexOf(props.id), 1);
} else {
openKeys.value.push(props.id);
}
};
const selectHandle = function () { const selectHandle = function () {
selectedKey.value = props.id; selectedKey.value = props.id;
}; };
</script> </script>
<template>
<li
class="layui-nav-item"
:class="[selectedKey === id ? 'layui-this' : '']"
@click="selectHandle()"
>
<a href="javascript:void(0)">
<slot v-if="slots.default"></slot>
<span v-else>{{ title }}</span>
</a>
</li>
</template>

View File

@ -1,10 +1,27 @@
<template> <template>
<div class="layui-slider-vertical" v-if="vertical"> <div class="layui-slider-vertical" v-if="vertical">
<div ref="rangetracker2" class="layui-slider-vrange" v-if="range"> <div
<div class="layui-slider-vertical-btn"></div> ref="rangetracker2"
<div class="layui-slider-vertical-btn"></div> @mousedown.stop="handle_mousedown"
class="layui-slider-vrange"
v-if="range"
>
<div
:style="{ bottom: verticalRangeValue[1] + '%' }"
class="layui-slider-vertical-btn"
></div>
<div
:style="{ bottom: verticalRangeValue[0] + '%' }"
class="layui-slider-vertical-btn"
></div>
<div class="layui-slider-vertical-line"></div> <div class="layui-slider-vertical-line"></div>
<div class="layui-slider-vertical-rate"></div> <div
:style="{
height: verticalRangeValue[1] - verticalRangeValue[0] + '%',
bottom: verticalRangeValue[0] + '%',
}"
class="layui-slider-vertical-rate"
></div>
</div> </div>
<div <div
@ -84,7 +101,7 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, reactive, Ref, ref } from "vue"; import { defineProps, reactive, Ref, ref, toRef } from "vue";
import { on, off } from "evtd"; import { on, off } from "evtd";
import "./index.less"; import "./index.less";
@ -98,6 +115,8 @@ interface LaySliderProps {
step?: number; step?: number;
disabled?: boolean; disabled?: boolean;
range?: boolean; range?: boolean;
verticalrange?: number[];
standardrange?: number[];
} }
const props = withDefaults(defineProps<LaySliderProps>(), { const props = withDefaults(defineProps<LaySliderProps>(), {
@ -106,17 +125,14 @@ const props = withDefaults(defineProps<LaySliderProps>(), {
disabled: false, disabled: false,
}); });
let rangeValue: Ref<number[]> = ref([0, 0]); // let rangeValue: Ref<number[]> = ref([0, 0]);
if (Array.isArray(props.modelValue)) { let rangeValue: Ref<number[]> | any = toRef(props, "standardrange");
// eslint-disable-next-line vue/no-setup-props-destructure // if (Array.isArray(props.modelValue)) {
rangeValue.value = props.modelValue; // // eslint-disable-next-line vue/no-setup-props-destructure
} // rangeValue.value = props.modelValue;
// }
let verticalRangeValue: Ref<number[]> = ref([0, 0]); let verticalRangeValue: Ref<number[]> | any = toRef(props, "verticalrange");
if (Array.isArray(props.modelValue)) {
// eslint-disable-next-line vue/no-setup-props-destructure
verticalRangeValue.value = props.modelValue;
}
const standardtracker = ref<HTMLElement | null>(null); const standardtracker = ref<HTMLElement | null>(null);
const verticaltracker = ref<HTMLElement | null>(null); const verticaltracker = ref<HTMLElement | null>(null);
@ -227,7 +243,7 @@ const starndardRangeMove = (e: MouseEvent) => {
rangeValue.value[0] = 0; rangeValue.value[0] = 0;
} else { } else {
let rate = (distance / tracker_rect.width) * 100; let rate = (distance / tracker_rect.width) * 100;
let idx = moveNeighbor(Math.floor(rate)); let idx = moveNeighbors(Math.floor(rate), rangeValue);
rangeValue.value[idx] = Math.floor(rate); rangeValue.value[idx] = Math.floor(rate);
if (rangeValue.value[1] > 100) { if (rangeValue.value[1] > 100) {
rangeValue.value[1] = 100; rangeValue.value[1] = 100;
@ -239,12 +255,33 @@ const starndardRangeMove = (e: MouseEvent) => {
emit("update:modelValue", rangeValue.value); emit("update:modelValue", rangeValue.value);
}; };
const verticalRangeMove = (e: MouseEvent) => {}; const verticalRangeMove = (e: MouseEvent) => {
if (!rangetracker2.value) {
function moveNeighbor(rate: number) { return;
let d1 = Math.abs(rate - rangeValue.value[0]); }
let d2 = Math.abs(rate - rangeValue.value[1]); let tracker_rect = rangetracker2.value.getBoundingClientRect();
let origin_bottom = tracker_rect.bottom;
let point_bottom = e.clientY;
let distance = (point_bottom - origin_bottom) * -1;
if (distance < 0) {
rangeValue.value[0] = 0;
} else {
let rate = (distance / tracker_rect.height) * 100;
let idx = moveNeighbors(Math.floor(rate), verticalRangeValue);
verticalRangeValue.value[idx] = Math.floor(rate);
if (verticalRangeValue.value[1] > 100) {
verticalRangeValue.value[1] = 100;
}
if (verticalRangeValue.value[0] < 0) {
verticalRangeValue.value[0] = 0;
}
}
emit("update:modelValue", verticalRangeValue.value);
};
function moveNeighbors(rate: number, rangeValues: any) {
let d1 = Math.abs(rate - rangeValues.value[0]);
let d2 = Math.abs(rate - rangeValues.value[1]);
if (d1 > d2) { if (d1 > d2) {
return 1; return 1;
} else { } else {

296
src/module/step/index.less Normal file
View File

@ -0,0 +1,296 @@
@width-height-pace: 24px;
@step-color: @step-success-color;
@step-fail-color: #FF5722;
@step-primary-color: #1E9FFF;
@step-warning-color: #FFB800;
@step-success-color: #5FB878;
.lay-step{
display: flex;
flex-wrap: nowrap;
.lay-step-item{
flex-grow: 1;
position: relative;
}
.is-item-center{
text-align: center;
}
.lay-step-item-last {
flex-grow: 0 !important;
}
.lay-step-item-pace{
cursor: pointer;
width: @width-height-pace;
height: @width-height-pace;
border: 1px #8D8D8D solid;
border-radius: 50%;
text-align: center;
line-height: @width-height-pace;
background: #FFFFFF;
}
.is-center{
margin: 0 auto;
}
.lay-step-item-active{
border: 1px @step-color solid;
color: @step-color;
}
.lay-step-item-wait{
border: 1px #000000 solid;
color: #000000;
}
.lay-step-item--success {
border: 1px @step-color solid;
color: #FFFFFF;
background: @step-color;
}
.lay-step-item--fail{
border: 1px @step-fail-color solid;
color: #FFFFFF;
background: @step-fail-color;
}
.lay-step-item--warning{
border: 1px @step-warning-color solid;
color: #FFFFFF;
background: @step-warning-color;
}
.lay-step-item--primary{
border: 1px @step-primary-color solid;
color: #FFFFFF;
background: @step-primary-color;
}
.lay-step-item-success {
border: 1px @step-color solid;
color: #FFFFFF;
background: @step-color;
}
.lay-step-item-fail{
border: 1px @step-fail-color solid;
color: #FFFFFF;
background: @step-fail-color;
}
.lay-step-item-warning{
border: 1px @step-warning-color solid;
color: #FFFFFF;
background: @step-warning-color;
}
.lay-step-item-primary{
border: 1px @step-primary-color solid;
color: #FFFFFF;
background: @step-primary-color;
}
.lay-step-item-content{
color: #8D8D8D;
cursor: pointer;
.lay-step-item-content-title{
font-weight: bold;
font-size: 16px;
}
}
.lay-step-item-content-row {
color: #8D8D8D;
position: absolute;
top: 5px;
left: 24px;
width: calc( 100% - 26px );
.lay-step-item-content-title{
word-wrap:break-word;
max-width: calc(100% - 8px);
font-weight: bold;
display: inline-block;
margin-left: 2px;
background: #ffffff;
padding: 0 8px;
font-size: 16px;
}
}
.lay-step-item-content-active{
color: @step-color;
}
.lay-step-item-content--success{
color: @step-color;
}
.lay-step-item-content--fail{
color: @step-fail-color;
}
.lay-step-item-content--warning{
color: @step-warning-color;
}
.lay-step-item-content--primary{
color: @step-primary-color;
}
.lay-step-item-content-wait{
color: #000000;
}
.lay-step-item-content-success{
color: @step-color;
}
.lay-step-item-content-fail{
color: @step-fail-color;
}
.lay-step-item-content-warning{
color: @step-warning-color;
}
.lay-step-item-content-primary{
color: @step-primary-color;
}
.lay-step-item-line{
position: relative;
}
.lay-step-item-line:before {
z-index: -1;
content: "";
position: absolute;
top: 50%;
// transform: translateY(-50%);
display: block;
height: 1px;
width: 100%;
background: #C9C5C5;
}
.is-line-center:before {
left: 50%;
}
.lay-step-item-line-active:before {
transition: background 150ms;
background: @step-success-color !important;
}
.lay-step-item-line-fail:before {
transition: background 150ms;
background: @step-fail-color !important;
}
.lay-step-item-line-warning:before {
transition: background 150ms;
background: @step-warning-color !important;
}
.lay-step-item-line-primary:before {
transition: background 150ms;
background: @step-primary-color !important;
}
.lay-step-simple{
height: 30px;
padding: 0 8px;
line-height: 30px;
color: #ffffff;
background-color: #cecece;
cursor: pointer;
}
.lay-step-item-simple{
padding: 0 18px;
}
.lay-step-item-simple:after{
content: "";
position: absolute;
top: 0;
left: 0;
right: auto;
bottom: auto;
border: 15px solid;
border-color: transparent transparent transparent #cecece;
background-color: transparent;
border-radius: 0;
display: block;
height: auto;
width: auto;
}
.lay-step-item-simple:before{
content: "";
position: absolute;
top: 0;
left: 0;
right: auto;
bottom: auto;
border: 15px solid;
border-color: transparent transparent transparent #cecece;
background-color: transparent;
border-radius: 0;
display: block;
height: auto;
width: auto;
}
.lay-step-item-simple-border:before{
left: 1px;
border-color: transparent transparent transparent #ffffff;
}
.lay-step-item-simple-active {
background-color: #9fd4ae;
}
.lay-step-item-simple-success {
background-color: @step-color;
}
.lay-step-item-simple-fail {
background-color: @step-fail-color;
}
.lay-step-item-simple-warning {
background-color: @step-warning-color;
}
.lay-step-item-simple-primary {
background-color: @step-primary-color;
}
.lay-step-item-simple-active-border:after{
border-color: transparent transparent transparent #9fd4ae !important;
}
.lay-step-item-simple-success-border:after{
border-color: transparent transparent transparent @step-success-color!important;
}
.lay-step-item-simple-fail-border:after{
border-color: transparent transparent transparent @step-fail-color!important;
}
.lay-step-item-simple-warning-border:after{
border-color: transparent transparent transparent @step-warning-color!important;
}
.lay-step-item-simple-primary-border:after{
border-color: transparent transparent transparent @step-primary-color!important;
}
}
.lay-step-column {
height: 100%;
flex-flow: column;
.lay-step-item-line{
position: relative;
height: 100%;
width: 24px;
}
.lay-step-item-line:before {
z-index: -1;
content: "";
position: absolute;
top: 0;
left: 50%;
// transform: translateX(-50%);
display: block;
width: 1px;
height: 100%;
background: #C9C5C5;
}
.lay-step-item-content{
margin-left: 8px;
}
.is-vertical{
display: flex;
}
}

9
src/module/step/index.ts Normal file
View File

@ -0,0 +1,9 @@
import type { App } from "vue";
import Component from "./index.vue";
import type { IDefineComponent } from "../type/index";
Component.install = (app: App) => {
app.component(Component.name || "laySetup", Component);
};
export default Component as IDefineComponent;

61
src/module/step/index.vue Normal file
View File

@ -0,0 +1,61 @@
<template>
<div :class="['lay-step', direction !== 'vertical' ? '' : 'lay-step-column']">
<slot></slot>
</div>
</template>
<script setup name="layStep" lang="ts">
import {
ref,
watch,
provide,
defineProps,
withDefaults,
defineEmits,
} from "vue";
import "./index.less";
export interface LayStepProps {
active?: number;
center?: boolean;
direction?: string;
space?: string;
currentStatus?: string;
composition?: string;
simple?: boolean;
}
const props = withDefaults(defineProps<LayStepProps>(), {
active: 0,
center: false,
direction: "horizontal",
space: "auto",
currentStatus: "success",
composition: "default",
simple: false,
});
const steps = ref([]);
const emits = defineEmits(["onChange"]);
const change = (index) => {
emits("onChange", index - 1);
};
watch(steps, () => {
steps.value.forEach(
(instance: { setIndex: (arg0: any) => void }, index: any) => {
instance.setIndex(index);
}
);
});
provide("LayStep", {
props,
steps,
change,
});
</script>
<style scoped></style>

View File

@ -0,0 +1,9 @@
import type { App } from "vue";
import Component from "./index.vue";
import type { IDefineComponent } from "../type/index";
Component.install = (app: App) => {
app.component(Component.name || "laySetupItem", Component);
};
export default Component as IDefineComponent;

View File

@ -0,0 +1,197 @@
<template>
<div
v-if="!simple"
:class="[
'lay-step-item',
isLast && !isCenter && composition !== 'row' ? 'lay-step-item-last' : '',
isCenter ? 'is-item-center' : '',
isVertical ? 'is-vertical' : '',
]"
:style="{ flexBasis: space, flexGrow: space === 'auto' ? 1 : 0 }"
>
<div
:class="[
!isLast
? isLineActive
? `lay-step-item-line lay-step-item-line-${status || 'active'}`
: 'lay-step-item-line'
: '',
isCenter ? 'is-line-center' : '',
]"
>
<div
:class="[
'lay-step-item-pace',
isActive ? `lay-step-item-active` : '',
isCurrent === index ? `lay-step-item--${currentStatus}` : '',
status ? `lay-step-item-${status}` : '',
isWait ? 'lay-step-item-wait' : '',
isCenter ? 'is-center' : '',
]"
@click="onChange(index + 1)"
>
<slot name="pace">
<template v-if="icon">
<lay-icon :type="icon"></lay-icon>
</template>
<template v-else>
<span v-if="!isActive">{{ index + 1 }}</span>
<lay-icon
v-else
:type="status === 'fail' ? 'layui-icon-close' : 'layui-icon-ok'"
></lay-icon>
</template>
</slot>
</div>
</div>
<div
:class="[
'lay-step-item-content',
composition === 'row' ? 'lay-step-item-content-row' : '',
isActive ? `lay-step-item-content-active` : '',
isCurrent === index ? `lay-step-item-content--${currentStatus}` : '',
status ? `lay-step-item-content-${status}` : '',
isWait ? 'lay-step-item-content-wait' : '',
]"
@click="onChange(index + 1)"
>
<slot>
<div class="lay-step-item-content-title">{{ title }}</div>
<p>{{ content }}</p>
</slot>
</div>
</div>
<div
v-else
:class="[
'lay-step-item',
'lay-step-simple',
!isStart ? 'lay-step-item-simple' : '',
'lay-step-item-simple-border',
isActive ? 'lay-step-item-simple-active' : '',
isCurrent === index ? `lay-step-item-simple-${currentStatus}` : '',
isCurrentBorder === index
? `lay-step-item-simple-${currentStatus}-border`
: '',
isSimpleActive ? 'lay-step-item-simple-active-border' : '',
]"
@click="onChange(index + 1)"
>
<slot>{{ index + 1 }}.{{ title }}</slot>
</div>
</template>
<script setup name="LayStepItem" lang="ts">
import {
ref,
inject,
onMounted,
computed,
getCurrentInstance,
onBeforeUnmount,
reactive,
defineProps,
withDefaults,
} from "vue";
import type { ComputedRef } from "vue";
export interface LayStepItemProps {
title?: string;
content?: string;
icon?: string;
status?: string;
}
const props = withDefaults(defineProps<LayStepItemProps>(), {
title: "",
content: "",
icon: "",
status: "",
});
const index = ref(-1);
const parents: any = inject("LayStep");
const currentInstance: any = getCurrentInstance();
const setIndex = (val: number) => {
index.value = val;
};
const onChange = (index) => {
parents.change(index);
};
const stepsCount = computed(() => {
return parents.steps.value.length;
});
const currentStatus = computed(() => {
return parents.props.currentStatus;
});
const simple = computed(() => {
return parents.props.simple;
});
const composition = computed(() => {
return parents.props.composition;
});
const isCurrent = computed(() => {
return parents.props.active;
});
const isCurrentBorder = computed(() => {
return parents.props.active + 1;
});
const space = computed(() => {
return parents.props.space;
});
const isVertical = computed(() => {
return parents.props.direction === "vertical";
});
const isCenter = computed(() => {
return parents.props.center;
});
const isLineActive: ComputedRef<boolean> = computed(() => {
return index.value <= parents.props.active - 1;
});
const isWait: ComputedRef<boolean> = computed(() => {
return index.value === parents.props.active + 1;
});
const isSimpleActive: ComputedRef<boolean> = computed(() => {
return index.value - 1 <= parents.props.active;
});
const isActive: ComputedRef<boolean> = computed(() => {
return index.value <= parents.props.active;
});
const isLast: ComputedRef<boolean> = computed(() => {
return (
parents.steps.value[stepsCount.value - 1]?.itemId === currentInstance.uid
);
});
const isStart: ComputedRef<boolean> = computed(() => {
return parents.steps.value[0]?.itemId === currentInstance.uid;
});
const stepItemState = reactive({
itemId: computed(() => currentInstance?.uid),
setIndex,
});
parents.steps.value = [...parents.steps.value, stepItemState];
onMounted(() => {});
onBeforeUnmount(() => {
parents.steps.value = parents.steps.value.filter(
(instance: { itemId: any }) => instance.itemId !== currentInstance.uid
);
});
</script>

View File

@ -0,0 +1,9 @@
import type { App } from "vue";
import Component from "./index.vue";
import type { IDefineComponent } from "../type/index";
Component.install = (app: App) => {
app.component(Component.name || "laySubMenu", Component);
};
export default Component as IDefineComponent;

View File

@ -0,0 +1,57 @@
<script lang="ts">
export default {
name: "LaySubMenu",
};
</script>
<script setup lang="ts">
import { computed, defineProps, inject, Ref, useSlots } from "vue";
const slots = useSlots();
const props = defineProps<{
id: string;
title: string;
}>();
const isTree = inject("isTree");
const selectedKey: Ref<string> = inject("selectedKey") as Ref<string>;
const openKeys: Ref<string[]> = inject("openKeys") as Ref<string[]>;
const openHandle = function () {
if (openKeys.value.includes(props.id)) {
openKeys.value.splice(openKeys.value.indexOf(props.id), 1);
} else {
openKeys.value.push(props.id);
}
};
const isOpen = computed(() => {
return openKeys.value.includes(props.id);
});
</script>
<template>
<li
class="layui-nav-item"
:class="[isOpen && isTree ? 'layui-nav-itemed' : '']"
>
<a href="javascript:void(0)" @click="openHandle()">
<slot v-if="slots.title" name="title"></slot>
<span v-else>{{ title }}</span>
<i
:class="[isOpen && !isTree ? 'layui-nav-mored' : '']"
class="layui-icon layui-icon-down layui-nav-more"
></i>
</a>
<dl
class="layui-nav-child"
:class="[
isOpen && !isTree ? 'layui-show' : '',
!isTree ? 'layui-anim layui-anim-upbit' : '',
]"
>
<slot></slot>
</dl>
</li>
</template>

View File

@ -1,6 +1,9 @@
<template> <template>
<li class="layui-timeline-item"> <li class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis"></i> <i class="layui-icon layui-timeline-axis" v-if="slot.dot">
<slot name="dot"></slot>
</i>
<i class="layui-icon layui-timeline-axis" v-else></i>
<div class="layui-timeline-content layui-text"> <div class="layui-timeline-content layui-text">
<div v-if="simple" class="layui-timeline-title"> <div v-if="simple" class="layui-timeline-title">
{{ title }} {{ title }}
@ -20,7 +23,9 @@ export default {
</script> </script>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps } from "vue"; import { defineProps, useSlots } from "vue";
const slot = useSlots();
export interface LayTimelineItemProps { export interface LayTimelineItemProps {
title: string; title: string;

180
src/module/tree/index.less Normal file
View File

@ -0,0 +1,180 @@
.layui-tree {
line-height: 22px;
}
.layui-tree .layui-form-checkbox {
margin: 0 !important;
}
.layui-tree-set {
width: 100%;
position: relative;
}
.layui-tree-pack {
display: none;
padding-left: 20px;
position: relative;
}
.layui-tree-iconClick,
.layui-tree-main {
display: inline-block;
vertical-align: middle;
}
.layui-tree-line .layui-tree-pack {
padding-left: 27px;
}
.layui-tree-line .layui-tree-set .layui-tree-set:after {
content: "";
position: absolute;
top: 14px;
left: -9px;
width: 17px;
height: 0;
border-top: 1px dotted #c0c4cc;
}
.layui-tree-entry {
position: relative;
padding: 3px 0;
height: 20px;
white-space: nowrap;
}
.layui-tree-entry:hover {
background-color: #eee;
}
.layui-tree-line .layui-tree-entry:hover {
background-color: rgba(0, 0, 0, 0);
}
.layui-tree-line .layui-tree-entry:hover .layui-tree-txt {
color: #999;
text-decoration: underline;
transition: 0.3s;
}
.layui-tree-main {
cursor: pointer;
padding-right: 10px;
}
.layui-tree-line .layui-tree-set:before {
content: "";
position: absolute;
top: 0;
left: -9px;
width: 0;
height: 100%;
border-left: 1px dotted #c0c4cc;
}
.layui-tree-line .layui-tree-set.layui-tree-setLineShort:before {
height: 13px;
}
.layui-tree-line .layui-tree-set.layui-tree-setHide:before {
height: 0;
}
.layui-tree-iconClick {
position: relative;
height: 20px;
line-height: 20px;
margin: 0 10px;
color: #c0c4cc;
}
.layui-tree-icon {
height: 12px;
line-height: 12px;
width: 12px;
text-align: center;
border: 1px solid #c0c4cc;
}
.layui-tree-iconClick .layui-icon {
font-size: 18px;
}
.layui-tree-icon .layui-icon {
font-size: 12px;
color: #666;
}
.layui-tree-iconArrow {
padding: 0 5px;
}
.layui-tree-iconArrow:after {
content: "";
position: absolute;
left: 4px;
top: 3px;
z-index: 100;
width: 0;
height: 0;
border-width: 5px;
border-style: solid;
border-color: transparent transparent transparent #c0c4cc;
transition: 0.5s;
}
.layui-tree-btnGroup,
.layui-tree-editInput {
position: relative;
vertical-align: middle;
display: inline-block;
}
.layui-tree-spread
> .layui-tree-entry
> .layui-tree-iconClick
> .layui-tree-iconArrow:after {
transform: rotate(90deg) translate(3px, 4px);
}
.layui-tree-txt {
display: inline-block;
vertical-align: middle;
color: #555;
}
.layui-tree-search {
margin-bottom: 15px;
color: #666;
}
.layui-tree-btnGroup .layui-icon {
display: inline-block;
vertical-align: middle;
padding: 0 2px;
cursor: pointer;
}
.layui-tree-btnGroup .layui-icon:hover {
color: #999;
transition: 0.3s;
}
.layui-tree-entry:hover .layui-tree-btnGroup {
visibility: visible;
}
.layui-tree-editInput {
height: 20px;
line-height: 20px;
padding: 0 3px;
border: none;
background-color: rgba(0, 0, 0, 0.05);
}
.layui-tree-emptyText {
text-align: center;
color: #999;
}

View File

@ -1,9 +1,3 @@
<!--
* @Date: 2021-10-16 13:22:38
* @LastEditors: 落小梅
* @LastEditTime: 2021-10-16 13:53:14
* @FilePath: \layui-vue\src\module\tree\new-tree\index.vue
-->
<script lang="ts"> <script lang="ts">
export default { export default {
name: "LayTree", name: "LayTree",
@ -16,6 +10,7 @@ import TreeNode from "./TreeNode.vue";
import { computed } from "vue"; import { computed } from "vue";
import { useTree } from "./useTree"; import { useTree } from "./useTree";
import { TreeData } from "./tree"; import { TreeData } from "./tree";
import "./index.less";
type StringFn = () => string; type StringFn = () => string;
type StringOrNumber = string | number; type StringOrNumber = string | number;