npm.io
1.0.4 • Published 10h ago

oceanx-component-ui-antd

Licence
UNLICENSED
Version
1.0.4
Deps
2
Size
362 kB
Vulns
1
Weekly
0

oceanx-component-ui-antd

基于 Vue 3 + ant-design-vue 4 的 Schema 驱动组件库。

安装后可直接使用:

  • <antd-table> — CRUD 表格(搜索 / 增删改查 / 分页 / 列设置)
  • <antd-form> — Schema 表单(分组 / 分步 / JSON 嵌套)
  • <antd-schema-conf> — 配置页(拉取 schema + 编辑保存)

安装

npm install oceanx-component-ui-antd
# 或
pnpm add oceanx-component-ui-antd

Peer 依赖(业务项目需自行安装):

npm install vue ant-design-vue @ant-design/icons-vue dayjs

快速接入

1. 全局注册(推荐)
// main.js
import { createApp } from 'vue'
import Antd from 'ant-design-vue'
import dayjs from 'dayjs'
import 'dayjs/locale/zh-cn'
import 'ant-design-vue/dist/reset.css'

import OceanxUI, { ANTD_THEME } from 'oceanx-component-ui-antd'
import 'oceanx-component-ui-antd/style.css'

import App from './App.vue'
import zhCN from 'ant-design-vue/es/locale/zh_CN'

dayjs.locale('zh-cn')

const app = createApp(App)
app.use(Antd)
app.use(OceanxUI) // 注册 antd-table / antd-form / antd-schema-conf
app.mount('#app')

根组件建议包一层 ConfigProvider(与演示站一致):

<template>
  <a-config-provider :locale="zhCN" :theme="ANTD_THEME">
    <a-app>
      <router-view />
    </a-app>
  </a-config-provider>
</template>

<script>
import zhCN from 'ant-design-vue/es/locale/zh_CN'
import { ANTD_THEME } from 'oceanx-component-ui-antd'

export default {
  setup() {
    return { zhCN, ANTD_THEME }
  }
}
</script>
2. 按需引入
<template>
  <CTable :res="tableRes" row-key-field="id" />
  <CForm
    v-model="formData"
    :visible-fields="visibleFields"
    :rules="rules"
  />
</template>

<script>
import { CTable, CForm } from 'oceanx-component-ui-antd'
import 'oceanx-component-ui-antd/style.css'

export default {
  components: { CTable, CForm },
  // ...
}
</script>

按需引入时,组件标签为 CTable / CForm;全局注册后模板里写 antd-table / antd-form


antd-table 表格

最小用法
<template>
  <antd-table :res="tableRes" row-key-field="id" />
</template>

<script>
export default {
  setup() {
    const tableRes = {
      code: 200,
      total: 2,
      data: [
        { id: 1, name: '设备A', role: 'admin' },
        { id: 2, name: '设备B', role: 'user' }
      ],
      schema: [
        {
          field: 'id',
          title: 'ID',
          type: 'number',
          hidden: ['add', 'edit']
        },
        {
          field: 'name',
          title: '名称',
          type: 'text',
          verify: [{ required: true, message: '名称不能为空' }]
        },
        {
          field: 'role',
          title: '角色',
          type: 'select',
          options: {
            data: [
              { value: 'admin', name: '管理员' },
              { value: 'user', name: '用户' }
            ],
            render: 'tag'
          }
        }
      ]
    }

    return { tableRes }
  }
}
</script>

res 也可拆开传::data + :schema + :total

常用 Props
Prop 类型 默认 说明
res Object {} 接口整包:{ data, schema, total }
data Array [] 行数据(无 res 时)
schema Array [] 字段 Schema
total Number 0 总数
row-key-field String 'id' 行主键
search-fields Object/Array {} 搜索字段,推荐对象:{ name: true, role: { multiple: true, default: ['admin'] } }
search-cols Number 3 搜索区列数
api Object/false false 远程 CRUD,见下方
params Object {} 列表固定查询参数
options Object actionButtons / toolbarButtonsshowSelection 为布尔值时覆盖下方同名 prop
file-props Object {} 上传配置
form-layout Object { cols: 2, labelPlacement: 'top' } 弹窗表单布局
cols Number 0 表单列数(优先于 formLayout.cols)
sorts / filters Object {} 列排序 / 筛选配置
is-card-list Boolean false 卡片列表模式
show-selection Boolean true 多选列,与批量删除按钮无关
远程 API
const api = {
  get: (query) => axios.get('/api/list', { params: query }),
  add: (row) => axios.post('/api/add', row),
  edit: (row) => axios.put('/api/edit', row),
  del: (row) => axios.delete(`/api/del/${row.id}`),
  // 可选
  export: (query) => axios.get('/api/export', { params: query, responseType: 'blob' })
}
<antd-table
  :api="api"
  row-key-field="id"
  :search-fields="{
    name: true,
    role: { multiple: true, default: ['admin'] }
  }"
/>

未搜索、未点表头排序时,api.get 收到的参数是:

{
  schema: true,
  desc: ['id'],
  pageable: {
    current_page: 1,
    page_size: 10
  }
}

搜索、排序、筛选会叠到同一对象上:

  • 文本类搜索字段写成模糊条件,例如搜名称「设备」→ name: { like: '设备' }
  • 日期范围收成 time_query: { name, start_time, end_time },原字段不再平铺
  • 表头降序 → desc: ['字段名'];升序 → asc: ['字段名'],此时不再带默认 desc: ['id']
  • 有列筛选时带 filters
  • params 里的固定条件会合并进来;其中的 schemapageable 会覆盖默认值,缺了仍会补回 schema: true 和完整 pageable

接口约定:列表返回 { code, data: [], schema: [], total }code === 200 视为成功。

常用事件
事件 说明
search 点击搜索
create / update / delete / clone 单行变更
batch-delete 批量删除
sort / filter / table-change 表头排序筛选
update:page / update:page-size 分页
常用插槽
<antd-table :res="tableRes" row-key-field="id">
  <!-- 自定义列 -->
  <template #column-amount="{ text }">
    ¥ {{ text }}
  </template>

  <!-- 自定义表单字段 -->
  <template #form-amount="{ field, modelValue, form, disabled }">
    <a-input-number
      :value="modelValue"
      :disabled="disabled"
      @update:value="(v) => (form[field.field] = v)"
    />
  </template>

  <!-- 工具栏扩展 -->
  <template #toolbar-buttons>
    <a-button>自定义</a-button>
  </template>

  <!-- 行操作扩展 -->
  <template #action-cell="{ row }">
    <a-button type="link" @click="onDetail(row)">详情</a-button>
  </template>
</antd-table>

antd-form 表单

适合弹窗内或独立配置页。需自行传入 v-model、可见字段与校验规则。

<template>
  <antd-form
    ref="formRef"
    v-model="formData"
    :visible-fields="visibleFields"
    :json-fields="jsonFields"
    :rules="rules"
    :cols="2"
    dialog-type="edit"
    :file-props="fileProps"
    :submit-handler="handleSubmit"
  />
  <a-button type="primary" @click="onSave">保存</a-button>
</template>

<script>
import { ref, computed } from 'vue'
import { _collectFormRules } from 'oceanx-component-ui-antd'

export default {
  setup() {
    const formRef = ref(null)
    const formData = ref({ name: '', config: {} })
    const schema = [
      { field: 'name', title: '名称', type: 'text' },
      {
        field: 'config',
        title: '配置',
        type: 'json',
        json: [
          { field: 'host', title: '地址', type: 'text' }
        ]
      }
    ]

    const visibleFields = computed(() =>
      schema.filter((f) => f.type !== 'json')
    )
    const jsonFields = computed(() =>
      schema.filter((f) => f.type === 'json')
    )
    const rules = _collectFormRules(schema)

    async function handleSubmit(payload) {
      await api.save(payload)
      return { code: 200 }
    }

    async function onSave() {
      await formRef.value?.submit()
    }

    return {
      formRef,
      formData,
      visibleFields,
      jsonFields,
      rules,
      handleSubmit,
      onSave
    }
  }
}
</script>
常用 Props
Prop 类型 说明
modelValue / v-model Object 表单数据
visible-fields Array 普通字段 schema(必填)
json-fields Array type: 'json' 字段
rules Object ant-design-vue Form rules
cols / form-layout Number / Object 列布局
dialog-type String add / edit / view 等,影响 hidden/disable
api Object { add, edit }
submit-handler Function 自定义提交
file-props Object 上传
disabled Boolean 整表禁用
暴露方法

通过 ref 调用:submit()validate()。分步表单还可读 isStepsModecurrentStep,并调用 nextStep()prevStep()

配置页场景更推荐直接用 <antd-schema-conf>,内部已包好 antd-form + 编辑/保存。


antd-schema-conf 配置页

<template>
  <antd-schema-conf
    :res="confRes"
    :api="confApi"
    :cols="2"
    :file-props="fileProps"
    @submit="onSubmit"
  />
</template>

<script>
export default {
  setup() {
    const confRes = {
      data: { title: '系统配置', retry: 3 },
      schema: [
        { field: 'title', title: '标题', type: 'text' },
        { field: 'retry', title: '重试次数', type: 'number' }
      ]
    }

    const confApi = {
      get: () => axios.get('/api/conf'),
      edit: (data) => axios.put('/api/conf', data)
    }

    function onSubmit(payload) {
      console.log('已保存', payload)
    }

    return { confRes, confApi, onSubmit }
  }
}
</script>

res.data 时优先用本地数据;否则走 api.get。保存走 api.edit,无 api 时抛出 submit 事件。


Schema 字段约定

{
  field: 'name',          // 字段名
  title: '名称',          // 标题
  type: 'text',           // 类型,见下表
  default: null,          // 默认值
  order: 0,               // 排序
  width: 160,             // 列宽
  verify: [],             // 校验规则
  options: {              // 选项类字段
    data: [{ value, name, color }],
    render: 'tag'         // 列表渲染:tag / switch 等
  },
  hidden: ['add', 'edit'], // 场景隐藏
  disable: ['edit'],      // 场景禁用
  bind: [],               // 联动
  json: [],               // type=json 时子字段
  jsonOptions: {}         // 动态 json schema
}
支持的 type
type 说明
text / str / textarea / password 文本
number / int / float 数字
select / checkbox / radio 选择
treeselect / cascader 树 / 级联
switch / bool 开关
date / datetime / time 日期时间
file / file-multiple 文件
base64 / image Base64 / 图片
tags / slider / progress 标签 / 滑块 / 进度
list[int] / list[float] / list[str] 列表
splice 拼接
json 嵌套对象 / 数组表
slot 外部插槽自定义
group 分组标题

文件上传 file-props

const fileProps = {
  fileUrl: '/api/file/upload',
  headers: { Authorization: 'Bearer xxx' },
  name: 'file',
  data: { scene: 'crud' },
  beforeUpload: (file) => true,
  onSuccess: (res, file) => {},
  onError: (err, file) => {},
  onRemove: (file) => true
}

主题

import { ANTD_THEME, CSS_VARS, _applyCssVars } from 'oceanx-component-ui-antd'

// 传给 a-config-provider :theme="ANTD_THEME"
// 或自定义 CSS 变量后再写入
_applyCssVars({
  ...CSS_VARS,
  '--var-primary-color': '#0958D9'
})

安装插件时默认会执行 _applyCssVars()。若业务自行管理变量:

app.use(OceanxUI, { applyCssVars: false })

自定义组件前缀:

app.use(OceanxUI, { prefix: 'ox' })
// 则使用 <ox-table> <ox-form>

本地开发 / 发布

# 演示站
npm run dev

# 打演示站产物 → demo-dist/
npm run build

# 打 npm 包产物 → dist/
npm run build:lib

# 发布(需已登录 npm / 私有源)
npm publish
# 或私有源:
# npm publish --registry=https://your-registry/

prepublishOnly 会在 publish 前自动执行 build:lib


导出一览

导出 说明
default / install Vue 插件
CTable / CRUDTable 表格
CForm / CRUDForm 表单
CSchemaConf / SchemaConf 配置页
fieldComponents 字段组件映射
_collectFormRules 从 schema 生成校验规则
ANTD_THEME / CSS_VARS / _applyCssVars 主题

注意事项

  1. 必须先 app.use(Antd),组件依赖 ant-design-vue。
  2. 建议外层使用 <a-app>,以便 Message / Modal 等上下文正常。
  3. 样式需引入:oceanx-component-ui-antd/style.cssant-design-vue/dist/reset.css
  4. Vue 版本建议 ^3.4,ant-design-vue 建议 ^4

Keywords