Skip to content

JPwise-Web 组件库文档 - Claude Code

🔥 必须使用的核心组件

JNPF-table 数据表格

强制使用,替代 el-table

vue
<JNPF-table 
  :data="tableData" 
  v-loading="listLoading"
  :hasC="true" 
  @selection-change="handleSelectionChange"
  :listQuery="listQuery">
  <el-table-column prop="NAME" label="名称" min-width="150" />
  <el-table-column prop="STATUS" label="状态" :formatter="formatter" />
</JNPF-table>

核心参数hasC(复选框) | listQuery(分页) | @selection-change(选择事件)

topOpts + tableOpts 操作按钮

vue
<!-- 顶部操作 -->
<topOpts @add="addOrUpdateHandle()" @delete="handleDelete" :buttonAuthList="buttonAuthList" />

<!-- 行内操作 -->
<template slot-scope="scope">
  <tableOpts @edit="addOrUpdateHandle(scope.row.id)" @delete="handleDelete(scope.row.id)" />
</template>

Pagination 分页

vue
<Pagination :total="total" :page.sync="listQuery.currentPage" :limit.sync="listQuery.pageSize" @pagination="initData" />

🛠️ JPW 业务组件

基础输入组件

vue
<!-- 输入框 -->
<JPWInput v-model="dataForm.name" placeholder="请输入" :maxlength="50" />

<!-- 下拉选择 -->
<JPWSelect v-model="dataForm.type" :options="typeOptions" placeholder="请选择" />

<!-- 级联选择 -->
<JPWCascader v-model="dataForm.category" :options="cascaderOptions" />

选项格式[{ enCode: "1", fullName: "选项名" }]

选择器组件

vue
<!-- 用户选择 -->
<UserSelect v-model="dataForm.userId" placeholder="选择用户" />

<!-- 部门选择 -->
<DepSelect v-model="dataForm.deptId" placeholder="选择部门" />

<!-- 树形选择 -->
<JNPFTreeSelect v-model="dataForm.treeValue" :options="treeOptions" />

上传组件

vue
<!-- 文件上传 -->
<uploadBtn v-model="dataForm.fileList" :fileSize="10" :limit="5" />

<!-- 图片上传 -->
<JNPFUploadImg v-model="dataForm.imageUrl" :limit="3" />

富功能组件

vue
<!-- 富文本编辑器 -->
<JPWCKEditor v-model="dataForm.content" :height="400" />

<!-- 电子签名 -->
<JPWSignature v-model="dataForm.signature" :width="400" :height="200" />

<!-- 地图组件 -->
<JPWMap v-model="dataForm.location" :zoom="13" />

🌲 树形和布局组件

树形组件

vue
<!-- 普通树 -->
<JPWTree :data="treeData" @node-click="handleNodeClick" />

<!-- 表格树 -->
<JPWTableTree :data="tableTreeData" :tree-props="{children: 'children'}" />

布局组件

vue
<!-- 卡片容器 -->
<JPWCard title="基本信息" :collapsible="true">
  <!-- 内容 -->
</JPWCard>

<!-- 标签页 -->
<JPWTabs v-model="activeTab">
  <el-tab-pane label="基本信息" name="basic">内容</el-tab-pane>
</JPWTabs>

🔄 流程组件

FlowBox 流程表单

javascript
// 在 openWindow 中使用
openWindow({
  url: "views/workFlow/components/FlowBox",
  data: { flowId: "流程ID", id: "数据ID", opType: "1" }
});

📦 容器组件

ComponentContainer 自定义组件容器

配合 CCMixin 使用,管理弹窗组件

vue
<template>
  <div>
    <!-- 触发按钮 -->
    <el-button @click="openCustomWindow">打开组件</el-button>
    
    <!-- ComponentContainer容器 -->
    <ComponentContainer
      v-if="ccVisible"
      :popupType="popupType"
      :popupTitle="popupTitle_"
      :popupWidth="popupWidth_"
      :popupHeight="popupHeight_"
      :showHeader="showHeader_"
      :showFooter="showFooter_"
      :componentUrl="componentUrl"
      :componentType="componentType"
      @cc_close="close"
      ref="ComponentContainer"
      v-loading.fullscreen.lock="layoutLoading"
    >
      <template #main>
        <component
          v-initComponent="{ data: componentData }"
          :is="componentName"
          :data="componentData"
          :config="componentData"
          :modelId="modelIdCC"
          :isPreview="isPreviewCC"
          ref="componentRef"
        ></component>
      </template>
    </ComponentContainer>
  </div>
</template>

<script>
import CCMixin from '@/mixins/basics/customComponents'

export default {
  mixins: [CCMixin],
  methods: {
    // 打开自定义组件窗口
    openCustomWindow() {
      this.openWindow({
        url: 'views/module/Form',           // 组件路径
        title: '编辑数据',                  // 窗口标题
        width: '80%',                      // 窗口宽度
        height: '90%',                     // 窗口高度
        popupType: 'general',              // 弹窗类型
        refresh: true,                     // 关闭后刷新
        data: {                           // 传递给组件的数据
          id: 'xxx',
          mode: 'edit'
        }
      })
    }
  }
}
</script>

核心属性

  • popupType: 弹窗类型 general(普通) | fullScreen(全屏) | drawer(抽屉)
  • componentUrl: 组件路径,相对于 src/ 目录
  • componentType: 组件类型,自动从URL推断或手动指定
  • v-initComponent: 自定义指令,用于组件初始化

openWindow 参数

javascript
this.openWindow({
  // 必需参数
  url: 'views/module/Form',              // 组件路径
  
  // 弹窗配置
  title: '窗口标题',                      // 弹窗标题
  width: '80%',                         // 弹窗宽度
  height: '90%',                        // 弹窗高度
  popupType: 'general',                 // general/fullScreen/drawer
  
  // 显示控制
  showHeader: true,                     // 显示头部
  showFooter: false,                    // 显示底部
  
  // 数据和行为
  refresh: false,                       // 关闭后刷新
  data: { id: 'xxx' },                 // 传递数据
  onDestroy: { 'event': callback }      // 销毁回调
})

⚡ 使用规范

📦 组件引用优先判断规则

⚠️ 强制要求:引用任何公共组件前必须执行以下检查流程

🔍 第一步:检查组件是否全局注册

必须先检查 src/components/index.js 确认组件是否已全局注册

javascript
// 🔍 检查方法1:查看 src/components/index.js 文件
// 同步加载组件(已全局注册,直接使用)
JNPFTable,           // ✅ 已注册,使用 <JNPF-table>
Pagination,          // ✅ 已注册,使用 <Pagination>
topOperation,        // ✅ 已注册,使用 <topOpts>
tableOperation,      // ✅ 已注册,使用 <tableOpts>

// 异步加载组件(已全局注册,直接使用)
UploadImg: () => import("@/components/JNPF-UploadImg"),  // ✅ 已注册
JNPFUploadFile: () => import("@/components/JNPF-uploadFile"), // ✅ 已注册
ExportBox: () => import("@/components/JNPF-ExportBox"), // ✅ 已注册

// 🔍 检查方法2:开发环境控制台验证
console.log('全局组件列表:', Object.keys(Vue.options.components))
console.log('组件是否存在:', 'JNPF-table' in Vue.options.components)

⚡ 第二步:全局组件直接使用(无需import)

javascript
// ✅ 已全局注册的组件 - 直接在模板中使用
<JNPF-table />           // 表格组件
<UploadImg />            // 图片上传(别名)
<JNPF-UploadImg />       // 图片上传(全名)
<uploadBtn />            // 文件上传
<Pagination />           // 分页组件
<topOpts />             // 顶部操作
<tableOpts />           // 表格操作
<ExportBox />           // 导出弹窗
<ComponentContainer />   // 组件容器
<JNPFTreeSelect />      // 树形选择

📍 第三步:检查未全局注册组件的正确路径

如果组件未全局注册,必须验证组件文件路径是否正确

javascript
// 🔍 强制检查:组件路径验证流程
// 1. 检查组件文件是否存在
// 2. 确认组件导出方式
// 3. 验证组件名称拼写

// ✅ 正确的路径检查示例
ls src/components/JNPF-userSelect/     // 检查目录是否存在
ls src/components/JNPF-userSelect/index.vue  // 检查文件是否存在

// ✅ 常用未全局注册组件的正确路径
import UserSelect from "@/components/JNPF-userSelect"        // ✅ 正确
import DepSelect from "@/components/JNPF-depSelect"          // ✅ 正确  
import JPWSignature from "@/components/JPW-Signature"        // ✅ 正确
import JNPFDialog from "@/components/JNPF-dialog"           // ✅ 正确

// ❌ 常见错误路径
import UserSelect from "@/components/UserSelect"            // ❌ 路径错误
import DepSelect from "@/components/JNPF-DepSelect"         // ❌ 大小写错误
import JPWSignature from "@/components/JPWSignature"        // ❌ 缺少连字符

🚫 第四步:避免重复引用

javascript
// ❌ 禁止:重复引用已全局注册的组件
import JNPFUploadImg from "@/components/JNPF-UploadImg"  // ❌ 已全局注册!
import Pagination from "@/components/Pagination"        // ❌ 已全局注册!
import JNPFTable from "@/components/JNPF-table"         // ❌ 已全局注册!

// ✅ 正确:直接使用全局组件
<JNPF-UploadImg />  // 直接使用
<UploadImg />       // 或使用别名
<Pagination />      // 直接使用
<JNPF-table />      // 直接使用

🔧 新建组件规范

📋 新建组件前置检查

创建新组件前必须执行以下检查

bash
# 🔍 检查1:确认组件不存在
find src/components -name "*ComponentName*" -type f
grep -r "ComponentName" src/components/

# 🔍 检查2:确认全局注册中没有同名组件
grep -r "ComponentName" src/components/index.js

# 🔍 检查3:检查是否已有类似功能组件
grep -r "similar-function" src/components/

创建公共组件时的全局注册要求

javascript
// 🔍 第一步:验证组件创建完成且路径正确
// ls src/components/JNPF-NewComponent/index.vue  # 确认文件存在
// 确认组件有正确的 export default

// 🔍 第二步:在 src/components/index.js 中注册
// 根据组件使用频率选择同步或异步加载

// 方式1:同步加载(核心组件,必须立即可用)
import JNPFNewComponent from './JNPF-NewComponent'

const syncComponents = {
  JNPFNewComponent,          // 同步注册
  // ... 其他同步组件
}

// 方式2:异步加载(按需加载,推荐)
const asyncComponents = {
  // ... 其他异步组件
  JNPFNewComponent: () => 
    import(/* webpackChunkName: "new-component" */ './JNPF-NewComponent'),
}

// 🔍 第三步:考虑别名注册(简化使用)
Vue.component('JNPF-NewComponent', JNPFNewComponent)  // 全名
Vue.component('NewComponent', JNPFNewComponent)       // 简化别名
// 注意:别名要避免与现有组件冲突

// 🔍 第四步:更新组件列表文档
// 在本文档中添加新组件的使用说明

📁 组件文件命名和目录规范

bash
# ✅ 正确的组件目录结构
src/components/
├── JNPF-ComponentName/           # 通用组件目录
   ├── index.vue                 # 主组件文件
   ├── components/               # 子组件目录(可选)
   └── README.md                 # 组件说明(可选)

├── JPW-ComponentName/            # 业务组件目录
   ├── index.vue                 # 主组件文件
   ├── components/               # 子组件目录(可选)
   └── README.md                 # 组件说明(可选)

└── Generator/                    # 生成器组件目录
    └── components/
        └── ComponentName/
            └── index.vue

# 📝 命名规则验证
echo "JNPF-userSelect" | grep -E "^JNPF-[a-z][a-zA-Z]*$"  # ✅ 通用组件
echo "JPW-Signature" | grep -E "^JPW-[A-Z][a-zA-Z]*$"     # ✅ 业务组件

# ❌ 错误的命名示例
# JNPF_userSelect   - 使用下划线
# jnpf-userSelect   - 首字母小写
# JPWSignature      - 缺少连字符
# User-Select       - 不符合前缀规范

强制要求

  • 列表页面:必须用 JNPF-table 不能用 el-table
  • 数据选择:必须用对应选择器组件
  • 文件上传:必须用 uploadBtnJNPF-UploadImg(已全局注册)
  • 自定义弹窗:必须用 ComponentContainer + CCMixin

样式定制

scss
// 正确方式:深度选择器
.my-component {
  ::v-deep .jnpf-table {
    .el-table__header { background: #f5f7fa; }
  }
}

🎯 组件使用最佳实践

🔍 强制组件检查流程

每次引用组件前必须执行以下检查

javascript
// 📋 检查清单1:全局注册验证
console.log('全局组件:', Object.keys(Vue.options.components))
console.log('JNPF-table存在:', 'JNPF-table' in Vue.options.components)

// 📋 检查清单2:组件文件存在性验证(未全局注册时)
// 在终端运行以下命令验证路径
// ls src/components/JNPF-userSelect/index.vue
// ls src/components/JPW-Signature/index.vue

// 📋 检查清单3:组件导出验证
// 查看组件文件最后的 export default
const componentPath = '@/components/JNPF-userSelect'
console.log('组件路径检查:', componentPath)

// 📋 检查清单4:避免路径拼写错误
// ✅ 正确命名模式
// JNPF-*     : 通用组件,如 JNPF-userSelect
// JPW-*      : 业务组件,如 JPW-Signature  
// Generator/ : 生成器组件目录

⚠️ 组件引用错误预防

javascript
// 🛡️ 防错措施1:使用IDE的路径提示
// 输入 import 时依赖IDE自动补全,避免手写路径

// 🛡️ 防错措施2:统一的组件检查函数
function checkComponent(componentName, componentPath) {
  // 检查是否全局注册
  if (componentName in Vue.options.components) {
    console.warn(`⚠️ ${componentName} 已全局注册,无需import`)
    return false
  }
  
  // 检查路径格式
  if (!componentPath.startsWith('@/components/')) {
    console.error(`❌ ${componentPath} 路径格式错误`)
    return false
  }
  
  return true
}

// 使用示例
if (checkComponent('JNPF-table', '@/components/JNPF-table')) {
  import JNPFTable from '@/components/JNPF-table'
}

📖 标准组件引用示例

严格按照检查流程执行的正确示例

vue
<script>
// 🔍 第一步:已检查 src/components/index.js 确认以下组件状态
// ✅ JNPF-table    - 已全局注册(同步)
// ✅ UploadImg     - 已全局注册(异步,别名)
// ✅ Pagination    - 已全局注册(同步)
// ❌ UserSelect    - 未全局注册,需要import
// ❌ DepSelect     - 未全局注册,需要import
// ❌ JPWSignature  - 未全局注册,需要import

// 🔍 第二步:验证组件路径正确性
// ls src/components/JNPF-userSelect/index.vue  ✅ 存在
// ls src/components/JNPF-depSelect/index.vue   ✅ 存在  
// ls src/components/JPW-Signature/index.vue    ✅ 存在

// 🔍 第三步:只引用未全局注册且路径正确的组件
import UserSelect from "@/components/JNPF-userSelect"  // ✅ 路径正确
import DepSelect from "@/components/JNPF-depSelect"    // ✅ 路径正确
import JPWSignature from "@/components/JPW-Signature"  // ✅ 路径正确

// ❌ 以下组件禁止引用 - 已全局注册
// import JNPFTable from "@/components/JNPF-table"     // ❌ 已全局注册
// import UploadImg from "@/components/JNPF-UploadImg"  // ❌ 已全局注册
// import Pagination from "@/components/Pagination"     // ❌ 已全局注册

export default {
  components: {
    // 🔍 只注册未全局注册的组件
    UserSelect,      // ✅ 需要注册
    DepSelect,       // ✅ 需要注册
    JPWSignature     // ✅ 需要注册
    // ❌ 以下组件禁止在此注册 - 已全局注册
    // JNPFTable,    // ❌ 已全局注册
    // UploadImg,    // ❌ 已全局注册
    // Pagination    // ❌ 已全局注册
  }
}
</script>

<template>
  <!-- 🔍 直接使用已全局注册的组件 -->
  <JNPF-table :data="list" />          <!-- ✅ 全局组件 -->
  <UploadImg v-model="form.image" />   <!-- ✅ 全局组件(别名)-->
  <JNPF-UploadImg v-model="form.pic" /> <!-- ✅ 全局组件(全名)-->
  <Pagination :total="total" />        <!-- ✅ 全局组件 -->
  <topOpts @add="handleAdd" />         <!-- ✅ 全局组件 -->
  <ExportBox ref="exportBox" />        <!-- ✅ 全局组件 -->
  
  <!-- 🔍 使用局部引用的组件 -->
  <UserSelect v-model="form.userId" />    <!-- ✅ 局部组件 -->
  <DepSelect v-model="form.deptId" />     <!-- ✅ 局部组件 -->
  <JPWSignature v-model="form.sign" />   <!-- ✅ 局部组件 -->
</template>

🚨 常见违规示例

vue
<script>
// ❌ 违规1:重复引用全局组件
import JNPFTable from "@/components/JNPF-table"      // ❌ 已全局注册!
import UploadImg from "@/components/JNPF-UploadImg"   // ❌ 已全局注册!

// ❌ 违规2:组件路径错误
import UserSelect from "@/components/UserSelect"      // ❌ 路径不存在
import DepSelect from "@/components/JNPF-DepSelect"   // ❌ 大小写错误

// ❌ 违规3:未检查组件是否存在就引用
import MyComponent from "@/components/MyComponent"    // ❌ 未验证文件存在

export default {
  components: {
    JNPFTable,    // ❌ 重复注册全局组件
    UploadImg,    // ❌ 重复注册全局组件
    UserSelect,   // ❌ 路径错误导致组件无效
    MyComponent   // ❌ 组件不存在
  }
}
</script>

数据绑定

javascript
// v-model 双向绑定
<JPWInput v-model="formData.name" />

// 复杂对象绑定
<JPWSelect :value="formData.type" @input="value => $set(formData, 'type', value)" />

ComponentContainer 使用规范

javascript
// ✅ 正确:使用 CCMixin 管理
export default {
  mixins: [CCMixin],
  methods: {
    openDialog() {
      this.openWindow({ url: 'views/module/Form' })
    }
  }
}

// ❌ 错误:手动管理弹窗状态
export default {
  data() {
    return { visible: false }
  }
}

🔧 组件开发规范

命名规范

  • 业务组件:JPW 开头
  • 通用组件:JNPF 开头

属性定义

javascript
props: {
  value: { type: [String, Array], default: '' },
  placeholder: { type: String, default: '请输入' },
  disabled: { type: Boolean, default: false }
}

组件库核心要点:强制使用规范 + 常用组件 + 基本配置