# 自用组件库

## 安装

```bash
npm install auto-vue-manual
```

## 使用

```js
import AutoVueManual from "auto-vue-manual";
import type { InstallOptions } from 'auto-vue-manual';
import 'auto-vue-manual/dist/index.css';

import request from "@/global/request";
import { Translate } from "@/languages/index";

const options: InstallOptions = {
  request,
  translate: Translate
}

const app = createApp(App);
app.use(AutoVueManual, options);
app.mount('#app');
```

## 目录

#### Table

[ProTable/ProTableSummary](#protable--protablesummary)  
[ProTableList](#protablelist)

#### Modal

[BasicDialog](#basicdialog)  
[BasicDrawer](#basicdrawer)  
[FormDialog](#formdialog)  
[TableDialog](#tabledialog)

#### Upload

[UploadAvatar](#uploadavatar)  
[UploadImage](#uploadimage)  
[UploadImages](#uploadimages)

## Button

### 组件列表

- OpenButton 新建按钮
- RefreshButton 刷新按钮
- SearchButton 搜索按钮
- ResetButton 重置按钮

### 通用 Props

| 属性名   | 类型    | 说明         | 默认值                                                             |
| -------- | ------- | ------------ | ------------------------------------------------------------------ |
| type     | string  | 按钮类型     | 'primary'（Open/Search），'default'（Refresh），'warning'（Reset） |
| size     | string  | 按钮尺寸     | 'default'                                                          |
| showIcon | boolean | 是否显示图标 | true                                                               |
| circle   | boolean | 是否圆形按钮 | true                                                               |
| plain    | boolean | 是否朴素按钮 | false                                                              |
| disabled | boolean | 是否禁用     | false                                                              |
| loading  | boolean | 是否加载中   | false                                                              |
| t        | string  | 按钮文本     | ''                                                                 |

### OpenButton

- 用于新建操作，蓝色圆形加号图标。
- 事件：`@open` 点击触发

### RefreshButton

- 用于刷新操作，圆形刷新图标。
- 事件：`@refresh` 点击触发
- 支持 loading 状态自定义

### SearchButton

- 用于搜索操作，蓝色圆形放大镜图标。
- 事件：`@search` 点击触发

### ResetButton

- 用于重置操作，橙色圆形刷新图标。
- 事件：`@reset` 点击触发

### 示例代码

```vue
<template>
  <OpenButton @open="onOpen" />
  <RefreshButton :loading="loading" @refresh="onRefresh" />
  <SearchButton t="搜索" @search="onSearch" />
  <ResetButton t="重置" @reset="onReset" />
</template>
<script setup lang="ts">
  import { ref } from 'vue'
  import { OpenButton, RefreshButton, SearchButton, ResetButton } from 'auto-vue-manual'
  const loading = ref(false)
  const onOpen = () => {
    /* 新建逻辑 */
  }
  const onRefresh = () => {
    loading.value = true
    setTimeout(() => (loading.value = false), 1000)
  }
  const onSearch = () => {
    /* 搜索逻辑 */
  }
  const onReset = () => {
    /* 重置逻辑 */
  }
</script>
```

# Document

## Table

### ProTable / ProTableSummary

#### ColumnProps

| 属性名           | 类型                                                                          | 说明                                                                | 默认值 |
| ---------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------- | ------ |
| **type**         | `string`                                                                      | 列类型, index / selection/ radio/ expand/ sort/ icon/ tag/ copy     | -      |
| **prop**         | `string`                                                                      | 列数据字段名                                                        | -      |
| **label**        | `string`                                                                      | 列标题                                                              | -      |
| **width**        | `number`                                                                      | 列宽                                                                | -      |
| **align**        | `string`                                                                      | 列对齐方式                                                          | center |
| **isShow**       | `boolean`                                                                     | 是否显示在表格当中                                                  | true   |
| **search**       | `{ defaultValue }`                                                            | 搜索项配置, defaultValue可以设置默认的init-param                    | -      |
| **headerRender** | `(scope: HeaderRenderScope<T>) => VNode`                                      | 自定义表头内容渲染（tsx语法）                                       | -      |
| **render**       | `(scope: RenderScope<T>) => VNode string`                                     | 自定义单元格内容渲染（tsx语法），Basic和list的scope略有不同，请注意 | -      |
| **props**        | `{ api?: string, activeValue?: any, inactiveValue?: any, refresh?: boolean }` | type = switch 时，props 配置 (TODO 更新其他type)                    | -      |

#### Props 参数说明

| 属性名              | 类型                            | 说明                                                                  | 默认值 |
| ------------------- | ------------------------------- | --------------------------------------------------------------------- | ------ |
| **columns**         | [`ColumnProps[]`](#columnprops) | 必填，列配置项                                                        | -      |
| **data**            | `any[]`                         | 静态 table data 数据，若存在则不会使用 request url 返回的 data        | -      |
| **url**             | `string`                        | 实际请求接口                                                          | -      |
| **auto-search**     | `boolean`                       | 是否自动执行请求 api                                                  | true   |
| **request-error**   | `(params: any) => void`         | 表格 api 请求错误监听                                                 | -      |
| **data-callback**   | `(data: any) => any`            | 返回数据的回调函数，可以对数据进行处理                                | -      |
| **has-pagination**  | `boolean`                       | 是否需要分页组件                                                      | true   |
| **init-param**      | `any`                           | 初始化请求参数                                                        | {}     |
| **search-param**    | `any`                           | 搜索参数                                                              | {}     |
| **border**          | `boolean`                       | 是否带有纵向边框                                                      | true   |
| **row-key**         | `string`                        | 行数据的 Key，用来优化 Table 的渲染，当表格数据多选时，所指定的 id ） | id     |
| **size**            | `string`                        | 列表大小，default/small/large                                         | small  |
| **page-size**       | `number`                        | 列表页大小                                                            | 0      |
| **row-h**           | `number`                        | 列表行高                                                              | 0      |
| **ext-h**           | `number`                        | 列表额外高度                                                          | 0      |
| **sum-url**         | `string`                        | 汇总接口url，仅 ProTableSummary 有效                                  |        |
| **sum-text**        | `string`                        | 汇总文本，仅 ProTableSummary 有效                                     | Total  |
| **sum-text-format** | `string`                        | 汇总文本格式，仅 ProTableSummary 有效                                 | \*     |

#### Event 事件说明

| 事件名             | 说明                                     | 参数                              |
| ------------------ | ---------------------------------------- | --------------------------------- |
| **@row-click**     | 行点击事件，已排除 status / operation 列 | `(row: any, column: any) => void` |
| **@row-dblclick**  | 行双击事件，已排除 status / operation 列 | `(row: any, column: any) => void` |
| **@switch-change** | 开关切换事件                             | `(value, scope, column) => void`  |

#### Expose 暴露方法说明

| 方法名            | 说明                                   | 参数                                          |
| ----------------- | -------------------------------------- | --------------------------------------------- |
| **@search**       | 搜索事件                               | `(searchParam?: Record<string, any>) => void` |
| **@reset**        | 重置事件                               | `() => void`                                  |
| **@getTableList** | 获取表格数据，不更新搜索参数及分页参数 | `() => void`                                  |

#### 示例代码

```vue
<template>
  <div>
    <el-button @click="search">搜索</el-button>
    <el-button @click="reset">重置</el-button>
  </div>
  <ProTable ref="proTableRef" :columns="columns" url="/league/search" :search-param="params" @row-dblclick="onRowDblclick">
    <template #logo="{ row }">
      <div class="flex-center h-100">
        <el-image style="width: 36px; height: 36px" :src="row.logo" />
      </div>
    </template>
  </ProTable>
</template>
<script setup lang="ts">
  import type { ColumnProps, RenderScope, HeaderRenderScope } from 'auto-vue-manual'

  import { reactive, ref } from 'vue'
  import { ProTable } from 'auto-vue-manual'

  const proTableRef = ref<InstanceType<typeof ProTable>>()
  const columns: ColumnProps[] = [
    { label: 'index', type: 'index' },
    { prop: 'code', label: '代号', width: 100, type: 'tag' },
    { prop: 'logo', label: '标志', width: 100 },
    {
      prop: 'status',
      label: '状态',
      width: 100,
      type: 'switch',
      props: {
        activeValue: 1,
        inactiveValue: 2,
        api: '/league/change_status',
        refresh: true
      }
    },
    {
      prop: 'name',
      label: '名称',
      width: 0,
      align: 'right',
      search: { defaultValue: 'League' },
      headerRender: ({ column }: HeaderRenderScope<any>) => {
        return <span>headerRender: {column.label}</span>
      },
      render: ({ row }: RenderScope<any>) => {
        return <span>render: {row.name}</span>
      }
    }
  ]
  const params = reactive({
    keyword: ''
  })
  const search = () => {
    // 修改搜索参数
    params.keyword = 'League'
    proTableRef.value?.search()
    // 直接传入参数
    // proTableRef.value?.search({
    //   keyword: "League",
    // })
  }
  const reset = () => {
    proTableRef.value?.reset()
  }
  const onRowDblclick = (row: any, column: any, event: any) => {
    console.log('onRowDblclick', row, column, event)
  }
</script>
```

## ProTableList

#### Props 参数说明

| 属性名      | 类型     | 说明                                                                  | 默认值 |
| ----------- | -------- | --------------------------------------------------------------------- | ------ |
| **row-key** | `string` | 行数据的 Key，用来优化 Table 的渲染，当表格数据多选时，所指定的 id ） | id     |

其余同 [ProTable](#protable--protablesummary)

#### Event 事件说明

| 事件名            | 说明                                                                              | 参数                                  |
| ----------------- | --------------------------------------------------------------------------------- | ------------------------------------- |
| **@row-click**    | 行点击事件，未排除 status / operation 列，需添加 e.stopPropagation() 阻止事件冒泡 | `({ row: any, column: any }) => void` |
| **@row-dblclick** | 行双击事件，未排除 status / operation 列，需添加 e.stopPropagation() 阻止事件冒泡 | `({ row: any, column: any }) => void` |

#### Expose 暴露方法说明

与 ProTable 相同。

#### 示例代码

```vue
<template>
  <div>
    <el-button @click="search">搜索</el-button>
    <el-button @click="reset">重置</el-button>
  </div>
  <ProTableList ref="proTableRef" row-key="key" :columns="columns" :search-param="params" url="/page/list" @row-dblclick="onRowDblclick" />
</template>
<script setup lang="tsx">
  import type { RowEventHandlerParams } from 'element-plus'
  import type { ColumnProps, HeaderRenderScope, RenderScope } from 'auto-vue-manual'

  import { ref, reactive } from 'vue'

  import { Plus } from '@element-plus/icons-vue'
  import ProTableList from 'auto-vue-manual'

  const proTableRef = ref<InstanceType<typeof ProTableList>>()
  const columns: ColumnProps[] = [
    { label: 'index', type: 'index' },
    { prop: 'label', label: 'Label', width: 100, type: 'tag' },
    { prop: 'key', label: 'Key', width: 100, type: 'copy' },
    {
      prop: 'value',
      label: 'Value',
      width: 200,
      headerRender: (scope: HeaderRenderScope<any>) => {
        return <span>HeaderRender: {scope.column.label}</span>
      }
    },
    {
      prop: 'status',
      label: 'Status',
      width: 100,
      type: 'switch',
      props: {
        activeValue: 1,
        inactiveValue: 2,
        api: '/league/change_status',
        refresh: true
      }
    },
    {
      prop: 'action',
      label: 'Action',
      width: 60,
      align: 'center',
      render: (scope: RenderScope<any>) => {
        return (
          <el-button
            type="primary"
            size="small"
            link
            icon={Plus}
            onClick={(e: Event) => {
              e.stopPropagation()
              console.log('onclick', e)
            }}
          >
            <span>render: {scope.rowData.label}</span>
          </el-button>
        )
      }
    }
  ]
  const params = reactive({
    keyword: ''
  })
  const search = () => {
    // 修改搜索参数
    params.keyword = 'League'
    proTableRef.value?.search()
    // 直接传入参数
    // proTableRef.value?.search({
    //   keyword: "League",
    // })
  }
  const reset = () => {
    proTableRef.value?.reset()
  }
  const onRowDblclick = (row: RowEventHandlerParams) => {
    console.log('onRowDblclick', row)
  }
</script>
```

## Modal 弹窗/抽屉

### 统一说明

- 所有弹窗类组件（BasicDialog、FormDialog、TableDialog）均基于 BasicDialog 实现，props/事件/用法风格统一。
- 所有抽屉类组件均基于 BasicDrawer 实现。
- 支持 v-bind 透传 Element Plus Dialog/Drawer 的所有原生属性。

### 通用 Props

| 属性名            | 类型    | 说明                    | 默认值 |
| ----------------- | ------- | ----------------------- | ------ |
| visible           | boolean | 是否显示                | false  |
| showClose         | boolean | 是否显示关闭按钮        | true   |
| title             | string  | 标题                    | Title  |
| width             | string  | 宽度                    | 520px  |
| top               | string  | 顶部距离                | 15vh   |
| dialogProps       | object  | 透传 Dialog/Drawer 属性 | {}     |
| appendToBody      | boolean | 是否插入 body           | true   |
| lockScroll        | boolean | 是否锁定滚动            | true   |
| closeOnClickModal | boolean | 点击遮罩关闭            | false  |

### BasicDialog

- 通用弹窗基类，支持所有通用 props 和事件。
- 事件：`@update:visible`、`@closed`、`@submit`

### BasicDrawer

- 通用抽屉基类，支持所有通用 props 和事件。
- 事件：`@update:visible`、`@closed`

### FormDialog

- 基于 BasicDialog 扩展，内置底部按钮，适合表单场景。
- 额外 props：`executing`（是否执行中）、`footer`（是否显示底部）、`btnSize`、`okText`、`cancelText`
- 事件：`@submit`、`@closed`、`@before-close`

### TableDialog

- 基于 BasicDialog 扩展，适合表格弹窗场景。
- 额外 props：`requesting`（是否请求中）

### 示例代码

```vue
<template>
  <OpenButton @open="visible = true" />
  <BasicDialog :visible="visible" title="标题" width="520px" @update:visible="visible = $event" @closed="onClosed">
    <template #default>内容区域</template>
  </BasicDialog>
</template>
<script setup lang="ts">
  import { ref } from 'vue'
  import { BasicDialog, OpenButton } from 'auto-vue-manual'
  const visible = ref(false)
  const onClosed = () => {
    visible.value = false
  }
</script>
```

### FormDialog 示例

```vue
<template>
  <OpenButton @open="visible = true" />
  <FormDialog :visible="visible" title="表单弹窗" @update:visible="visible = $event" @submit="onSubmit">
    <template #default>
      <el-input v-model="form.name" placeholder="请输入名称" />
    </template>
  </FormDialog>
</template>
<script setup lang="ts">
  import { ref } from 'vue'
  import { FormDialog, OpenButton } from 'auto-vue-manual'
  const visible = ref(false)
  const form = ref({ name: '' })
  const onSubmit = () => {
    /* 提交逻辑 */
  }
</script>
```

## Upload

### UploadAvatar

#### Props 参数说明

| 属性名       | 类型      | 说明         | 默认值 |
| ------------ | --------- | ------------ | ------ |
| **url**      | `string`  | 上传地址     | -      |
| **avatar**   | `string`  | 头像地址     | -      |
| **text**     | `string`  | 上传提示     | -      |
| **path**     | `string`  | 保存路径     | -      |
| **preview**  | `boolean` | 是否显示预览 | false  |
| **disabled** | `boolean` | 是否禁用     | false  |
| **size**     | `number`  | 大小（KB）   | 5120   |

### UploadImage

#### Props 参数说明

| 属性名    | 类型     | 说明     | 默认值 |
| --------- | -------- | -------- | ------ |
| **image** | `string` | 图片地址 | -      |

其余同 [UploadAvatar](#uploadavatar)

#### 示例代码

```vue
<template>
  <UploadAvatar ref="uploadAvatarRef" url="/upload/image" :avatar="avatar" text="上传头像" path="/avatar" preview :size="1024" />
</template>
<script setup lang="ts">
  import { ref } from 'vue'
  import UploadAvatar from 'auto-vue-manual'

  const uploadAvatarRef = ref<InstanceType<typeof UploadAvatar>>()
  const avatar = ref('')
</script>
```

### UploadImages

#### Props 参数说明

| 属性名     | 类型         | 说明     | 默认值 |
| ---------- | ------------ | -------- | ------ |
| **images** | `FileList[]` | 图片地址 | -      |
| **limit**  | `number`     | 限制数量 | 10     |

其余同 [UploadAvatar](#uploadavatar)

#### 示例代码

```vue
<template>
  <UploadImages ref="uploadImagesRef" url="/upload/image" :images="images" text="上传图片" path="/image" preview :size="1024" />
</template>
<script setup lang="ts">
  import type { FileList } from 'auto-vue-manual'

  import { ref } from 'vue'
  import UploadImages from 'auto-vue-manual'

  const uploadImagesRef = ref<InstanceType<typeof UploadImages>>()
  const images = ref<FileList[]>([])
</script>
```

## Tinymce 富文本编辑器

### 组件说明

基于 tinymce 封装的富文本编辑器，支持图片上传、字数统计、代码高亮等常用功能，适用于内容管理、文章编辑等场景。

### Props 参数说明

| 属性名   | 类型    | 说明                  | 默认值        |
| -------- | ------- | --------------------- | ------------- |
| url      | string  | 图片上传接口          | /upload/image |
| content  | string  | 编辑器内容（v-model） | ''            |
| height   | number  | 编辑器高度            | 600           |
| disabled | boolean | 是否禁用编辑          | false         |

### 事件

| 事件名         | 说明           | 参数          |
| -------------- | -------------- | ------------- |
| update:content | 内容变更时触发 | value: string |

### 功能特性

- 支持图片粘贴/上传，自动调用 `url` 接口
- 支持字数统计、代码高亮、列表、字体样式等
- 支持自定义高度、禁用状态
- 默认中文界面

### 示例代码

```vue
<template>
  <Tinymce v-model:content="content" :height="400" :url="'/upload/image'" />
  <p>内容：{{ content }}</p>
</template>
<script setup lang="ts">
  import { ref } from 'vue'
  import Tinymce from 'auto-vue-manual'
  const content = ref('<p>初始内容</p>')
</script>
```
