发布 8.0

This commit is contained in:
神仙都没用 2025-02-19 11:41:01 +08:00
parent 719fb21fda
commit 68cd190481
557 changed files with 24064 additions and 20309 deletions

View File

@ -0,0 +1,305 @@
---
description: cl-adv-search 组件示例
globs: *.tsx, *.ts, *.vue
---
## 起步 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>base</el-tag>
<span>起步</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['adv-search/base.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="起步" width="80%">
<cl-crud ref="Crud">
<cl-row>
<!--【很重要】高级搜索组件按钮 -->
<cl-adv-btn />
</cl-row>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
<!--【很重要】高级搜索组件 -->
<cl-adv-search ref="AdvSearch" />
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useAdvSearch, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
// cl-adv-search 配置
//【很重要】该组件基于 cl-form 故很多示例都可复用
const AdvSearch = useAdvSearch({
// 配置如 cl-form 一样
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input',
props: {
clearable: true
}
}
},
{
label: '手机号',
prop: 'phone',
component: {
name: 'el-input',
props: {
clearable: true
}
}
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true,
checkStrictly: true,
options: dict.get('occupation')
}
}
}
]
});
function refresh(params?: any) {
Crud.value?.refresh(params);
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 自定义 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>custom</el-tag>
<span>自定义</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['adv-search/custom.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="自定义" width="80%">
<cl-crud ref="Crud">
<cl-row>
<!--【很重要】高级搜索组件按钮 -->
<cl-adv-btn>更多搜索</cl-adv-btn>
</cl-row>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
<!--【很重要】高级搜索组件 -->
<cl-adv-search ref="AdvSearch">
<!-- 自定义按钮 -->
<template #slot-btn>
<el-button @click="toSearch">自定义</el-button>
</template>
</cl-adv-search>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useAdvSearch, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
// cl-adv-search 配置
//【很重要】该组件基于 cl-form 故很多示例都可复用
const AdvSearch = useAdvSearch({
// 配置如 cl-form 一样
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input',
props: {
clearable: true
}
}
},
{
label: '手机号',
prop: 'phone',
component: {
name: 'el-input',
props: {
clearable: true
}
}
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true,
checkStrictly: true,
options: dict.get('occupation')
}
}
}
],
title: '更多搜索',
size: '50%',
op: ['close', 'search', 'slot-btn']
});
function refresh(params?: any) {
Crud.value?.refresh(params);
}
// 自定义搜索
function toSearch() {
refresh({ page: 1 });
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```

1281
.cursor/rules/crud.mdc Normal file

File diff suppressed because it is too large Load Diff

1819
.cursor/rules/form.mdc Normal file

File diff suppressed because it is too large Load Diff

464
.cursor/rules/module.mdc Normal file
View File

@ -0,0 +1,464 @@
---
description: module | plugins 模块、插件
globs:
---
# 模块/插件开发
## 目录结构
在 `src/modules` 或 `src/plugins` 下添加一个目录 `demo`
```js
demo
├──pages // 页面路由
├──views // 视图路由
├──hooks // 常用函数
├──components // 常用组件
├──directives // 指令
├──static // 静态文件目录
├──store // 状态管理
├──... // 其他自定义文件
├──config.ts // 配置文件
└──index.ts // 入口文件
```
::: warning
约定的目录名称不可修改,但可自行添加或者删除。
:::
## pages、views
1. 页面参与权限控制,所以不主动注册目录下的路由,通过 `菜单列表` 中配置注册。或者在 `config.ts` 中手动配置:
```js
import { type ModuleConfig } from "/@/cool";
export default (): ModuleConfig => {
return {
views: [
{
path: "/demo",
meta: {
label: "测试",
},
component: () => import("./views/demo.vue"),
},
],
pages: [
{
path: "/demo2",
meta: {
label: "测试",
},
component: () => import("./pages/demo.vue"),
},
],
};
};
```
2. 使页面参与路由缓存,配置 `name` 参数
:::warning
`path` 与 `name` 的匹配规则:
- /demo/t1 = demo-t1
- /demo/t1-det = demo-t1-det
:::
方式 1
```html
<script lang="ts" setup>
defineOptions({
name: "demo",
});
</script>
```
方式 2
```html
<script lang="ts">
export default defineComponent({
name: "demo",
});
</script>
```
## components
目录下的组件,全局注册配置方法如下:
```js
import { ModuleConfig } from "/@/cool";
export default (): ModuleConfig => {
return {
components: [
import("./components/demo.vue"),
import("./components/demo1.vue"),
],
};
};
```
## directives
`directives` 会以目录下的文件名分别注册指令
```ts
// demo/directives/test.ts
export default {
created(el, binding) {},
mounted() {},
...
};
```
使用
```html
<div v-test></div>
```
## store
使用 `pinia` 的推荐写法:
```ts
import { defineStore } from "pinia";
import { ref } from "vue";
export const useTestStore = defineStore("test", function () {
const count = ref(0);
function add() {
count.value += 1;
}
return {
count,
add,
};
});
```
使用
```ts
import { useTestStore } from "/$/demo/store";
const test = useTestStore();
test.add();
console.log(test.count); // 1
```
::: tip
参考 `base` 模块下 `store` 的导出方式
:::
## config.ts
模块的配置,程序运行时会读取该文件。
- 全局组件、路由的导入
- 事件钩子
输入 `module-config` 关键字,`vscode` 中会自动生成:
```ts
import { ModuleConfig } from "/@/cool";
import { Vue } from "vue";
export default (): ModuleConfig => {
return {
// 是否启用
enable: true,
// 插件名称
label: "插件名称",
// 插件描述
description: "插件描述",
// 作者
author: "作者",
version: "1.0.0",
updateTime: "2024-02-02",
logo: "",
// 忽略
ignore: {
// 忽略进度条的请求
NProgress: [
"/base/open/eps",
"/base/comm/person",
"/base/comm/permmenu",
"/base/comm/upload",
"/base/comm/uploadMode",
],
// 忽略 token 的路由
token: ["/login", "/401", "/403", "/404", "/500", "/502"],
},
// 排序
order: 0,
// 配置参数
options: {
name: "神仙",
},
// 示例页面
demo: [
{
name: "基础用法",
component: () => import("..."),
},
],
// 注册全局组件
components: [],
// 视图路由
views: [],
// 页面路由
pages: [],
// 顶部工具栏
toolbar: {
order: 1,
pc: true, // 是否在 pc 端显示
h5: true, // 是否在 h5 端显示
component: import("./components/index.vue"),
},
// 注入全局组件
index: {
component: import("./components/index.vue"),
},
// 安装时触发
install(app: Vue) {},
// 加载时触发
onLoad(events) {},
};
};
```
- order 模块加载顺序,值越大越先
- options 提供给外部使用的参数配置:
```ts
import { ModuleConfig } from "/@/cool";
export default (): ModuleConfig => {
return {
options: {
// 尺寸
size: 120,
// 显示文案
text: "选择文件",
// 限制
limit: {
// 上传最大数量
upload: 9,
// 文件空间选择数
select: 9,
// 上传大小限制
size: 100,
},
},
};
};
```
获取方式:
```ts
import { module } from "/@/cool";
const config = module.config("模块名");
```
- components 提供全局的组件:
```ts
import type { ModuleConfig } from "/@/cool";
export default (): ModuleConfig => {
return {
components: [import("./components/test.vue")],
};
};
```
批量导入可以使用 [import.meta.glob](mdc:https:/vitejs.dev/guide/features.html#glob-import) 方法:
```ts
import { ModuleConfig } from "/@/cool";
export default (): ModuleConfig => {
return {
components: Object.values(import.meta.glob("./components/**/*")),
};
};
```
- views 全局注册的视图路由,存放在 `/` 中的子路由 `children`
```ts
import { ModuleConfig } from "/@/cool";
export default (): ModuleConfig => {
return {
views: [
{
path: "/test",
meta: {
label: "测试中心",
},
component: () => import("./views/test.vue"),
},
],
};
};
```
- pages 全局注册的页面路由:
```ts
import { ModuleConfig } from "/@/cool";
export default (): ModuleConfig => {
return {
pages: [
{
path: "/test",
meta: {
label: "测试中心",
},
component: () => import("./views/test.vue"),
},
],
};
};
```
- install 模块安装时触发。用于预先处理:
```ts
import { ModuleConfig } from "/@/cool";
import { Vue } from "vue";
export default (): ModuleConfig => {
return {
install(app: Vue) {
// 注册组件
app.component("test", Test);
// 注册指令
app.directive("focus", {
created(el, bind) {},
});
},
};
};
```
- onLoad 模块安装时触发,预先加载数据,如菜单配置、用户信息:
1. 使用 `await` 等待加载完成后往下执行
2. 可往下模块导出某个方法和变量,如 `hasToken` 验证是否有登陆
```ts
import { ModuleConfig } from "/@/cool";
import { Vue } from "vue";
export default (): ModuleConfig => {
return {
async onLoad() {
const { user, menu } = useStore();
if (user.token) {
// 获取用户信息
user.get();
// 获取菜单权限
await menu.get();
}
return {
async hasToken(cb: () => Promise<any> | void) {
if (user.token) {
if (cb) await cb();
}
},
};
},
};
};
```
其他模块中接收 `hasToken` 方法:
```ts
import { ModuleConfig } from "/@/cool";
import { useDict } from "./index";
export default (): ModuleConfig => {
return {
onLoad({ hasToken }) {
const { dict } = useDict();
hasToken(() => {
dict.refresh();
});
},
};
};
```
## index.ts
该模块需要对外开放的变量及方法,方便于别人直接使用:
```ts
// modules/test/index.ts
import { useStore } from "./store";
export function useTest() {
return {
// 导出 pinia
...useStore(),
// 自定义方法
test() {},
// 自定义变量
data: {
description: "数据描述",
},
};
}
```
导出命名规则 `useBase` `useDemo` `useDict` use + 模块名
使用:
```ts
import { useTest } from "/$/test";
const { data, test } = useTest();
```

743
.cursor/rules/search.mdc Normal file
View File

@ -0,0 +1,743 @@
---
description: cl-search 组件示例
globs: *.tsx, *.ts, *.vue
---
## 起步 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>base</el-tag>
<span>起步</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['search/base.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="起步" width="80%">
<cl-crud ref="Crud">
<cl-row>
<!--【很重要】搜索组件 -->
<cl-search ref="Search" />
</cl-row>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useSearch, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
// cl-search 配置
//【很重要】该组件基于 cl-form 故很多示例都可复用
const Search = useSearch({
// 配置如 cl-form 一样
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input',
props: {
clearable: true,
// 值改变的时候刷新列表
onChange(val: string) {
refresh({
name: val,
page: 1
});
}
}
}
},
{
label: '手机号',
prop: 'phone',
component: {
name: 'el-input',
props: {
clearable: true
}
}
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true,
checkStrictly: true,
options: dict.get('occupation')
}
}
}
],
onChange(data, prop) {
console.log(data, prop);
}
});
function refresh(params?: any) {
Crud.value?.refresh(params);
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 折叠 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>collapse</el-tag>
<span>折叠</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['search/collapse.vue']" />
<!-- 折叠表格组件 -->
<cl-dialog v-model="visible" title="折叠" width="80%">
<cl-crud ref="Crud">
<!--【collapse】折叠参数【inline】是否行内 -->
<cl-search ref="Search" reset-btn collapse :inline="false" />
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-12-26</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useSearch, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { range } from 'lodash-es';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
// cl-search 配置
const Search = useSearch({
items: [
...range(20).map(i => {
return {
label: '输入框',
prop: `T${i + 1}`,
component: {
name: 'el-input'
}
};
})
]
});
function refresh(params?: any) {
Crud.value?.refresh(params);
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
x
```
## 自定义 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>custom</el-tag>
<span>自定义</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['search/custom.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="自定义" width="80%">
<cl-crud ref="Crud">
<cl-row>
<!--【很重要】搜索组件 -->
<cl-search
ref="Search"
:reset-btn="true"
:on-load="onLoad"
:on-search="onSearch"
>
<!-- 自定义按钮 -->
<template #buttons="scope">
<el-button @click="toSearch(scope)">自定义按钮</el-button>
</template>
</cl-search>
</cl-row>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useSearch, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { ElMessage } from 'element-plus';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
// cl-search 配置
//【很重要】该组件基于 cl-form 故很多示例都可复用
const Search = useSearch({
// 配置如 cl-form 一样
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input',
props: {
clearable: true,
// 值改变的时候刷新列表
onChange(val: string) {
refresh({
name: val,
page: 1
});
}
}
}
},
{
label: '手机号',
prop: 'phone',
component: {
name: 'el-input',
props: {
clearable: true
}
}
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true,
checkStrictly: true,
options: dict.get('occupation')
}
}
}
]
});
function refresh(params?: any) {
Crud.value?.refresh(params);
}
// cl-search 初始化
function onLoad(data: any) {
data.name = '白小纯';
}
// cl-search 配置 onSearch 后,必须使用 next 方法继续请求
function onSearch(data: any, { next }: { next: (data: any) => void }) {
ElMessage.info('开始搜索');
// 这边可以处理其他事务
next(data);
}
// 自定义搜索data 为表单数据
function toSearch(data: any) {
ElMessage.info('自定义搜索');
refresh({
page: 1,
...data
});
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 布局 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>layout</el-tag>
<span>布局</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['search/layout.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="布局" width="80%">
<cl-crud ref="Crud">
<!--【很重要】搜索组件 -->
<cl-search ref="Search" :reset-btn="true" />
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useSearch, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
// cl-search 配置
//【很重要】该组件基于 cl-form 故很多示例都可复用
const Search = useSearch({
// 取消行内表单模式
inline: false,
// 表单参数
props: {
labelPosition: 'top'
},
// 配置如 cl-form 一样
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input',
props: {
clearable: true,
// 值改变的时候刷新列表
onChange(val: string) {
refresh({
name: val,
page: 1
});
}
}
}
},
{
label: '手机号',
prop: 'phone',
component: {
name: 'el-input',
props: {
clearable: true
}
}
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true,
checkStrictly: true,
options: dict.get('occupation')
}
}
}
]
});
function refresh(params?: any) {
Crud.value?.refresh(params);
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 使用插件 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>plugin</el-tag>
<span>使用插件</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['search/layout.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="使用插件" width="80%">
<cl-crud ref="Crud">
<cl-row>
<cl-flex1 />
<!--【很重要】搜索组件 -->
<cl-search ref="Search" />
</cl-row>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useSearch, useTable } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { Plugins } from '/#/crud';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
}
]
});
// cl-search 配置
const Search = useSearch({
// 【很重要】自动读取 service 下的 search 数据
plugins: [
Plugins.Search.setAuto({
customComponent(field) {
if (field.propertyName == 'name') {
return {
name: 'cl-select',
props: {
options: [
{
label: '张三',
value: '1'
},
{
label: '李四',
value: '2'
}
]
}
};
}
// null 则不操作,按系统默认操作
return null;
}
})
]
});
function refresh(params?: any) {
Crud.value?.refresh(params);
}
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```

2117
.cursor/rules/table.mdc Normal file

File diff suppressed because it is too large Load Diff

716
.cursor/rules/upsert.mdc Normal file
View File

@ -0,0 +1,716 @@
---
description: cl-upsert 组件示例
globs: *.tsx, *.ts, *.vue
---
## 起步 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>base</el-tag>
<span>起步</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['upsert/base.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="起步" width="80%">
<cl-crud ref="Crud">
<cl-row>
<!-- 打开新增表单的按钮 -->
<cl-add-btn />
</cl-row>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
<!--【很重要】新增、编辑的表单组件 -->
<cl-upsert ref="Upsert" />
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable, useUpsert } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
},
{
type: 'op',
// edit 打开编辑表单
buttons: ['edit', 'delete']
}
]
});
// cl-upsert 配置
//【很重要】该组件基于 cl-form 故很多示例都可复用
const Upsert = useUpsert({
// 配置如 cl-form 一样
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input'
}
},
{
label: '手机号',
prop: 'phone',
component: {
name: 'el-input'
}
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true,
checkStrictly: true,
options: dict.get('occupation')
}
}
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 打开、关闭、提交等事件 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>event</el-tag>
<span>打开、关闭、提交等事件</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['upsert/event.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="事件" width="80%">
<cl-crud ref="Crud">
<cl-row>
<!-- 打开新增表单的按钮 -->
<cl-add-btn />
</cl-row>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
<!--【很重要】新增、编辑的表单组件 -->
<cl-upsert ref="Upsert" />
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable, useUpsert } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { useCool } from '/@/cool';
const { service } = useCool();
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
},
{
type: 'op',
// edit 打开编辑表单
buttons: ['edit', 'delete']
}
]
});
// cl-upsert 配置
const Upsert = useUpsert({
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input'
}
},
{
label: '手机号',
prop: 'phone',
component: {
name: 'el-input'
}
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true,
checkStrictly: true,
options: dict.get('occupation')
}
}
}
],
// 以下事件按顺序触发
// 弹窗打开的事件,这个时候还未有表单数据
onOpen() {
console.log('onOpen');
},
// 获取详情,编辑的时候会触发
async onInfo(data, { next, done }) {
// 不配置 onInfo 的时候默认执行 next(data),调用 service 的 info 接口获取详情
// next(data);
// 自定义,需要对请求数据进行处理或者返回处理后的数据
const res = await next({
id: data.id
});
done({
...res,
name: `[${res.name}]`
});
},
// 弹窗打开后,已经得到了表单数据
onOpened(data) {
// 判定是否编辑模式
if (Upsert.value?.mode == 'update') {
// 对数据处理
data.phone += '000';
}
},
// 提交事件的钩子
// data 表单提交数据
// next 继续往下执行
// done 关闭加载
// close 关闭弹窗
async onSubmit(data, { next, done, close }) {
// 不配置 onSubmit 的时候默认执行 next(data),提交后会去请求 service 的 update/add 接口
// next(data);
// 自定义如下
// 场景1提交时对参数额外的处理
// next({
// ...data,
// status: 1,
// createTime: dayjs().format("YYYY-MM-DD")
// });
// 场景2提交前、后的操作
// 之前,模拟获取 userId
const userId = await service.base.sys.user.info({ id: 1 });
// 返回值
const res = await next({
userId,
data
});
// 之后
// console.log(res);
},
// 关闭时触发
onClose(action, done) {
// action 关闭的类型
console.log('action', action);
// 使用 done 关闭窗口
done();
},
// 关闭后触发
onClosed() {
console.log('onClosed');
}
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## Hook的使用 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>hook</el-tag>
<span>Hook的使用</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['upsert/hook/index.vue', 'upsert/hook/reg-pca2.ts']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="Hook的使用" width="80%">
<cl-crud ref="Crud">
<cl-row>
<!-- 打开新增表单的按钮 -->
<cl-add-btn />
</cl-row>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
<!--【很重要】新增、编辑的表单组件 -->
<cl-upsert ref="Upsert" />
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable, useUpsert } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '省市区',
prop: 'pca',
formatter(row) {
return row.province ? row.province + '-' + row.city + '-' + row.district : '-';
},
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
},
{
type: 'op',
buttons: ['edit', 'delete']
}
]
});
// cl-upsert 配置
const Upsert = useUpsert({
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input'
}
},
{
label: '手机号',
prop: 'phone',
component: {
name: 'el-input'
}
},
{
label: '省市区',
prop: 'pca2',
//【很重要】hook 参数配置
hook: {
bind(value, { form }) {
// 将3个参数合并成一个数组带入级联选择器
return [form.province, form.city, form.district];
},
submit(value, { form, prop }) {
// 提交的时候将数组拆分成3个字段提交
const [province, city, district] = value || [];
form.province = province;
form.city = city;
form.district = district;
// 删除 prop 绑定值
form[prop] = undefined;
}
},
// 注册到全局后可直接使用,注册代码看 ./reg-pca2.ts
// hook: "pca2",
component: {
name: 'cl-distpicker'
}
},
{
label: '标签',
prop: 'labels',
//【很重要】使用内置方法,避免一些辣鸡后端要你这么传给他
hook: {
// labels 的数据为 1,2,3
// 绑定的时候将 labels 按 , 分割成数组
bind: ['split', 'number'],
// 提交的时候将 labels 拼接成字符串
submit: ['join']
},
component: {
name: 'el-select',
props: {
multiple: true
},
options: [
{
label: '帅气',
value: 1
},
{
label: '多金',
value: 2
},
{
label: '有才华',
value: 3
}
]
}
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true,
checkStrictly: true,
options: dict.get('occupation')
}
}
}
]
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```
## 新增、编辑、详情模式 示例
```vue
<template>
<div class="scope">
<div class="h">
<el-tag size="small" effect="dark" disable-transitions>mode</el-tag>
<span>新增、编辑、详情模式</span>
</div>
<div class="c">
<el-button @click="open">预览</el-button>
<demo-code :files="['upsert/mode.vue']" />
<!-- 自定义表格组件 -->
<cl-dialog v-model="visible" title="不同模式" width="80%">
<cl-crud ref="Crud">
<cl-row>
<!-- 打开新增表单的按钮 -->
<cl-add-btn />
</cl-row>
<cl-row>
<cl-table ref="Table" />
</cl-row>
<cl-row>
<cl-flex1 />
<cl-pagination />
</cl-row>
<!--【很重要】新增、编辑的表单组件 -->
<cl-upsert ref="Upsert" />
</cl-crud>
</cl-dialog>
</div>
<div class="f">
<span class="date">2024-01-01</span>
</div>
</div>
</template>
<script setup lang="ts">
import { useCrud, useTable, useUpsert } from '@cool-vue/crud';
import { ref } from 'vue';
import { useDict } from '/$/dict';
import { ElMessage } from 'element-plus';
const { dict } = useDict();
// cl-crud 配置
const Crud = useCrud(
{
service: 'test'
},
app => {
app.refresh();
}
);
// cl-table 配置
const Table = useTable({
autoHeight: false,
contextMenu: ['refresh'],
columns: [
{
label: '姓名',
prop: 'name',
minWidth: 140
},
{
label: '手机号',
prop: 'phone',
minWidth: 140
},
{
label: '工作',
prop: 'occupation',
dict: dict.get('occupation'),
minWidth: 140
},
{
label: '创建时间',
prop: 'createTime',
minWidth: 170,
sortable: 'desc'
},
{
type: 'op',
width: 240,
buttons: ['info', 'edit', 'delete']
}
]
});
// cl-upsert 配置
const Upsert = useUpsert({
items: [
{
label: '姓名',
prop: 'name',
component: {
name: 'el-input'
}
},
//【很重要】只有返回方法的时候才能使用 Upsert
() => {
return {
label: '手机号',
prop: 'phone',
// 新增的时候隐藏
// hidden: Upsert.value?.mode == "add",
component: {
name: 'el-input',
props: {
// 编辑的时候禁用
disabled: Upsert.value?.mode == 'update'
}
}
};
},
{
label: '工作',
prop: 'occupation',
component: {
name: 'cl-select',
props: {
tree: true,
checkStrictly: true,
options: dict.get('occupation')
}
}
}
],
onOpen() {
ElMessage.info(`当前模式:` + Upsert.value?.mode);
}
});
const visible = ref(false);
function open() {
visible.value = true;
}
</script>
```

74
.cursorrules Normal file
View File

@ -0,0 +1,74 @@
# 项目背景
- 库typescript、javaScript、scss、vue、tailwind
- 框架cool-admin-vue
- 项目版本8.x
# 项目目录
├── .vscode(代码片段,根据关键字可以快速地生成代码)
├── public(静态资源文件)
├── packages(源码包:@cool-vue/crud、@cool-vue/vite-plugin)
├── build
│ └── cool()
│ │ └── eps.json(Eps 配置文件)
│ │ └── eps.d.ts(Eps 描述文件)
├── src
│ └── cool(核心文件)
│ └── modules(项目模块)
│ │ └── base(基础模块)
│ │ └── demo(示例模块)
│ │ └── dict(字典模块)
│ │ └── helper(辅助模块)
│ │ └── recycle(回收站模块)
│ │ └── space(cl-upload-space 文件空间模块)
│ │ └── task(任务模块)
│ │ └── user(用户模块)
│ └── plugins(项目插件)
│ │ └── crud(cl-crud、@cool-vue/crud)
│ │ └── distpicker(cl-distpicker、省市区选择器)
│ │ └── echarts(图标)
│ │ └── editor-preview(编辑器预览组件)
│ │ └── editor-wange(wang富文本编辑器)
│ │ └── element-ui(element-plus 组件)
│ │ └── excel(excel导入、导出组件)
│ │ └── i18n(多语言)
│ │ └── iconfont(iconfont 图标)
│ │ └── theme(cl-theme 主题组件)
│ │ └── upload(cl-upload 文件上传组件)
│ │ └── view(cl-view-group、cl-view-head 视图组件)
│ └── config
│ │ └── index.ts(默认配置)
│ │ └── dev.ts(开发环境)
│ │ └── prod.ts(生产环境)
│ │ └── proxy.ts(代理配置)
│ └── App.vue(入口文件)
│ └── main.ts(入口文件)
├── package.json(依赖管理,项目信息)
└── ...
模块、插件目录
├── modules/plugins
│ └── base(模块名)
│ │ └── components(全局组件)
│ │ └── directives(全局指令)
│ │ └── locales(国际化)
│ │ └── router(路由)
│ │ └── store(状态管理)
│ │ └── utils(工具函数)
│ │ └── views(视图)
│ │ └── config.ts(必须,模块的配置)
│ │ └── index.ts(模块导出)
# 其它
- 文件、组件命名用 - 连接student-info.vue
- service 的描述类型,查看 build/cool/eps.d.ts 描述文件
- 创建模块、插件代码需要读取.cursor/rules的module.mdc其它的rules根据需要进行参考
# import 引用别名
- "/@" 对应 "./src"
- "/$" 对应 "./src/modules"
- "/#" 对应 "./src/plugins"
- "/~" 对应 "./packages"

2
.gitignore vendored
View File

@ -17,3 +17,5 @@ yarn-error.log*
*.njsproj
*.sln
*.sw*
vite.config.ts.timestamp*

View File

@ -5,6 +5,6 @@
"tabWidth": 4,
"printWidth": 100,
"singleQuote": true,
"arrowParens": "avoid",
"arrowParens": "avoid",
"trailingComma": "none"
}

View File

@ -3,7 +3,7 @@
"prefix": "module-config",
"scope": "typescript",
"body": [
"import type { ModuleConfig } from \"/@/cool\";",
"import { type ModuleConfig } from \"/@/cool\";",
"",
"export default (): ModuleConfig => {",
" return {};",

View File

@ -13,8 +13,8 @@
" <!-- 删除按钮 -->",
" <cl-multi-delete-btn />",
" <cl-flex1 />",
" <!-- 关键字搜索 -->",
" <cl-search-key />",
" <!-- 条件搜索 -->",
" <cl-search ref=\"Search\" />",
" </cl-row>",
"",
" <cl-row>",
@ -33,8 +33,12 @@
" </cl-crud>",
"</template>",
"",
"<script lang=\"ts\" name=\"$1\" setup>",
"import { useCrud, useTable, useUpsert } from \"@cool-vue/crud\";",
"<script lang=\"ts\" setup>",
"defineOptions({",
" name: \"$1\"",
"});",
"",
"import { useCrud, useTable, useUpsert, useSearch } from \"@cool-vue/crud\";",
"import { useCool } from \"/@/cool\";",
"",
"const { service } = useCool();",
@ -49,6 +53,9 @@
" columns: []",
"});",
"",
"// cl-search",
"const Search = useSearch();",
"",
"// cl-crud",
"const Crud = useCrud(",
" {",
@ -78,25 +85,16 @@
],
"description": "cl-filter snippets"
},
"item": {
"prefix": "item",
"scope": "typescript",
"body": [
"{",
" label: \"$1\",",
" prop: \"\",",
" component: {",
" name: \"\"",
" }",
"},",
""
],
"description": "item snippets"
"slot-item": {
"prefix": "slot item",
"scope": "html",
"body": ["<template #slot-$1=\"{ scope }\">", "</template>", ""],
"description": "slot snippets"
},
"column": {
"prefix": "column",
"scope": "typescript",
"body": ["{", " label: \"$1\",", " prop: \"\",", "},", ""],
"description": "column snippets"
"slot-column": {
"prefix": "slot column",
"scope": "html",
"body": ["<template #column-$1=\"{ scope }\">", " ", "</template>", ""],
"description": "column slot snippets"
}
}

View File

@ -1,8 +1,3 @@
{
"recommendations": [
"Vue.volar",
"vitest.explorer",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
"recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}

27
.vscode/settings.json vendored
View File

@ -1,14 +1,17 @@
{
"editor.cursorSmoothCaretAnimation": "on",
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.patterns": {
"tsconfig.json": "tsconfig.*.json, env.d.ts",
"vite.config.*": "jsconfig*, vitest.config.*, cypress.config.*, playwright.config.*",
"package.json": "package-lock.json, pnpm*, .yarnrc*, yarn*, .eslint*, eslint*, .prettier*, prettier*, .editorconfig"
},
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.cursorSmoothCaretAnimation": "on",
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.patterns": {
"tsconfig.json": "tsconfig.*.json, env.d.ts",
"vite.config.*": "jsconfig*, vitest.config.*, cypress.config.*, playwright.config.*",
"package.json": "package-lock.json, pnpm*, .yarnrc*, yarn*, .eslint*, eslint*, .prettier*, prettier*, .editorconfig"
},
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

14
LICENSE
View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 cool-team-official
Copyright (c) [2025] [厦门闪酷科技开发有限公司]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -19,3 +19,15 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
MIT 许可证
版权所有 (c) [2025] [厦门闪酷科技开发有限公司]
特此免费授予获得本软件及相关文档文件(“软件”)副本的任何人无限制地处理本软件的权限,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许软件提供给其的人员这样做,但须符合以下条件:
上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。
本软件按“原样”提供,不提供任何明示或暗示的担保,包括但不限于对适销性、特定用途适用性和非侵权的担保。在任何情况下,作者或版权持有人均不对因软件或软件使用或其他交易而产生的任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权诉讼或其他诉讼中。

View File

@ -16,6 +16,8 @@
body,
#app {
height: 100%;
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
}
* {
@ -60,41 +62,49 @@
letter-spacing: 5px;
font-weight: bold;
margin-bottom: 30px;
min-height: 50px;
}
.preload__title {
color: #fff;
font-size: 14px;
margin: 30px 0 20px 0;
min-height: 20px;
}
.preload__sub-title {
color: #ababab;
font-size: 12px;
min-height: 20px;
}
.preload__footer {
text-align: center;
padding: 10px 0 20px 0;
.preload__name,
.preload__title,
.preload__sub-title {
animation: s 0.5s ease-in;
}
.preload__footer a {
font-size: 12px;
color: #ababab;
text-decoration: none;
@keyframes s {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.preload__loading {
height: 30px;
width: 30px;
height: 44px;
width: 44px;
border-radius: 30px;
border: 7px solid currentColor;
border-bottom-color: #2f3447 !important;
border-bottom-color: #2f3447;
position: relative;
animation:
r 1s infinite cubic-bezier(0.17, 0.67, 0.83, 0.67),
bc 2s infinite ease-in;
transform: rotate(0deg);
box-sizing: border-box;
}
@keyframes r {
@ -154,14 +164,10 @@
<body>
<div class="preload__wrap" id="Loading">
<div class="preload__container">
<p class="preload__name">%VITE_NAME%</p>
<p class="preload__name"></p>
<div class="preload__loading"></div>
<p class="preload__title">正在加载资源...</p>
<p class="preload__sub-title">初次加载资源可能需要较多时间 请耐心等待</p>
</div>
<div class="preload__footer">
<a href="https://cool-js.com" target="_blank"> https://cool-js.com </a>
<p class="preload__title"></p>
<p class="preload__sub-title"></p>
</div>
</div>

View File

@ -1,71 +1,74 @@
{
"name": "cool-admin",
"version": "7.3.0",
"name": "cool-admin-vue",
"version": "8.0.0",
"type": "module",
"scripts": {
"dev": "vite --host",
"build": "vite build",
"build-static": "vite build --mode static",
"preview": "vite preview",
"type-check": "vue-tsc --build --force",
"lint": "eslint . --fix",
"format": "prettier --write src/"
},
"dependencies": {
"@cool-vue/crud": "^7.2.10",
"@cool-vue/crud": "^8.0.0",
"@element-plus/icons-vue": "^2.3.1",
"@vueuse/core": "^12.3.0",
"@vueuse/core": "^12.5.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.7.7",
"axios": "^1.7.9",
"chardet": "^2.0.0",
"core-js": "^3.38.1",
"core-js": "^3.40.0",
"dayjs": "^1.11.13",
"echarts": "^5.5.1",
"element-plus": "^2.9.1",
"echarts": "^5.6.0",
"element-plus": "^2.9.3",
"file-saver": "^2.0.5",
"lodash-es": "^4.17.21",
"marked": "^14.1.3",
"mitt": "^3.0.1",
"mockjs": "^1.1.0",
"monaco-editor": "0.52.0",
"nprogress": "^0.2.0",
"pinia": "^2.3.0",
"socket.io-client": "^4.8.0",
"pinia": "^2.3.1",
"store": "^2.0.12",
"vue": "^3.5.13",
"vue-echarts": "^7.0.3",
"vue-router": "^4.4.5",
"vue-i18n": "^11.0.1",
"vue-router": "^4.5.0",
"vuedraggable": "^4.1.0",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@cool-vue/vite-plugin": "^7.2.7",
"@rushstack/eslint-patch": "^1.10.4",
"@cool-vue/vite-plugin": "^8.0.0",
"@intlify/unplugin-vue-i18n": "^6.0.3",
"@rushstack/eslint-patch": "^1.10.5",
"@tsconfig/node20": "^20.1.4",
"@types/file-saver": "^2.0.7",
"@types/lodash-es": "^4.17.12",
"@types/mockjs": "^1.0.10",
"@types/node": "^20.16.11",
"@types/node": "^20.17.17",
"@types/nprogress": "^0.2.3",
"@types/store": "^2.0.5",
"@vitejs/plugin-vue": "^5.1.4",
"@vitejs/plugin-vue-jsx": "^4.0.1",
"@vue/compiler-sfc": "^3.5.12",
"@vue/eslint-config-prettier": "^10.0.0",
"@vue/eslint-config-typescript": "^14.0.1",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"@vue/compiler-sfc": "^3.5.13",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.3.0",
"@vue/test-utils": "^2.4.6",
"@vue/tsconfig": "^0.5.1",
"eslint": "^9.12.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-vue": "^9.29.0",
"prettier": "^3.3.3",
"rollup-plugin-visualizer": "^5.12.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.19.0",
"eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-vue": "^9.32.0",
"postcss": "^8.5.1",
"prettier": "^3.4.2",
"rollup-plugin-visualizer": "^5.14.0",
"sass": "1.81.0",
"tailwindcss": "^3.4.17",
"terser": "^5.36.0",
"typescript": "~5.5.4",
"vite": "^5.4.10",
"vite": "^5.4.14",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-vue-devtools": "^7.5.2",
"vue-tsc": "^2.1.6"
"vite-plugin-vue-devtools": "^7.7.1",
"vue-tsc": "^2.2.0"
}
}

View File

@ -1,3 +0,0 @@
> 1%
last 2 versions
not dead

View File

@ -1,3 +0,0 @@
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"]
};

View File

@ -1 +0,0 @@
/// <reference types="./index" />

View File

@ -60,8 +60,8 @@ declare type obj = {
declare type DeepPartial<T> = T extends Function
? T
: T extends object
? { [P in keyof T]?: DeepPartial<T[P]> }
: T;
? { [P in keyof T]?: DeepPartial<T[P]> }
: T;
// 合并
declare type Merge<A, B> = Omit<A, keyof B> & B;
@ -130,6 +130,15 @@ declare namespace Render {
// crud
declare namespace ClCrud {
declare interface Field {
comment: string;
source: string;
propertyName: string;
type: string;
dict: string | string[];
nullable: boolean;
}
interface Label {
op: string;
add: string;
@ -248,7 +257,13 @@ declare namespace ClCrud {
update(params?: Params["update"]): Promise<Response["update"]>;
info(params?: Params["info"]): Promise<Response["info"]>;
delete(params?: Params["delete"]): Promise<Response["delete"]>;
[key: string]: (params?: any) => Promise<any>;
permission: Permission;
search: {
fieldEq: Field[];
fieldLike: Field[];
keyWordLikeFields: Field[];
};
[key: string]: any;
};
}
@ -320,6 +335,7 @@ declare namespace ClTable {
search: {
isInput: boolean;
value: any;
icon: () => any;
refreshOnChange: boolean;
component: Render.Component;
};
@ -331,6 +347,7 @@ declare namespace ClTable {
buttons: OpButton | ((options: { scope: T }) => OpButton);
align: ElementPlus.Align;
label: any;
renderLabel: (options: { column: any; $index: number }) => any;
className: string;
prop: PropKey<T>;
orderNum: number;
@ -345,6 +362,7 @@ declare namespace ClTable {
headerAlign: ElementPlus.Align;
showOverflowTooltip: boolean;
fixed: boolean | string;
render: (row: T, column: any, value: any, index: number) => any;
formatter: (row: T, column: any, value: any, index: number) => any;
selectable: (row: T, index: number) => boolean;
reserveSelection: boolean;
@ -386,6 +404,9 @@ declare namespace ClTable {
sortRefresh: boolean;
emptyText: string;
rowKey: string;
on?: {
[key: string]: (...args: any[]) => void;
};
plugins?: Plugin[];
onRowContextmenu?(row: T, column: any, event: any): void;
}
@ -416,6 +437,7 @@ declare namespace ClTable {
scrollTo(position: { top?: number; left?: number }): void;
setScrollTop(top: number): void;
setScrollLeft(left: number): void;
updateKeyChildren(key: string, children: any[]): void;
}
interface Options<T = any> extends DeepPartial<Config<T>> {
@ -663,6 +685,8 @@ declare namespace ClAdvSearch {
}
declare namespace ClSearch {
type Plugin = (options: { exposed: Ref }) => void;
interface Config<T = any> {
inline?: boolean;
items?: ClForm.Item[];
@ -674,6 +698,7 @@ declare namespace ClSearch {
onChange?(data: T, prop: string): void;
onLoad?(data: T): void;
onSearch?(data: T, options: { next: ClCrud.Service["api"]["page"] }): void;
plugins?: Plugin[];
}
interface Ref<T = any> extends ClForm.Ref<T> {
@ -764,6 +789,9 @@ declare interface Config {
};
plugins: ClTable.Plugin[];
};
search: {
plugins: ClSearch.Plugin[];
};
};
}

29
packages/crud/index.html Normal file
View File

@ -0,0 +1,29 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="referer" content="never" />
<meta name="renderer" content="webkit" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0"
/>
<title></title>
<link rel="icon" href="./favicon.ico" />
</head>
<body>
<div class="preload__wrap" id="Loading">
<div class="preload__container">
<p class="preload__name"></p>
<div class="preload__loading"></div>
<p class="preload__title"></p>
<p class="preload__sub-title"></p>
</div>
</div>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@ -1,40 +1,38 @@
{
"name": "@cool-vue/crud",
"version": "7.2.13",
"version": "8.0.0",
"private": false,
"main": "./dist/index.umd.min.js",
"typings": "types/index.d.ts",
"main": "./dist/index.umd.js",
"module": "./dist/index.es.js",
"types": "types/entry.d.ts",
"type": "module",
"scripts": {
"dev": "vue-cli-service serve",
"build": "vue-cli-service build",
"tsc": "tsc --watch",
"dist": "tsc && pnpm build --target lib --name index ./src/index.ts"
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"array.prototype.flat": "^1.2.4",
"core-js": "^3.21.1",
"@vue/runtime-core": "^3.5.13",
"element-plus": "^2.9.4",
"lodash-es": "^4.17.21",
"mitt": "^3.0.1",
"vue": "^3.5.13"
},
"devDependencies": {
"@types/array.prototype.flat": "^1.2.1",
"@types/clone-deep": "^4.0.1",
"@types/lodash-es": "^4.17.12",
"@vue/cli-plugin-babel": "^5.0.1",
"@vue/cli-plugin-typescript": "^5.0.3",
"@vue/cli-service": "^5.0.3",
"@vue/compiler-sfc": "^3.3.9",
"prettier": "^3.1.0",
"sass": "^1.55.0",
"sass-loader": "^12.6.0",
"@types/node": "^20.11.16",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"prettier": "^3.5.1",
"sass": "^1.85.0",
"sass-loader": "^16.0.5",
"typescript": "^5.3.3",
"element-plus": "^2.9.1"
"vite": "^6.1.0",
"vite-plugin-dts": "^4.5.0",
"vue-tsc": "^2.2.2"
},
"files": [
"dist",
"types",
"index.d.ts"
"dist",
"index.d.ts",
"index.ts"
]
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
<template>
<div>
<div class="title">CRUD DEMO v7</div>
<div class="title">CRUD DEMO v8</div>
<cl-crud ref="Crud">
<div class="search">
@ -38,12 +38,12 @@
</cl-row>
<cl-upsert ref="Upsert"></cl-upsert>
<cl-form ref="Form"></cl-form>
</cl-crud>
</div>
</template>
<script setup lang="tsx">
import { computed } from "vue";
import { useTable, useForm, useUpsert, useCrud, useSearch } from "./hooks";
import { EditPen } from "@element-plus/icons-vue";
@ -60,26 +60,40 @@ const Upsert = useUpsert<Data>({
props: {
labels: [
{
label: "A",
label: "基础",
value: "A",
icon: EditPen
},
{
label: "B",
label: "高级",
value: "B"
}
]
}
},
{
group: "B",
group: "A",
prop: "age",
label: "年龄",
component: {
name: "el-input"
}
},
{
group: "A",
prop: "name",
label: "昵称",
component: {
name: "el-input"
},
hidden({ scope }) {
return scope.age < 18;
}
},
{
group: "B",
prop: "phone",
label: "手机",
component: {
name: "el-input"
},
@ -90,17 +104,12 @@ const Upsert = useUpsert<Data>({
() => {
return {
group: "A",
hidden: Upsert.value?.mode == "add",
hook: {
bind(value, { form }) {
return "";
},
submit(value, { form }) {}
}
hidden: Upsert.value?.mode == "add"
};
}
],
onOpened(data) {
console.log(data);
Upsert.value?.setForm("age", "18");
}
});
@ -182,7 +191,6 @@ const Search = useSearch({
},
hook: {
reset() {
console.log(1111);
return [];
}
}
@ -197,11 +205,4 @@ const Search = useSearch({
font-size: 14px;
font-weight: bold;
}
.search {
background-color: #f7f7f7;
border-radius: 8px;
padding: 10px;
margin-bottom: 10px;
}
</style>

View File

@ -155,7 +155,7 @@ export default defineComponent({
type: e == "search" ? "primary" : null,
size: style.size,
onClick: () => {
fns[e]();
fns[e]()
}
},
{ default: () => crud.dict.label[e] }

View File

@ -55,7 +55,9 @@ export default defineComponent({
scrollbar: {
type: Boolean,
default: true
}
},
// 背景透明
transparent: Boolean
},
emits: ["update:modelValue", "fullscreen-change"],
@ -232,7 +234,7 @@ export default defineComponent({
return h(
<el-dialog
ref={Dialog}
class="cl-dialog"
class={["cl-dialog", { 'is-transparent': props.transparent }]}
width={props.width}
beforeClose={props.beforeClose}
show-close={false}

View File

@ -9,7 +9,9 @@ export default defineComponent({
setup(props) {
return () => {
return <el-alert title={props.title} type="error" />;
return <div class="cl-error-message">
{props.title}
</div>;
};
}
});

View File

@ -28,7 +28,8 @@ export function useApi({ Form }: { Form: Vue.Ref<any> }) {
"validateField",
"resetFields",
"scrollToField",
"clearValidate"
"clearValidate",
"fields"
],
Form
);

View File

@ -1,5 +1,6 @@
import { Ref, WatchStopHandle, getCurrentInstance, watch } from "vue";
import { useConfig } from "../../../hooks";
import { uniqueFns } from "../../../utils";
export function usePlugins(enable: boolean, { visible }: { visible: Ref<boolean> }) {
const that: any = getCurrentInstance();
@ -38,7 +39,7 @@ export function usePlugins(enable: boolean, { visible }: { visible: Ref<boolean>
}
// 执行
[...(style.form.plugins || []), ...plugins].forEach((p) => {
uniqueFns([...(style.form.plugins || []), ...plugins]).forEach((p) => {
const d: any = {
exposed: that.exposed
};

View File

@ -1,22 +1,22 @@
import { defineComponent, h, nextTick, toRef, watch } from "vue";
import { assign, cloneDeep, isBoolean, keys } from "lodash-es";
import { defineComponent, h, nextTick, } from "vue";
import { assign, cloneDeep, isBoolean, isFunction, keys } from "lodash-es";
import { useAction, useForm, usePlugins, useTabs } from "./helper";
import { useBrowser, useConfig, useElApi, useRefs } from "../../hooks";
import { getValue, merge } from "../../utils";
import formHook from "../../utils/form-hook";
import { renderNode } from "../../utils/vnode";
import { parseFormHidden } from "../../utils/parse";
export default defineComponent({
name: "cl-form",
props: {
name: String,
inner: Boolean,
inline: Boolean,
enablePlugin: {
type: Boolean,
default: true
}
},
},
setup(props, { expose, slots }) {
@ -39,7 +39,7 @@ export default defineComponent({
// 方法
const ElFormApi = useElApi(
["validate", "validateField", "resetFields", "scrollToField", "clearValidate"],
["validate", "validateField", "resetFields", "scrollToField", "clearValidate", "fields"],
Form
);
@ -96,7 +96,7 @@ export default defineComponent({
// 清空表单验证
function clear() {
for (const i in form) {
form[i] = undefined;
delete form[i];
}
setTimeout(() => {
@ -291,7 +291,7 @@ export default defineComponent({
if (e.required) {
e.rules = {
required: true,
message: `${e.label}${dict.label.nonEmpty}`
message: dict.label.nonEmpty.replace('{label}', e.label || '')
};
}
}
@ -361,7 +361,7 @@ export default defineComponent({
}
// 是否隐藏
e._hidden = parseFormHidden(e.hidden, {
e._hidden = parseHidden(e.hidden, {
scope: form
});
@ -499,6 +499,7 @@ export default defineComponent({
size={style.size}
label-width={style.form.labelWidth}
inline={props.inline}
require-asterisk-position="right"
disabled={saving.value}
scroll-to-error
model={form}
@ -535,7 +536,7 @@ export default defineComponent({
);
}
// 渲染表单按钮
// 渲染表单底部按钮
function renderFooter() {
const { hidden, buttons, saveButtonText, closeButtonText, justify } = config.op;
@ -599,7 +600,19 @@ export default defineComponent({
);
}
expose({
// Tools
function parseHidden(value: any, { scope }: any) {
if (isBoolean(value)) {
return value;
} else if (isFunction(value)) {
return value({ scope });
}
return false;
}
const ctx = {
name: props.name,
refs,
Form,
visible,
@ -622,7 +635,11 @@ export default defineComponent({
Tabs,
...Action,
...ElFormApi
});
}
// console.log(ctx)
expose(ctx);
return () => {
if (props.inner) {

View File

@ -68,6 +68,7 @@ export default defineComponent({
return () => {
return h(
<el-pagination
class="cl-pagination"
size={browser.isMini ? 'small' : style.size}
background
page-sizes={[10, 20, 30, 40, 50, 100]}

View File

@ -26,7 +26,7 @@ export default defineComponent({
// 宽度
width: {
type: [String, Number],
default: 260
default: 280
},
// 是否实时刷新
refreshOnInput: Boolean

View File

@ -0,0 +1,21 @@
import { getCurrentInstance } from "vue";
import { useConfig } from "../../../hooks";
import { uniqueFns } from "../../../utils";
export function usePlugins() {
const that: any = getCurrentInstance();
const { style } = useConfig();
// 插件创建
function create(plugins: ClSearch.Plugin[] = []) {
uniqueFns([...(style.search?.plugins || []), ...plugins]).forEach((p) => {
p({
exposed: that.exposed
});
});
}
return {
create
};
}

View File

@ -14,27 +14,29 @@ import {
import { useApi } from "../form/helper";
import { Search, Refresh, Bottom, Top } from "@element-plus/icons-vue";
import { mitt } from "../../utils/mitt";
import { isArray, isObject, isString } from "lodash-es";
import { isArray, isEmpty } from "lodash-es";
import { usePlugins } from "./helper/plugins";
export default defineComponent({
name: "cl-search",
props: {
// 是否行内
inline: {
type: Boolean,
default: true
},
// cl-form 表单配置
props: {
type: Object,
default: () => { }
default: () => ({})
},
// 表单值
data: {
type: Object,
default: () => {
return {};
}
default: () => ({})
},
// 列
@ -50,7 +52,10 @@ export default defineComponent({
},
// 是否需要折叠
collapse: Boolean,
collapse: {
type: Boolean,
default: false
},
// 初始化
onLoad: Function,
@ -65,6 +70,7 @@ export default defineComponent({
const { crud } = useCore();
const { refs, setRefs } = useRefs()
const { style } = useConfig();
const plugin = usePlugins()
// 配置
const config = reactive<ClSearch.Config>(
@ -179,15 +185,28 @@ export default defineComponent({
useProxy(ctx);
expose(ctx);
plugin.create(config.plugins);
onMounted(() => {
// 打开表单
Form.value?.open({
op: {
hidden: true
},
props: config.props,
items: config.items,
props: {
labelPosition: 'right',
...config.props
},
items: config.items?.map(e => {
return {
col: {
sm: 12,
md: 8,
xs: 24,
lg: 6,
},
...e,
}
}),
form: config.data,
on: {
open(data) {
@ -235,7 +254,10 @@ export default defineComponent({
);
return (
<div class={["cl-search", isExpand.value ? "is-expand" : "is-collapse"]}>
<div class={["cl-search", isExpand.value ? "is-expand" : "is-fold", {
'is-inline': config.inline,
'is-collapse': config.collapse,
}]}>
<div class="cl-search__form" ref={setRefs("form")}>
{h(
<cl-form
@ -243,11 +265,12 @@ export default defineComponent({
inner
inline={config.inline}
enable-plugin={false}
name='search'
/>,
{},
{
append() {
return config.collapse ? null : btnEl;
return config.collapse ? null : (isEmpty(config.items) || btnEl);
},
...slots
}

View File

@ -15,7 +15,7 @@ export function renderHeader(item: ClTable.Column, { scope, slots }: any) {
}
if (!item.search || !item.search.component) {
return scope.column.label;
return item.label;
}
// 显示输入框
@ -28,10 +28,10 @@ export function renderHeader(item: ClTable.Column, { scope, slots }: any) {
const text = (
<div onClick={show}>
<el-icon class="icon">
<Search />
{item.search.icon?.() ?? <Search />}
</el-icon>
<span>{scope.column.label}</span>
{item.renderLabel ? item.renderLabel(scope) : item.label}
</div>
);
@ -47,6 +47,8 @@ export function renderHeader(item: ClTable.Column, { scope, slots }: any) {
item.search.value = val;
},
onChange(val: any) {
item.search.value = val;
// 更改时刷新列表
if (item.search.refreshOnChange) {
crud.value?.refresh({
@ -54,6 +56,11 @@ export function renderHeader(item: ClTable.Column, { scope, slots }: any) {
[item.prop]: val === "" ? undefined : val
});
}
},
onBlur() {
if (item.search.value === null || item.search.value === undefined || item.search.value === "") {
item.search.isInput = false;
}
}
});

View File

@ -1,11 +1,12 @@
import { inject, reactive, ref } from "vue";
import { useConfig } from "../../../hooks";
import { getValue, mergeConfig } from "../../../utils";
import { ElTable } from "element-plus";
export function useTable(props: any) {
const { style } = useConfig();
const Table = ref();
const Table = ref<InstanceType<typeof ElTable>>();
// 配置
const config = reactive<ClTable.Config>(mergeConfig(props, inject("useTable__options") || {}));
@ -19,6 +20,11 @@ export function useTable(props: any) {
// 右键菜单
config.contextMenu = config.contextMenu ?? style.table.contextMenu;
// 事件
if (!config.on) {
config.on = {};
}
return { Table, config };
}

View File

@ -1,5 +1,6 @@
import { getCurrentInstance } from "vue";
import { useConfig } from "../../../hooks";
import { uniqueFns } from "../../../utils";
export function usePlugins() {
const that: any = getCurrentInstance();
@ -8,7 +9,7 @@ export function usePlugins() {
// 插件创建
function create(plugins: ClTable.Plugin[] = []) {
// 执行
[...(style.table.plugins || []), ...plugins].forEach((p) => {
uniqueFns([...(style.table.plugins || []), ...plugins]).forEach((p) => {
p({
exposed: that.exposed
});

View File

@ -1,8 +1,7 @@
import { h, useSlots } from "vue";
import { useCore, useBrowser, useConfig } from "../../../hooks";
import { cloneDeep, isEmpty, orderBy } from "lodash-es";
import { getValue } from "../../../utils";
import { parseTableDict, parseTableOpButtons } from "../../../utils/parse";
import { assign, cloneDeep, isArray, isEmpty, isObject, isString, orderBy } from "lodash-es";
import { deepFind, getValue, } from "../../../utils";
import { renderNode } from "../../../utils/vnode";
import { renderHeader } from "./header";
@ -42,19 +41,20 @@ export function useRender() {
// 操作按钮
if (item.type === "op") {
const props = assign({
label: crud.dict.label.op,
width: style.table.column.opWidth,
fixed: browser.isMini ? null : "right",
}, item)
return h(
ElTableColumn,
{
label: crud.dict.label.op,
width: style.table.column.opWidth,
fixed: browser.isMini ? null : "right",
...item
},
props,
{
default: (scope: any) => {
return (
<div class="cl-table__op">
{parseTableOpButtons(item.buttons, { scope })}
{renderOpButtons(item.buttons, { scope })}
</div>
);
}
@ -106,10 +106,23 @@ export function useRender() {
value,
scope.$index
);
if (isObject(value)) {
return value
}
}
// 自定义渲染
if (item.component) {
if (item.render) {
return item.render(
scope.row,
scope.column,
value,
scope.$index
);
}
// 自定义渲染2
else if (item.component) {
return renderNode(item.component, {
prop: item.prop,
scope: scope.row,
@ -122,7 +135,7 @@ export function useRender() {
}
// 字典状态
else if (item.dict) {
return parseTableDict(value, item);
return renderDict(value, item);
}
// 空数据
else if (isEmpty(value)) {
@ -141,6 +154,156 @@ export function useRender() {
.filter(Boolean);
}
// 渲染操作按钮
function renderOpButtons(buttons: any, { scope }: any) {
const list = getValue(buttons || ["edit", "delete"], { scope }) as ClTable.OpButton;
return list.map((vnode) => {
if (vnode === "info") {
return (
<el-button
plain
size={style.size}
v-show={crud.getPermission("info")}
onClick={(e: MouseEvent) => {
crud.rowInfo(scope.row);
e.stopPropagation();
}}>
{crud.dict.label?.info}
</el-button>
);
} else if (vnode === "edit") {
return (
<el-button
text
type="primary"
size={style.size}
v-show={crud.getPermission("update")}
onClick={(e: MouseEvent) => {
crud.rowEdit(scope.row);
e.stopPropagation();
}}>
{crud.dict.label?.update}
</el-button>
);
} else if (vnode === "delete") {
return (
<el-button
text
type="danger"
size={style.size}
v-show={crud.getPermission("delete")}
onClick={(e: MouseEvent) => {
crud.rowDelete(scope.row);
e.stopPropagation();
}}>
{crud.dict.label?.delete}
</el-button>
);
} else {
if (typeof vnode === 'object') {
if (vnode.hidden) {
return null;
}
}
return (
renderNode(vnode, {
scope,
slots,
custom(vnode) {
return (
<el-button
text
type={vnode.type}
{...vnode?.props}
onClick={(e: MouseEvent) => {
vnode.onClick({ scope });
e.stopPropagation();
}}>
{vnode.label}
</el-button>
);
}
})
);
}
});
}
// 渲染字典
function renderDict(value: any, item: ClTable.Column) {
// 选项列表
const list = cloneDeep(item.dict || []) as DictOptions;
// 字符串分隔符
const separator = item.dictSeparator === undefined ? "," : item.dictSeparator;
// 设置颜色
if (item.dictColor) {
list.forEach((e, i) => {
if (!e.color) {
e.color = style.colors[i];
}
});
}
// 绑定值
let values: any[] = [];
// 格式化值
if (isArray(value)) {
values = value;
} else if (isString(value)) {
if (separator) {
values = value.split(separator);
} else {
values = [value];
}
} else {
values = [value];
}
// 返回值
const result = values
.filter((e) => e !== undefined && e !== null && e !== "")
.map((v) => {
const d = deepFind(v, list, { allLevels: item.dictAllLevels }) || {
label: v,
value: v
};
return {
...d,
children: []
};
});
// 格式化返回
if (item.dictFormatter) {
return item.dictFormatter(result);
} else {
// tag 返回
return result.map((e) => {
return h(
<el-tag disable-transitions style="margin: 2px; border: 0" />,
{
type: e.type,
closable: e.closable,
hit: e.hit,
color: e.color,
size: e.size,
effect: e.effect || "dark",
round: e.round
},
{
default: () => <span>{e.label}</span>
}
);
});
}
}
// 插槽 empty
function renderEmpty(emptyText: string) {
return (

View File

@ -94,13 +94,15 @@ export default defineComponent({
"sort",
"scrollTo",
"setScrollTop",
"setScrollLeft"
"setScrollLeft",
"updateKeyChildren"
],
Table
);
const ctx = {
Table,
config,
columns: config.columns,
...Selection,
...Data,
@ -123,6 +125,8 @@ export default defineComponent({
h(
<el-table class="cl-table" ref={Table} v-loading={crud.loading} />,
{
...config.on,
// config
maxHeight: config.autoHeight ? ctx.maxHeight.value : null,
height: config.autoHeight ? config.height : null,
@ -140,7 +144,8 @@ export default defineComponent({
border: style.table.border,
highlightCurrentRow: style.table.highlightCurrentRow,
resizable: style.table.resizable,
stripe: style.table.stripe
stripe: style.table.stripe,
},
{
default() {

View File

@ -0,0 +1,30 @@
import type { App } from "vue";
import { useComponent } from "./components";
import { useProvide } from "./provide";
import global from "./utils/global";
import "./static/index.scss";
const Crud = {
install(app: App, options?: any) {
global.set("__CrudApp__", app);
// 穿透值
useProvide(app, options);
// 设置组件
useComponent(app);
return {
name: "cl-crud"
};
}
};
export { Crud };
export * from "./emitter";
export * from "./hooks";
export * from "./locale";
export { registerFormHook } from "./utils/form-hook";
export { renderNode } from "./utils/vnode";
export { ContextMenu } from "./components/context-menu";

View File

@ -1 +0,0 @@
/// <reference types="../index" />

View File

@ -171,9 +171,7 @@ export function useSearch<T = any>(options?: ClSearch.Options<T>) {
const Search = ref<ClSearch.Ref<T>>();
useParent("cl-search", Search);
if (options) {
provide("useSearch__options", options);
}
provide("useSearch__options", options);
return Search;
}

View File

@ -1,6 +1,6 @@
import { Mitt } from "../utils/mitt";
import { isFunction } from "lodash-es";
import { computed, getCurrentInstance, inject, reactive } from "vue";
import { getCurrentInstance, inject, reactive } from "vue";
export function useCore() {
const crud = inject("crud") as ClCrud.Ref;

View File

@ -1,30 +1 @@
import type { App } from "vue";
import { useComponent } from "./components";
import { useProvide } from "./provide";
import global from "./utils/global";
import "./static/index.scss";
const Crud = {
install(app: App, options?: Options) {
global.set("__CrudApp__", app);
// 穿透值
useProvide(app, options);
// 设置组件
useComponent(app);
return {
name: "cl-crud"
};
}
};
export default Crud;
export * from "./emitter";
export * from "./hooks";
export * from "./plugins";
export * from "./locale";
export { registerFormHook } from "./utils/form-hook";
export { ContextMenu } from "./components/context-menu";
export * from "./entry";

View File

@ -15,7 +15,6 @@ export default {
advSearch: "Advanced Search",
searchKey: "Search Keyword",
placeholder: "Please enter",
placeholderSelect: "Please select",
tips: "Tips",
saveSuccess: "Save successful",
deleteSuccess: "Delete successful",
@ -28,7 +27,7 @@ export default {
deselect: "Deselect",
seeMore: "See more",
hideContent: "Hide content",
nonEmpty: "Cannot be empty",
nonEmpty: "{label} cannot be empty",
collapse: "Collapse",
expand: "Expand"
};

View File

@ -6,6 +6,6 @@ import zhTw from "./zh-tw";
export const locale = {
en,
ja,
zhCn,
zhTw
"zh-cn": zhCn,
"zh-tw": zhTw
};

View File

@ -15,7 +15,6 @@ export default {
advSearch: "高度な検索",
searchKey: "検索キーワード",
placeholder: "入力してください",
placeholderSelect: "選択してください",
tips: "ヒント",
saveSuccess: "保存が成功しました",
deleteSuccess: "削除が成功しました",
@ -27,7 +26,7 @@ export default {
deselect: "選択解除",
seeMore: "詳細を表示",
hideContent: "コンテンツを非表示",
nonEmpty: "空にできません",
nonEmpty: "{label}は空にできません",
collapse: "折り畳む",
expand: "展開"
};

View File

@ -15,7 +15,6 @@ export default {
advSearch: "高级搜索",
searchKey: "搜索关键字",
placeholder: "请输入",
placeholderSelect: "请选择",
tips: "提示",
saveSuccess: "保存成功",
deleteSuccess: "删除成功",
@ -27,7 +26,7 @@ export default {
deselect: "取消选择",
seeMore: "查看更多",
hideContent: "隐藏内容",
nonEmpty: "不能为空",
nonEmpty: "{label}不能为空",
collapse: "收起",
expand: "展开更多"
};

View File

@ -15,7 +15,6 @@ export default {
advSearch: "高級搜索",
searchKey: "搜索關鍵字",
placeholder: "請輸入",
placeholderSelect: "請選擇",
tips: "提示",
saveSuccess: "保存成功",
deleteSuccess: "刪除成功",
@ -27,7 +26,7 @@ export default {
deselect: "取消選擇",
seeMore: "查看更多",
hideContent: "隱藏內容",
nonEmpty: "不能為空",
nonEmpty: "{label}不能為空",
collapse: "收起",
expand: "展開"
};

View File

@ -1,6 +1,6 @@
import { createApp } from "vue";
import App from "./App.vue";
import Crud, { locale } from "./index";
import { Crud, locale } from "./entry";
// import Crud, { locale } from "../dist/index.umd";
// import "../dist/index.css";
@ -16,7 +16,7 @@ app.use(ElementPlus)
prop: "order",
order: "sort"
},
label: locale.zhCn
label: locale["zh-cn"]
},
style: {
// size: "default"

View File

@ -38,7 +38,7 @@ function setConfig(app: App, options: Options = {}) {
order: "order",
prop: "prop"
},
label: locale.zhCn
label: locale["zh-cn"]
},
style: {
colors: [
@ -65,7 +65,7 @@ function setConfig(app: App, options: Options = {}) {
contextMenu: ["refresh", "check", "edit", "delete", "order-asc", "order-desc"],
column: {
align: "center",
opWidth: 160
opWidth: 180
}
}
},

View File

@ -66,8 +66,8 @@
&__header {
.el-table__cell {
background-color: #f5f7fa !important;
color: #333;
background-color: var(--el-fill-color-lighter) !important;
color: var(--el-text-color-primary);
.cell {
line-height: normal;
@ -98,7 +98,7 @@
}
.el-loading-text {
color: #666;
color: var(--el-text-color-secondary);
margin-top: 5px;
}
}
@ -109,6 +109,15 @@
.el-button {
margin-bottom: 5px;
outline-offset: -2px !important;
&.is-text {
border: 1px solid var(--el-button-border-color) !important;
&:hover {
background-color: var(--el-button-bg-color) !important;
}
}
}
}
@ -138,6 +147,18 @@
}
}
.cl-pagination {
&.el-pagination {
--el-pagination-border-radius: var(--el-border-radius-base);
}
.btn-prev,
.btn-next,
.el-pager li {
border-radius: var(--el-border-radius-base);
}
}
.cl-filter {
display: flex;
align-items: center;
@ -155,9 +176,27 @@
}
.cl-search {
margin-bottom: 0px !important;
&__btns {
margin-left: 5px;
}
&__more {
display: flex;
align-items: center;
justify-content: space-between;
.el-form-item {
margin-bottom: 0;
}
}
.el-form:not(.el-form--label-top) {
.el-form-item__label {
&:empty {
display: none;
}
}
.cl-search__btns {
.el-form-item__label {
display: none;
@ -165,33 +204,32 @@
}
}
.el-form:not(.el-form--inline) {
.cl-search__btns {
margin-left: 5px;
}
}
.cl-search__btns {
.el-button + .el-button {
margin-left: 10px;
}
}
&__more {
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px 0;
.el-form-item {
margin-bottom: 0;
}
&.is-inline {
margin-bottom: 0 !important;
}
&.is-collapse {
.cl-search__form {
max-height: 84px;
overflow: hidden;
background-color: var(--el-fill-color-lighter);
padding: 10px;
margin-bottom: 10px !important;
border-radius: 6px;
border: 1px solid var(--el-border-color-extra-light);
&.is-fold {
.cl-search__form {
max-height: 42px;
overflow: hidden;
&:has(.el-form--label-top) {
max-height: 68px;
}
}
}
}
}
@ -328,78 +366,89 @@
line-height: normal;
}
.el-form-item {
.el-form {
.el-form-item {
margin-bottom: 18px;
}
.el-input-number {
&__decrease,
&__increase {
border: 0;
background-color: transparent;
.el-form-item {
margin-bottom: 18px;
}
}
&__label {
.el-tooltip {
i {
margin-left: 5px;
.el-input-number {
&__decrease,
&__increase {
border: 0;
background-color: transparent;
}
}
}
&__content {
min-width: 0px;
& > div {
width: 100%;
}
}
}
&:not(.el-form--label-top) {
.el-form-item {
&.no-label {
& > .el-form-item__label {
padding: 0;
display: none;
}
}
}
}
.el-form--label-top {
.el-form-item__label {
min-height: 22px;
}
}
.el-form--inline {
.cl-form__items {
display: flex;
flex-wrap: wrap;
}
.el-form-item {
margin: 0 10px 10px 0;
.el-date-editor {
box-sizing: border-box;
.el-range-input {
&:nth-child(2) {
&__label {
.el-tooltip {
i {
margin-left: 5px;
}
}
}
.el-select {
width: 173px;
&__content {
min-width: 0px;
& > div {
width: 100%;
}
}
}
&:not(.el-form--label-top) {
.el-form-item {
&.no-label {
& > .el-form-item__label {
padding: 0;
display: none;
}
}
}
}
&.el-form--label-top {
.el-form-item {
margin-bottom: 22px;
}
&:last-child {
margin-right: 0;
.el-form-item__label {
margin: 0 0 4px 0;
min-height: 22px;
}
.el-form-item__error {
padding-top: 4px;
}
}
&.el-form--inline {
.cl-form__items {
display: flex;
flex-wrap: wrap;
}
.el-form-item {
margin: 0 10px 10px 0;
.el-date-editor {
box-sizing: border-box;
.el-range-input {
&:nth-child(2) {
margin-left: 5px;
}
}
}
.el-select {
width: 173px;
}
&:last-child {
margin-right: 0;
}
}
}
}
@ -495,14 +544,13 @@
line-height: normal;
font-weight: bold;
padding: 0 10px;
background-color: var(--el-border-color-extra-light);
background-color: var(--el-fill-color-lighter);
border-radius: var(--el-border-radius-base);
cursor: pointer;
user-select: none;
&:hover {
.el-icon {
color: var(--el-color-primary);
}
background-color: var(--el-fill-color-light);
}
}
@ -538,8 +586,8 @@
flex-direction: column;
&.el-dialog {
border-radius: 6px;
padding: 0;
border-radius: 8px;
}
.el-dialog {
@ -598,8 +646,8 @@
display: flex;
justify-content: flex-end;
position: absolute;
right: 0;
top: 0;
right: 8px;
top: 8px;
z-index: 9;
width: 100%;
@ -610,19 +658,21 @@
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 40px;
height: 28px;
width: 28px;
border: 0;
background-color: transparent;
cursor: pointer;
outline: none;
border-radius: 6px;
margin-left: 5px;
i {
font-size: 18px;
}
&:hover {
opacity: 0.7;
}
&:hover {
background-color: var(--el-fill-color-darker);
}
}
}
@ -642,6 +692,10 @@
height: 100% !important;
}
}
&.is-transparent {
background-color: transparent !important;
}
}
.cl-context-menu {
@ -649,12 +703,16 @@
z-index: 9999;
&__box {
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
width: 160px;
background-color: #fff;
border-radius: 4px;
background-color: var(--el-bg-color);
border: 1px solid var(--el-border-color-extra-light);
box-shadow:
0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -2px rgba(0, 0, 0, 0.1);
border-radius: 6px;
position: absolute;
top: 0;
padding: 5px;
&.is-append {
right: calc(-100% - 5px);
@ -664,30 +722,20 @@
& > div {
display: flex;
align-items: center;
height: 35px;
font-size: 13px;
font-size: 12px;
cursor: pointer;
padding: 0 15px;
color: #666;
padding: 5px 15px;
color: var(--el-text-color-primary);
position: relative;
&:first-child {
margin-top: 5px;
}
&:last-child {
margin-bottom: 5px;
}
border-radius: 4px;
span {
height: 35px;
line-height: 35px;
flex: 1;
user-select: none;
}
&:hover {
background-color: #f7f7f7;
color: #000;
background-color: var(--el-fill-color-lighter);
}
i {
@ -762,3 +810,16 @@
}
}
}
.cl-error-message {
display: flex;
align-items: center;
height: 32px;
padding: 0 10px;
font-size: 14px;
color: var(--el-color-danger);
border: 1px solid var(--el-color-danger);
border-radius: 4px;
box-sizing: border-box;
user-select: none;
}

View File

@ -196,6 +196,36 @@ class TestService {
async list() {
return userList;
}
search = {
fieldEq: [
{
propertyName: "occupation",
comment: "工作",
source: "a.occupation"
}
],
fieldLike: [
{
propertyName: "status",
comment: "状态",
dict: ["关闭", "开启"],
source: "a.status"
}
],
keyWordLikeFields: [
{
propertyName: "name",
comment: "姓名",
source: "a.name"
},
{
propertyName: "phone",
comment: "手机号",
source: "a.phone"
}
]
};
}
export { TestService };

View File

@ -1,5 +1,4 @@
// @ts-nocheck
import { App } from "vue";
export default {

View File

@ -1,6 +1,7 @@
import { isRef, mergeProps } from "vue";
import { assign, flatMap, isArray, isFunction, isNumber, isString, mergeWith } from "lodash-es";
import { isRef, mergeProps, toValue } from "vue";
import { assign, flatMap, isArray, isFunction, isNumber, mergeWith } from "lodash-es";
// 是否对象
export function isObject(val: any) {
return val !== null && typeof val === "object";
}
@ -85,31 +86,27 @@ export function merge(d1: any, d2: any) {
// 添加元素
export function addClass(el: Element, name: string) {
if (isString(el?.className)) {
const f = el.className.includes(name);
if (!f) {
el.className += " " + name;
}
if (el?.classList) {
el.classList.add(name);
}
}
// 移除元素
export function removeClass(el: Element, name: string) {
if (isString(el?.className)) {
el.className = el.className.replace(name, "");
if (el?.classList) {
el.classList.remove(name);
}
}
// 获取值
export function getValue(data: any, params?: any) {
if (isRef(data)) {
return data.value;
export function getValue<T = any>(value: T | Vue.Ref<T> | ((d: any) => T), data?: any): T {
if (isRef(value)) {
return toValue(value) as T;
} else {
if (isFunction(data)) {
return data(params);
if (isFunction(value)) {
return value(data);
} else {
return data;
return value as T;
}
}
}
@ -118,7 +115,7 @@ export function getValue(data: any, params?: any) {
export function deepFind(value: any, list: any[], options?: { allLevels: boolean }) {
const { allLevels = true } = options || {};
function deep(arr: any[], name: string[]): any | undefined {
function deep(arr: DictOptions, name: string[]): any | undefined {
for (const e of arr) {
if (e.value === value) {
if (allLevels) {
@ -130,7 +127,7 @@ export function deepFind(value: any, list: any[], options?: { allLevels: boolean
return e;
}
} else if (e.children) {
const d = deep(e.children, [...name, e.label]);
const d = deep(e.children, [...name!, e.label!]);
if (d !== undefined) {
return d;
@ -156,3 +153,12 @@ export function uuid(separator = "-"): string {
return s.join("");
}
// 移除相同的方法
export function uniqueFns(fns: any[]) {
const arr = new Map();
fns.forEach((fn) => {
arr.set(fn.name, fn);
});
return Array.from(arr.values());
}

View File

@ -1,183 +1,10 @@
import { h, useSlots } from "vue";
import { useConfig, useCore } from "../hooks";
import { isBoolean, isFunction, isArray, isString, cloneDeep } from "lodash-es";
import { renderNode } from "./vnode";
import { deepFind, getValue, isObject } from ".";
import { isString } from "lodash-es";
import { getValue, isObject } from ".";
/**
* form.hidden
*/
export function parseFormHidden(value: any, { scope }: any) {
if (isBoolean(value)) {
return value;
} else if (isFunction(value)) {
return value({ scope });
}
return false;
}
/**
* table.dict
*/
export function parseTableDict(value: any, item: ClTable.Column) {
const { style } = useConfig();
// 选项列表
const list: DictOptions = cloneDeep(getValue(item.dict || []));
// 字符串分隔符
const separator = item.dictSeparator === undefined ? "," : item.dictSeparator;
// 设置颜色
if (item.dictColor) {
list.forEach((e, i) => {
if (!e.color) {
e.color = style.colors[i];
}
});
}
// 绑定值
let values: any[] = [];
// 格式化值
if (isArray(value)) {
values = value;
} else if (isString(value)) {
if (separator) {
values = value.split(separator);
} else {
values = [value];
}
} else {
values = [value];
}
// 返回值
const result = values
.filter((e) => e !== undefined && e !== null && e !== "")
.map((v) => {
const d = deepFind(v, list, { allLevels: item.dictAllLevels }) || {
label: v,
value: v
};
return {
...d,
children: []
};
});
// 格式化返回
if (item.dictFormatter) {
return item.dictFormatter(result);
} else {
// tag 返回
return result.map((e) => {
return h(
<el-tag disable-transitions style="margin: 2px; border: 0" />,
{
type: e.type,
closable: e.closable,
hit: e.hit,
color: e.color,
size: e.size,
effect: e.effect || "dark",
round: e.round
},
{
default: () => <span>{e.label}</span>
}
);
});
}
}
/**
* table.op.buttons
*/
export function parseTableOpButtons(buttons: any[], { scope }: any) {
const { crud } = useCore();
const { style } = useConfig();
const slots = useSlots();
const list: any[] = getValue(buttons, { scope }) || ["edit", "delete"];
return list.map((vnode) => {
if (vnode === "info") {
return (
<el-button
text
bg
size={style.size}
v-show={crud.getPermission("info")}
onClick={() => {
crud.rowInfo(scope.row);
}}>
{crud.dict.label?.info}
</el-button>
);
} else if (vnode === "edit") {
return (
<el-button
text
bg
type="primary"
size={style.size}
v-show={crud.getPermission("update")}
onClick={() => {
crud.rowEdit(scope.row);
}}>
{crud.dict.label?.update}
</el-button>
);
} else if (vnode === "delete") {
return (
<el-button
text
bg
type="danger"
size={style.size}
v-show={crud.getPermission("delete")}
onClick={() => {
crud.rowDelete(scope.row);
}}>
{crud.dict.label?.delete}
</el-button>
);
} else {
return (
!vnode.hidden &&
renderNode(vnode, {
scope,
slots,
custom(vnode) {
return (
<el-button
text
type={vnode.type}
bg
{...vnode?.props}
onClick={() => {
vnode.onClick({ scope });
}}>
{vnode.label}
</el-button>
);
}
})
);
}
});
}
/**
*
*/
export function parseExtensionComponent(vnode: any) {
if (["el-select", "el-radio-group", "el-checkbox-group"].includes(vnode.name)) {
const list: any[] = getValue(vnode.options) || [];
// 解析扩展组件
export function parseExtensionComponent(vnode: Render.Component) {
if (["el-select", "el-radio-group", "el-checkbox-group"].includes(vnode.name!)) {
const list = getValue(vnode.options || []);
const children = (
<div>

View File

@ -30,7 +30,7 @@ const regs: Map<string, any> = new Map();
// 解析节点
export function parseNode(vnode: any, options: Options): VNode {
const { scope, prop, slots, children, _data } = options || [];
const { scope, prop, slots, children, _data } = options || {};
// 渲染后组件
let comp: VNode | null = null;
@ -128,18 +128,14 @@ export function renderNode(vnode: any, options: Options) {
let placeholder = "";
switch (item.component?.name) {
case "el-select":
placeholder = config.dict.label.placeholderSelect;
break;
default:
case "el-input":
placeholder = config.dict.label.placeholder;
break;
}
if (placeholder) {
if (!item.component.props.placeholder) {
item.component.props.placeholder = placeholder + (item.label || '');
item.component.props.placeholder = placeholder
}
}
}
@ -179,7 +175,7 @@ export function renderNode(vnode: any, options: Options) {
return options.custom(vnode);
}
return <cl-error-message title={`Errorname is required`} />;
return <cl-error-message title="Errorcomponent name is required" />;
}
}
}

View File

@ -1,25 +1,34 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"noImplicitAny": false,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": false,
"strict": false,
"noImplicitAny": false,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"types": ["./index.d.ts"],
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"declaration": true,
"declarationDir": "types",
"inlineSourceMap": false,
"disableSizeLimit": true,
"baseUrl": ".",
"outDir": "dist",
"paths": {},
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
"emitDeclarationOnly": true
},
"include": ["src"],
"exclude": ["node_modules", "src/main.ts"]
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"exclude": ["src/App.vue", "node_modules", "dist"]
}

View File

@ -1,2 +1,2 @@
declare const _default: import("vue").DefineComponent<{}, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,4 +1,4 @@
declare const _default: import("vue").DefineComponent<{}, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {
Search: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {
Search: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<import('vue').ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,8 +1,8 @@
import { PropType } from "vue";
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
import { PropType } from 'vue';
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
items: {
type: PropType<ClForm.Item[]>;
default: () => never[];
default: () => any[];
};
title: StringConstructor;
size: {
@ -14,10 +14,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
default: () => string[];
};
onSearch: FunctionConstructor;
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("clear" | "reset")[], "clear" | "reset", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("clear" | "reset")[], "clear" | "reset", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
items: {
type: PropType<ClForm.Item[]>;
default: () => never[];
default: () => any[];
};
title: StringConstructor;
size: {
@ -30,13 +30,13 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
};
onSearch: FunctionConstructor;
}>> & Readonly<{
onReset?: ((...args: any[]) => any) | undefined;
onClear?: ((...args: any[]) => any) | undefined;
onReset?: (...args: any[]) => any;
onClear?: (...args: any[]) => any;
}>, {
size: string | number;
items: ClForm.Item<any>[];
op: unknown[];
}, {}, {
Close: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
Close: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<import('vue').ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,5 +1,5 @@
import { type PropType } from "vue";
declare const ClContextMenu: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
import { PropType } from 'vue';
declare const ClContextMenu: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
show: BooleanConstructor;
options: {
type: PropType<ClContextMenu.Options>;
@ -9,7 +9,7 @@ declare const ClContextMenu: import("vue").DefineComponent<import("vue").Extract
type: ObjectConstructor;
default: () => {};
};
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
show: BooleanConstructor;
options: {
type: PropType<ClContextMenu.Options>;
@ -23,7 +23,7 @@ declare const ClContextMenu: import("vue").DefineComponent<import("vue").Extract
options: ClContextMenu.Options;
show: boolean;
event: Record<string, any>;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export declare const ContextMenu: {
open(event: any, options: ClContextMenu.Options): ClContextMenu.Exposed;
};

View File

@ -1,4 +1,4 @@
import { Mitt } from "../../utils/mitt";
import { Mitt } from '../../utils/mitt';
interface Options {
mitt: Mitt;
config: ClCrud.Config;
@ -6,7 +6,7 @@ interface Options {
}
export declare function useHelper({ config, crud, mitt }: Options): {
proxy: (name: string, data?: any[]) => void;
set: (key: string, value: any) => false | undefined;
set: (key: string, value: any) => boolean;
on: (name: string, callback: fn) => void;
rowInfo: (data: any) => void;
rowAdd: () => void;

View File

@ -1,11 +1,11 @@
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
name: StringConstructor;
border: BooleanConstructor;
padding: {
type: StringConstructor;
default: string;
};
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
name: StringConstructor;
border: BooleanConstructor;
padding: {
@ -15,5 +15,5 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
}>> & Readonly<{}>, {
border: boolean;
padding: string;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,4 +1,4 @@
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
modelValue: {
type: BooleanConstructor;
default: boolean;
@ -29,9 +29,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
type: BooleanConstructor;
default: boolean;
};
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
transparent: BooleanConstructor;
}>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
[key: string]: any;
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:modelValue" | "fullscreen-change")[], "update:modelValue" | "fullscreen-change", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("update:modelValue" | "fullscreen-change")[], "update:modelValue" | "fullscreen-change", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
modelValue: {
type: BooleanConstructor;
default: boolean;
@ -62,22 +63,24 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
type: BooleanConstructor;
default: boolean;
};
transparent: BooleanConstructor;
}>> & Readonly<{
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
"onFullscreen-change"?: ((...args: any[]) => any) | undefined;
"onUpdate:modelValue"?: (...args: any[]) => any;
"onFullscreen-change"?: (...args: any[]) => any;
}>, {
title: string;
padding: string;
width: string;
keepAlive: boolean;
hideHeader: boolean;
controls: unknown[];
fullscreen: boolean;
keepAlive: boolean;
modelValue: boolean;
transparent: boolean;
scrollbar: boolean;
}, {}, {
Close: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
FullScreen: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
Minus: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
Close: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<import('vue').ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
FullScreen: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<import('vue').ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
Minus: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<import('vue').ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,6 +1,6 @@
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
title: StringConstructor;
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
title: StringConstructor;
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,6 +1,6 @@
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
label: StringConstructor;
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
label: StringConstructor;
}>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,2 +1,2 @@
declare const _default: import("vue").DefineComponent<{}, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,4 +1,4 @@
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
label: StringConstructor;
expand: {
type: BooleanConstructor;
@ -8,7 +8,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
type: BooleanConstructor;
default: boolean;
};
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
label: StringConstructor;
expand: {
type: BooleanConstructor;
@ -22,7 +22,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
expand: boolean;
isExpand: boolean;
}, {}, {
ArrowDown: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
ArrowUp: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
ArrowDown: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<import('vue').ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
ArrowUp: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<import('vue').ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,9 +1,9 @@
import { PropType } from "vue";
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
import { PropType } from 'vue';
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
modelValue: (NumberConstructor | StringConstructor)[];
labels: {
type: ArrayConstructor;
default: () => never[];
default: () => any[];
};
justify: {
type: PropType<"start" | "end" | "left" | "right" | "center" | "justify" | "match-parent">;
@ -13,11 +13,11 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
type: PropType<"card" | "default">;
default: string;
};
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("change" | "update:modelValue")[], "change" | "update:modelValue", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("change" | "update:modelValue")[], "change" | "update:modelValue", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
modelValue: (NumberConstructor | StringConstructor)[];
labels: {
type: ArrayConstructor;
default: () => never[];
default: () => any[];
};
justify: {
type: PropType<"start" | "end" | "left" | "right" | "center" | "justify" | "match-parent">;
@ -28,11 +28,11 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
default: string;
};
}>> & Readonly<{
onChange?: ((...args: any[]) => any) | undefined;
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
onChange?: (...args: any[]) => any;
"onUpdate:modelValue"?: (...args: any[]) => any;
}>, {
type: "default" | "card";
labels: unknown[];
justify: "center" | "left" | "right" | "justify" | "start" | "end" | "match-parent";
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,5 +1,5 @@
export declare function useForm(): {
Form: import("vue").Ref<any, any>;
Form: import('vue').Ref<any, any>;
config: {
[x: string]: any;
title?: any;
@ -7,42 +7,42 @@ export declare function useForm(): {
width?: any;
props: {
[x: string]: any;
inline?: boolean | undefined;
labelPosition?: "left" | "right" | "top" | undefined;
labelWidth?: string | number | undefined;
labelSuffix?: string | undefined;
hideRequiredAsterisk?: boolean | undefined;
showMessage?: boolean | undefined;
inlineMessage?: boolean | undefined;
statusIcon?: boolean | undefined;
validateOnRuleChange?: boolean | undefined;
size?: ElementPlus.Size | undefined;
disabled?: boolean | undefined;
inline?: boolean;
labelPosition?: "left" | "right" | "top";
labelWidth?: string | number;
labelSuffix?: string;
hideRequiredAsterisk?: boolean;
showMessage?: boolean;
inlineMessage?: boolean;
statusIcon?: boolean;
validateOnRuleChange?: boolean;
size?: ElementPlus.Size;
disabled?: boolean;
};
items: {
[x: string]: any;
type?: "tabs" | undefined;
prop?: (string & {}) | undefined;
type?: "tabs";
prop?: string & {};
props?: {
[x: string]: any;
labels?: {
[x: string]: any;
label: string;
value: string;
name?: string | undefined;
name?: string;
icon?: any;
lazy?: boolean | undefined;
}[] | undefined;
justify?: "left" | "center" | "right" | undefined;
color?: string | undefined;
mergeProp?: boolean | undefined;
labelWidth?: string | undefined;
error?: string | undefined;
showMessage?: boolean | undefined;
inlineMessage?: boolean | undefined;
size?: "medium" | "default" | "small" | undefined;
} | undefined;
span?: number | undefined;
lazy?: boolean;
}[];
justify?: "left" | "center" | "right";
color?: string;
mergeProp?: boolean;
labelWidth?: string;
error?: string;
showMessage?: boolean;
inlineMessage?: boolean;
size?: "medium" | "default" | "small";
};
span?: number;
col?: {
span: number;
offset: number;
@ -54,184 +54,184 @@ export declare function useForm(): {
lg: any;
xl: any;
tag: string;
} | undefined;
group?: string | undefined;
collapse?: boolean | undefined;
};
group?: string;
collapse?: boolean;
value?: any;
label?: string | undefined;
label?: string;
renderLabel?: any;
flex?: boolean | undefined;
hook?: "string" | "number" | "boolean" | "join" | AnyString | "empty" | "split" | "booleanNumber" | "datetimeRange" | "splitJoin" | "json" | {
bind?: (ClForm.Hook["Pipe"] | ClForm.Hook["Pipe"][]) | undefined;
submit?: (ClForm.Hook["Pipe"] | ClForm.Hook["Pipe"][]) | undefined;
reset?: ((prop: string) => string[]) | undefined;
} | undefined;
flex?: boolean;
hook?: "string" | "number" | "boolean" | "join" | "split" | AnyString | "empty" | "booleanNumber" | "datetimeRange" | "splitJoin" | "json" | {
bind?: ClForm.Hook["Pipe"] | ClForm.Hook["Pipe"][];
submit?: ClForm.Hook["Pipe"] | ClForm.Hook["Pipe"][];
reset?: (prop: string) => string[];
};
hidden?: boolean | ((options: {
scope: obj;
}) => boolean) | undefined;
}) => boolean);
prepend?: {
[x: string]: any;
name?: string | undefined;
name?: string;
options?: {
[x: string]: any;
label?: string | undefined;
label?: string;
value?: any;
color?: string | undefined;
type?: string | undefined;
color?: string;
type?: string;
}[] | {
value: {
[x: string]: any;
label?: string | undefined;
label?: string;
value?: any;
color?: string | undefined;
type?: string | undefined;
color?: string;
type?: string;
}[];
} | undefined;
};
props?: {
[x: string]: any;
onChange?: ((value: any) => void) | undefined;
onChange?: (value: any) => void;
} | {
value: {
[x: string]: any;
onChange?: ((value: any) => void) | undefined;
onChange?: (value: any) => void;
};
} | undefined;
style?: obj | undefined;
};
style?: obj;
slots?: {
[key: string]: (data?: any) => any;
} | undefined;
};
vm?: any;
} | undefined;
};
component?: {
[x: string]: any;
name?: string | undefined;
name?: string;
options?: {
[x: string]: any;
label?: string | undefined;
label?: string;
value?: any;
color?: string | undefined;
type?: string | undefined;
color?: string;
type?: string;
}[] | {
value: {
[x: string]: any;
label?: string | undefined;
label?: string;
value?: any;
color?: string | undefined;
type?: string | undefined;
color?: string;
type?: string;
}[];
} | undefined;
};
props?: {
[x: string]: any;
onChange?: ((value: any) => void) | undefined;
onChange?: (value: any) => void;
} | {
value: {
[x: string]: any;
onChange?: ((value: any) => void) | undefined;
onChange?: (value: any) => void;
};
} | undefined;
style?: obj | undefined;
};
style?: obj;
slots?: {
[key: string]: (data?: any) => any;
} | undefined;
};
vm?: any;
} | undefined;
};
append?: {
[x: string]: any;
name?: string | undefined;
name?: string;
options?: {
[x: string]: any;
label?: string | undefined;
label?: string;
value?: any;
color?: string | undefined;
type?: string | undefined;
color?: string;
type?: string;
}[] | {
value: {
[x: string]: any;
label?: string | undefined;
label?: string;
value?: any;
color?: string | undefined;
type?: string | undefined;
color?: string;
type?: string;
}[];
} | undefined;
};
props?: {
[x: string]: any;
onChange?: ((value: any) => void) | undefined;
onChange?: (value: any) => void;
} | {
value: {
[x: string]: any;
onChange?: ((value: any) => void) | undefined;
onChange?: (value: any) => void;
};
} | undefined;
style?: obj | undefined;
};
style?: obj;
slots?: {
[key: string]: (data?: any) => any;
} | undefined;
};
vm?: any;
} | undefined;
};
rules?: {
[x: string]: any;
type?: "string" | "number" | "boolean" | "method" | "regexp" | "integer" | "float" | "array" | "object" | "enum" | "date" | "url" | "hex" | "email" | "any" | undefined;
required?: boolean | undefined;
message?: string | undefined;
min?: number | undefined;
max?: number | undefined;
type?: "string" | "number" | "boolean" | "method" | "regexp" | "integer" | "float" | "array" | "object" | "enum" | "date" | "url" | "hex" | "email" | "any";
required?: boolean;
message?: string;
min?: number;
max?: number;
trigger?: any;
validator?: ((rule: any, value: any, callback: (error?: Error) => void) => void) | undefined;
validator?: (rule: any, value: any, callback: (error?: Error) => void) => void;
} | {
[x: string]: any;
type?: "string" | "number" | "boolean" | "method" | "regexp" | "integer" | "float" | "array" | "object" | "enum" | "date" | "url" | "hex" | "email" | "any" | undefined;
required?: boolean | undefined;
message?: string | undefined;
min?: number | undefined;
max?: number | undefined;
type?: "string" | "number" | "boolean" | "method" | "regexp" | "integer" | "float" | "array" | "object" | "enum" | "date" | "url" | "hex" | "email" | "any";
required?: boolean;
message?: string;
min?: number;
max?: number;
trigger?: any;
validator?: ((rule: any, value: any, callback: (error?: Error) => void) => void) | undefined;
}[] | undefined;
required?: boolean | undefined;
children?: /*elided*/ any[] | undefined;
validator?: (rule: any, value: any, callback: (error?: Error) => void) => void;
}[];
required?: boolean;
children?: /*elided*/ any[];
}[];
form: obj;
isReset?: boolean | undefined;
isReset?: boolean;
on?: {
open?: ((data: any) => void) | undefined;
close?: ((action: ClForm.CloseAction, done: fn) => void) | undefined;
submit?: ((data: any, event: {
open?: (data: any) => void;
close?: (action: ClForm.CloseAction, done: fn) => void;
submit?: (data: any, event: {
close: fn;
done: fn;
}) => void) | undefined;
change?: ((data: any, prop: string) => void) | undefined;
} | undefined;
}) => void;
change?: (data: any, prop: string) => void;
};
op: {
hidden?: boolean | undefined;
saveButtonText?: string | undefined;
closeButtonText?: string | undefined;
justify?: "flex-start" | "center" | "flex-end" | undefined;
hidden?: boolean;
saveButtonText?: string;
closeButtonText?: string;
justify?: "flex-start" | "center" | "flex-end";
buttons?: (`slot-${string}` | ClForm.CloseAction | {
[x: string]: any;
label: string;
type?: string | undefined;
hidden?: boolean | undefined;
type?: string;
hidden?: boolean;
onClick: (options: {
scope: obj;
}) => void;
})[] | undefined;
})[];
};
dialog: {
[x: string]: any;
title?: any;
height?: string | undefined;
width?: string | undefined;
hideHeader?: boolean | undefined;
controls?: Array<"fullscreen" | "close" | AnyString> | undefined;
height?: string;
width?: string;
hideHeader?: boolean;
controls?: Array<"fullscreen" | "close" | AnyString>;
};
};
form: obj;
visible: import("vue").Ref<boolean, boolean>;
saving: import("vue").Ref<boolean, boolean>;
loading: import("vue").Ref<boolean, boolean>;
disabled: import("vue").Ref<boolean, boolean>;
visible: import('vue').Ref<boolean, boolean>;
saving: import('vue').Ref<boolean, boolean>;
loading: import('vue').Ref<boolean, boolean>;
disabled: import('vue').Ref<boolean, boolean>;
};
export * from "./action";
export * from "./api";
export * from "./plugins";
export * from "./tabs";
export * from './action';
export * from './api';
export * from './plugins';
export * from './tabs';

View File

@ -1,7 +1,7 @@
import { Ref } from "vue";
import { Ref } from 'vue';
export declare function usePlugins(enable: boolean, { visible }: {
visible: Ref<boolean>;
}): {
create: (plugins?: ClForm.Plugin[]) => false | undefined;
create: (plugins?: ClForm.Plugin[]) => boolean;
submit: (data: any) => Promise<any>;
};

View File

@ -2,11 +2,11 @@ export declare function useTabs({ config, Form }: {
config: ClForm.Config;
Form: Vue.Ref<any>;
}): {
active: import("vue").Ref<string | undefined, string | undefined>;
list: import("vue").ComputedRef<ClFormTabs.labels>;
active: import('vue').Ref<string, string>;
list: import('vue').ComputedRef<ClFormTabs.labels>;
isLoaded: (value: any) => any;
onLoad: (value: any) => void;
get: () => ClForm.Item<any> | undefined;
get: () => ClForm.Item<any>;
set: (data: any) => void;
change: (value: any, isValid?: boolean) => Promise<unknown>;
clear: () => void;

View File

@ -1,11 +1,13 @@
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
name: StringConstructor;
inner: BooleanConstructor;
inline: BooleanConstructor;
enablePlugin: {
type: BooleanConstructor;
default: boolean;
};
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
name: StringConstructor;
inner: BooleanConstructor;
inline: BooleanConstructor;
enablePlugin: {
@ -16,5 +18,5 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
inline: boolean;
inner: boolean;
enablePlugin: boolean;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,4 +1,4 @@
import { App } from "vue";
import { App } from 'vue';
export declare const components: {
[key: string]: any;
};

View File

@ -1,2 +1,2 @@
declare const _default: import("vue").DefineComponent<{}, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,4 +1,4 @@
declare const _default: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
declare const _default: import('vue').DefineComponent<{}, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
[key: string]: any;
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,2 +1,2 @@
declare const _default: import("vue").DefineComponent<{}, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,2 +1,2 @@
declare const _default: import("vue").DefineComponent<{}, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
declare const _default: import('vue').DefineComponent<{}, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,5 +1,5 @@
import { type PropType } from "vue";
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
import { PropType } from 'vue';
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
modelValue: StringConstructor;
field: {
type: StringConstructor;
@ -10,7 +10,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
label: string;
value: string;
}>>;
default: () => never[];
default: () => any[];
};
onSearch: FunctionConstructor;
placeholder: StringConstructor;
@ -19,7 +19,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
default: number;
};
refreshOnInput: BooleanConstructor;
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("change" | "update:modelValue" | "field-change")[], "change" | "update:modelValue" | "field-change", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("change" | "update:modelValue" | "field-change")[], "change" | "update:modelValue" | "field-change", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
modelValue: StringConstructor;
field: {
type: StringConstructor;
@ -30,7 +30,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
label: string;
value: string;
}>>;
default: () => never[];
default: () => any[];
};
onSearch: FunctionConstructor;
placeholder: StringConstructor;
@ -40,9 +40,9 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
};
refreshOnInput: BooleanConstructor;
}>> & Readonly<{
onChange?: ((...args: any[]) => any) | undefined;
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
"onField-change"?: ((...args: any[]) => any) | undefined;
onChange?: (...args: any[]) => any;
"onUpdate:modelValue"?: (...args: any[]) => any;
"onField-change"?: (...args: any[]) => any;
}>, {
width: string | number;
refreshOnInput: boolean;
@ -51,5 +51,5 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
label: string;
value: string;
}[];
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -0,0 +1,3 @@
export declare function usePlugins(): {
create: (plugins?: ClSearch.Plugin[]) => void;
};

View File

@ -1,12 +1,12 @@
import { PropType } from "vue";
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
import { PropType } from 'vue';
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
inline: {
type: BooleanConstructor;
default: boolean;
};
props: {
type: ObjectConstructor;
default: () => void;
default: () => {};
};
data: {
type: ObjectConstructor;
@ -14,23 +14,26 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
};
items: {
type: PropType<ClForm.Item[]>;
default: () => never[];
default: () => any[];
};
resetBtn: {
type: BooleanConstructor;
default: boolean;
};
collapse: BooleanConstructor;
collapse: {
type: BooleanConstructor;
default: boolean;
};
onLoad: FunctionConstructor;
onSearch: FunctionConstructor;
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "reset"[], "reset", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, "reset"[], "reset", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
inline: {
type: BooleanConstructor;
default: boolean;
};
props: {
type: ObjectConstructor;
default: () => void;
default: () => {};
};
data: {
type: ObjectConstructor;
@ -38,23 +41,26 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
};
items: {
type: PropType<ClForm.Item[]>;
default: () => never[];
default: () => any[];
};
resetBtn: {
type: BooleanConstructor;
default: boolean;
};
collapse: BooleanConstructor;
collapse: {
type: BooleanConstructor;
default: boolean;
};
onLoad: FunctionConstructor;
onSearch: FunctionConstructor;
}>> & Readonly<{
onReset?: ((...args: any[]) => any) | undefined;
onReset?: (...args: any[]) => any;
}>, {
items: ClForm.Item<any>[];
props: Record<string, any>;
inline: boolean;
data: Record<string, any>;
props: Record<string, any>;
items: ClForm.Item<any>[];
inline: boolean;
resetBtn: boolean;
collapse: boolean;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -2,6 +2,6 @@ export declare function useData({ config, Table }: {
config: ClTable.Config;
Table: Vue.Ref<any>;
}): {
data: import("vue").Ref<obj[], obj[]>;
data: import('vue').Ref<obj[], obj[]>;
setData: (list: obj[]) => void;
};

View File

@ -2,6 +2,6 @@ export declare function useHeight({ config, Table }: {
Table: Vue.Ref<any>;
config: ClTable.Config;
}): {
maxHeight: import("vue").Ref<number, number>;
calcMaxHeight: import("lodash-es").DebouncedFunc<() => Promise<void>>;
maxHeight: import('vue').Ref<number, number>;
calcMaxHeight: import('lodash-es').DebouncedFunc<() => Promise<void>>;
};

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
export declare function useOp({ config }: {
config: ClTable.Config;
}): {
visible: import("vue").Ref<boolean, boolean>;
visible: import('vue').Ref<boolean, boolean>;
reBuild: (cb?: fn) => Promise<void>;
showColumn: (prop: string | string[], status?: boolean) => void;
hideColumn: (prop: string | string[]) => void;

View File

@ -1,7 +1,7 @@
export declare function useRender(): {
renderColumn: (columns: ClTable.Column[]) => (import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
renderColumn: (columns: ClTable.Column[]) => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
[key: string]: any;
}> | null)[];
}>[];
renderEmpty: (emptyText: string) => any;
renderAppend: () => any;
};

View File

@ -1,16 +1,16 @@
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
columns: {
type: ArrayConstructor;
default: () => never[];
default: () => any[];
};
autoHeight: {
type: BooleanConstructor;
default: null;
default: any;
};
height: null;
height: any;
contextMenu: {
type: (BooleanConstructor | ArrayConstructor)[];
default: null;
type: (ArrayConstructor | BooleanConstructor)[];
default: any;
};
defaultSort: ObjectConstructor;
sortRefresh: {
@ -22,21 +22,21 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
type: StringConstructor;
default: string;
};
}>, () => false | import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
}>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
[key: string]: any;
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("selection-change" | "sort-change")[], "selection-change" | "sort-change", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("selection-change" | "sort-change")[], "selection-change" | "sort-change", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
columns: {
type: ArrayConstructor;
default: () => never[];
default: () => any[];
};
autoHeight: {
type: BooleanConstructor;
default: null;
default: any;
};
height: null;
height: any;
contextMenu: {
type: (BooleanConstructor | ArrayConstructor)[];
default: null;
type: (ArrayConstructor | BooleanConstructor)[];
default: any;
};
defaultSort: ObjectConstructor;
sortRefresh: {
@ -49,13 +49,14 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
default: string;
};
}>> & Readonly<{
"onSelection-change"?: ((...args: any[]) => any) | undefined;
"onSort-change"?: ((...args: any[]) => any) | undefined;
"onSelection-change"?: (...args: any[]) => any;
"onSort-change"?: (...args: any[]) => any;
}>, {
columns: unknown[];
autoHeight: boolean;
height: any;
contextMenu: boolean | unknown[];
sortRefresh: boolean;
rowKey: string;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

View File

@ -1,7 +1,7 @@
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
items: {
type: ArrayConstructor;
default: () => never[];
default: () => any[];
};
props: ObjectConstructor;
sync: BooleanConstructor;
@ -13,10 +13,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
onClosed: FunctionConstructor;
onInfo: FunctionConstructor;
onSubmit: FunctionConstructor;
}>, () => any, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("opened" | "closed")[], "opened" | "closed", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
}>, () => any, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, ("opened" | "closed")[], "opened" | "closed", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
items: {
type: ArrayConstructor;
default: () => never[];
default: () => any[];
};
props: ObjectConstructor;
sync: BooleanConstructor;
@ -29,10 +29,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
onInfo: FunctionConstructor;
onSubmit: FunctionConstructor;
}>> & Readonly<{
onOpened?: ((...args: any[]) => any) | undefined;
onClosed?: ((...args: any[]) => any) | undefined;
onOpened?: (...args: any[]) => any;
onClosed?: (...args: any[]) => any;
}>, {
sync: boolean;
items: unknown[];
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
export default _default;

13
packages/crud/types/entry.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
import { App } from 'vue';
declare const Crud: {
install(app: App, options?: any): {
name: string;
};
};
export { Crud };
export * from './emitter';
export * from './hooks';
export * from './locale';
export { registerFormHook } from './utils/form-hook';
export { renderNode } from './utils/vnode';
export { ContextMenu } from './components/context-menu';

View File

@ -1,10 +1,10 @@
import { Ref } from "vue";
export declare function useCrud(options?: ClCrud.Options, cb?: (app: ClCrud.Ref) => void): Ref<ClCrud.Ref | undefined, ClCrud.Ref | undefined>;
export declare function useUpsert<T = any>(options?: ClUpsert.Options<T>): Ref<ClUpsert.Ref<any> | undefined, ClUpsert.Ref<any> | undefined>;
export declare function useTable<T = any>(options?: ClTable.Options<T>, cb?: (table: ClTable.Ref) => void): Ref<ClTable.Ref<T> | undefined, ClTable.Ref<T> | undefined>;
export declare function useForm<T = any>(cb?: (app: ClForm.Ref<T>) => void): Ref<ClForm.Ref<T> | undefined, ClForm.Ref<T> | undefined>;
export declare function useAdvSearch<T = any>(options?: ClAdvSearch.Options<T>): Ref<ClAdvSearch.Ref<T> | undefined, ClAdvSearch.Ref<T> | undefined>;
export declare function useSearch<T = any>(options?: ClSearch.Options<T>): Ref<ClSearch.Ref<T> | undefined, ClSearch.Ref<T> | undefined>;
import { Ref } from 'vue';
export declare function useCrud(options?: ClCrud.Options, cb?: (app: ClCrud.Ref) => void): Ref<ClCrud.Ref, ClCrud.Ref>;
export declare function useUpsert<T = any>(options?: ClUpsert.Options<T>): Ref<ClUpsert.Ref<any>, ClUpsert.Ref<any>>;
export declare function useTable<T = any>(options?: ClTable.Options<T>, cb?: (table: ClTable.Ref) => void): Ref<ClTable.Ref<T>, ClTable.Ref<T>>;
export declare function useForm<T = any>(cb?: (app: ClForm.Ref<T>) => void): Ref<ClForm.Ref<T>, ClForm.Ref<T>>;
export declare function useAdvSearch<T = any>(options?: ClAdvSearch.Options<T>): Ref<ClAdvSearch.Ref<T>, ClAdvSearch.Ref<T>>;
export declare function useSearch<T = any>(options?: ClSearch.Options<T>): Ref<ClSearch.Ref<T>, ClSearch.Ref<T>>;
export declare function useDialog(options?: {
onFullscreen(visible: boolean): void;
}): ClDialog.Provide;

View File

@ -1,4 +1,4 @@
import { Mitt } from "../utils/mitt";
import { Mitt } from '../utils/mitt';
export declare function useCore(): {
crud: ClCrud.Ref;
mitt: Mitt;
@ -13,4 +13,4 @@ export declare function useRefs(): {
};
export declare function useProxy(ctx: any): any;
export declare function useElApi(keys: string[], el: any): obj;
export * from "./crud";
export * from './crud';

View File

@ -1,14 +0,0 @@
import type { App } from "vue";
import "./static/index.scss";
declare const Crud: {
install(app: App, options?: Options): {
name: string;
};
};
export default Crud;
export * from "./emitter";
export * from "./hooks";
export * from "./plugins";
export * from "./locale";
export { registerFormHook } from "./utils/form-hook";
export { ContextMenu } from "./components/context-menu";

View File

@ -15,7 +15,6 @@ declare const _default: {
advSearch: string;
searchKey: string;
placeholder: string;
placeholderSelect: string;
tips: string;
saveSuccess: string;
deleteSuccess: string;

View File

@ -16,7 +16,6 @@ export declare const locale: {
advSearch: string;
searchKey: string;
placeholder: string;
placeholderSelect: string;
tips: string;
saveSuccess: string;
deleteSuccess: string;
@ -49,7 +48,6 @@ export declare const locale: {
advSearch: string;
searchKey: string;
placeholder: string;
placeholderSelect: string;
tips: string;
saveSuccess: string;
deleteSuccess: string;
@ -65,7 +63,7 @@ export declare const locale: {
collapse: string;
expand: string;
};
zhCn: {
"zh-cn": {
op: string;
add: string;
delete: string;
@ -82,7 +80,6 @@ export declare const locale: {
advSearch: string;
searchKey: string;
placeholder: string;
placeholderSelect: string;
tips: string;
saveSuccess: string;
deleteSuccess: string;
@ -98,7 +95,7 @@ export declare const locale: {
collapse: string;
expand: string;
};
zhTw: {
"zh-tw": {
op: string;
add: string;
delete: string;
@ -115,7 +112,6 @@ export declare const locale: {
advSearch: string;
searchKey: string;
placeholder: string;
placeholderSelect: string;
tips: string;
saveSuccess: string;
deleteSuccess: string;

View File

@ -15,7 +15,6 @@ declare const _default: {
advSearch: string;
searchKey: string;
placeholder: string;
placeholderSelect: string;
tips: string;
saveSuccess: string;
deleteSuccess: string;

View File

@ -15,7 +15,6 @@ declare const _default: {
advSearch: string;
searchKey: string;
placeholder: string;
placeholderSelect: string;
tips: string;
saveSuccess: string;
deleteSuccess: string;

View File

@ -15,7 +15,6 @@ declare const _default: {
advSearch: string;
searchKey: string;
placeholder: string;
placeholderSelect: string;
tips: string;
saveSuccess: string;
deleteSuccess: string;

0
packages/crud/types/main.d.ts vendored Normal file
View File

Some files were not shown because too many files have changed in this diff Show More