@aftership/approval-widget-kit
v1.0.3
Published
Reusable approval widgets component library for AfterShip platforms
Downloads
126
Readme
@aftership/approval-widget-kit
🎨 Reusable approval widgets component library for AfterShip platforms
📦 安装
# npm
npm install @aftership/approval-widget-kit
# yarn
yarn add @aftership/approval-widget-kit
# pnpm
pnpm add @aftership/approval-widget-kit✨ 特性
- ✅ 零配置:无需手动配置认证和环境,开箱即用
- 🎨 基于 Ant Design:与 Ant Design 完美集成
- 📦 Tree-shakable:支持按需加载,减小打包体积
- 🔒 TypeScript:完整的类型定义支持
- 🌍 多环境支持:自动识别 production/staging/development
- 🔐 自动认证:无缝集成 AfterShip 认证系统
- 🔥 热更新友好:支持开发环境热更新
🚀 零配置使用
本组件库采用零配置设计,自动处理:
- 认证:通过
@aftership/automizely-product-auth自动获取 token - 环境:通过
process.env.APP_ENV自动识别环境 - API 请求:内置统一请求工具,自动添加认证头
前置条件
使用本组件库前,你的应用需要:
- ✅ 包裹
AuthProviderEmployee(来自@aftership/automizely-product-auth) - ✅ 包裹
QueryClientProvider(来自react-query) - ✅ 设置环境变量
process.env.APP_ENV(可选,默认 production)
快速开始
import React from 'react';
import ReactDOM from 'react-dom';
import { AuthProviderEmployee } from '@aftership/automizely-product-auth/internal';
import { QueryClient, QueryClientProvider } from 'react-query';
import { ApprovalDetail } from '@aftership/approval-widget-kit';
import '@aftership/approval-widget-kit/dist/index.css';
// 创建 QueryClient 实例
const queryClient = new QueryClient();
function App() {
return (
<AuthProviderEmployee
config={{
forceLogin: true,
clientId: 'your-client-id'
}}
>
<QueryClientProvider client={queryClient}>
{/* 使用审批详情组件 */}
<ApprovalDetail approvalId="12345" />
</QueryClientProvider>
</AuthProviderEmployee>
);
}
ReactDOM.render(<App />, document.getElementById('root'));📚 组件说明
ApprovalDetail
审批详情组件,展示审批流程的完整信息,包括审批数据、流程图、评论和操作按钮。
Props
interface TApprovalDetailProps {
// 必填
approvalId: string; // 审批单 ID
// 可选 - 显示控制
isShowData?: boolean; // 是否显示审批数据,默认 true
isShowLink?: boolean; // 是否显示流程图,默认 true
isShowComment?: boolean; // 是否显示评论区,默认 true
isShowOperation?: boolean; // 是否显示操作按钮,默认 true
// 可选 - 事件回调
onApprovalChange?: (approval: TApproval) => void; // 审批状态变化回调
}基础用法
import { ApprovalDetail } from '@aftership/approval-widget-kit';
import '@aftership/approval-widget-kit/dist/index.css';
function MyApprovalPage() {
return <ApprovalDetail approvalId="12345" />;
}自定义显示模块
import { ApprovalDetail } from '@aftership/approval-widget-kit';
function CustomApprovalView() {
return (
<ApprovalDetail
approvalId="12345"
isShowData={true} // 显示审批数据
isShowLink={true} // 显示流程图
isShowComment={true} // 显示评论区
isShowOperation={false} // 隐藏操作按钮(只读模式)
/>
);
}监听审批状态变化
import { ApprovalDetail } from '@aftership/approval-widget-kit';
import type { TApproval, EApprovalState } from '@aftership/approval-widget-kit';
function ApprovalWithCallback() {
const handleApprovalChange = (approval: TApproval) => {
console.log('审批状态已更新:', approval.status);
// 根据状态执行不同操作
if (approval.status === EApprovalState.APPROVED) {
console.log('审批已通过!');
// 执行通过后的逻辑
} else if (approval.status === EApprovalState.REJECTED) {
console.log('审批已拒绝!');
// 执行拒绝后的逻辑
}
};
return (
<ApprovalDetail
approvalId="12345"
onApprovalChange={handleApprovalChange}
/>
);
}打印模式(隐藏操作)
import { ApprovalDetail } from '@aftership/approval-widget-kit';
function PrintableApproval() {
const handlePrint = () => {
window.print();
};
return (
<div>
<button onClick={handlePrint}>打印</button>
{/* 打印时不显示操作按钮 */}
<ApprovalDetail
approvalId="12345"
isShowOperation={false}
/>
</div>
);
}其他工具组件
UserSelect - 用户选择器
import { UserSelect } from '@aftership/approval-widget-kit';
function MyForm() {
return (
<UserSelect
placeholder="Please select users"
mode="multiple"
filterUser={['user1', 'user2']} // 过滤掉特定用户
/>
);
}UserTag - 用户标签
import { UserTag } from '@aftership/approval-widget-kit';
function UserDisplay() {
return <UserTag email="[email protected]" />;
}CopyButton - 复制按钮
import { CopyButton } from '@aftership/approval-widget-kit';
function CopyDemo() {
return <CopyButton text="要复制的文本内容" />;
}RichEditor - 富文本编辑器
import { RichEditor } from '@aftership/approval-widget-kit';
import { useRef } from 'react';
function EditorDemo() {
const editorRef = useRef(null);
return (
<RichEditor
editorRef={editorRef}
placeholder="请输入内容..."
/>
);
}🔧 工具函数
请求工具
组件库内置统一请求工具,自动处理认证头和环境配置。
import { request, get, post, put, del } from '@aftership/approval-widget-kit';
import type { IResponse } from '@aftership/approval-widget-kit';
// GET 请求
const fetchUser = async () => {
const data = await get<IResponse<UserData>>('/api/users/123');
return data;
};
// POST 请求
const createApproval = async () => {
const result = await post<IResponse>('/api/approvals', {
title: 'New Approval',
description: 'Approval description'
});
return result;
};
// PUT 请求
const updateApproval = async () => {
const result = await put<IResponse>('/api/approvals/123', {
status: 'approved'
});
return result;
};
// DELETE 请求
const deleteApproval = async () => {
await del('/api/approvals/123');
};
// 自定义请求
const customRequest = async () => {
const response = await request('/api/custom', {
method: 'POST',
headers: { 'X-Custom-Header': 'value' },
payload: { data: 'value' }
});
return response;
};工具函数
import {
camelCaseToShow, // 驼峰转展示文本
onError, // 统一错误处理
} from '@aftership/approval-widget-kit';
// 驼峰转展示文本
const displayText = camelCaseToShow('approvalStatus'); // "Approval Status"
// 统一错误处理
try {
await someApiCall();
} catch (error) {
onError(error); // 自动显示友好错误提示
}🎯 类型定义
核心类型
import type {
// 审批相关
TApproval, // 审批单数据
TApprovalNode, // 审批节点
ApprovalComment, // 审批评论
TAttachments, // 附件
ApprovalError, // 错误类型
// 枚举
EApprovalState, // 审批状态
EApprovalStatusOperation, // 审批操作
ESignType, // 签名类型
ERequireApproverField, // 审批人必填字段
// 请求相关
IResponse, // 响应类型
TMethod, // 请求方法
} from '@aftership/approval-widget-kit';枚举说明
EApprovalState - 审批状态
enum EApprovalState {
PENDING = 'pending', // 待审批
APPROVED = 'approved', // 已通过
REJECTED = 'rejected', // 已拒绝
CANCELLED = 'cancelled', // 已取消
EXPIRED = 'expired', // 已过期
}EApprovalStatusOperation - 审批操作
enum EApprovalStatusOperation {
APPROVE = 'approve', // 通过
REJECT = 'reject', // 拒绝
REASSIGN = 'reassign', // 转交
ADD = 'add', // 加签
CANCEL = 'cancel', // 取消
}类型示例
import type { TApproval, EApprovalState } from '@aftership/approval-widget-kit';
// 审批单数据结构
const approval: TApproval = {
id: '12345',
title: '采购申请',
status: EApprovalState.PENDING,
createTime: '2024-01-01T00:00:00Z',
creator: {
id: 'user1',
name: 'John Doe',
email: '[email protected]'
},
// ... 更多字段
};🏗️ 开发
本地开发
# 安装依赖
pnpm install
# 开发模式(监听文件变化自动重新构建)
pnpm dev
# 构建
pnpm build
# 类型检查
pnpm typecheck在 Monorepo 中使用
如果你的项目也是 monorepo,可以使用 workspace 协议:
{
"dependencies": {
"@aftership/approval-widget-kit": "workspace:*"
}
}📝 注意事项
必需的依赖
确保你的项目已安装以下 peer dependencies:
{
"peerDependencies": {
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0",
"antd": "^5.0.0",
"react-query": "^3.0.0",
"@aftership/automizely-product-auth": "^1.23.0"
}
}前置条件检查清单
使用组件库前,确保:
- ✅ 应用已包裹
AuthProviderEmployee - ✅ 应用已包裹
QueryClientProvider - ✅ 已导入样式
@aftership/approval-widget-kit/dist/index.css - ✅ 设置了
process.env.APP_ENV环境变量(可选)
样式导入
重要:必须导入组件库的样式文件
// 在入口文件或组件中导入
import '@aftership/approval-widget-kit/dist/index.css';环境变量
组件库会读取以下环境变量(可选):
# 应用环境(默认: production)
APP_ENV=development # development | staging | production🐛 故障排查
1. 样式丢失
现象: 组件显示不正常,缺少样式
原因: 未导入 CSS 文件
解决方案:
import '@aftership/approval-widget-kit/dist/index.css';2. 认证失败
现象: 请求返回 401 错误
原因: 未包裹 AuthProviderEmployee 或配置错误
解决方案:
<AuthProviderEmployee
config={{
forceLogin: true,
clientId: 'your-client-id'
}}
>
{/* 你的应用 */}
</AuthProviderEmployee>3. React Query 错误
现象: 组件报错 "No QueryClient set"
原因: 未包裹 QueryClientProvider
解决方案:
import { QueryClient, QueryClientProvider } from 'react-query';
const queryClient = new QueryClient();
<QueryClientProvider client={queryClient}>
{/* 你的应用 */}
</QueryClientProvider>4. TypeScript 类型错误
现象: 导入类型时报错
原因: 可能是组件库版本问题或构建产物缺失
解决方案:
# 清理并重新安装
rm -rf node_modules
pnpm install5. 打包体积过大
优化方案:
- 按需导入组件:
// ✅ 推荐:按需导入
import { ApprovalDetail } from '@aftership/approval-widget-kit';
// ❌ 避免:全量导入
import * as ApprovalKit from '@aftership/approval-widget-kit';- 使用 Tree-shaking(确保你的打包工具支持)
📖 完整示例
示例 1: 基础审批详情页
import React from 'react';
import { ApprovalDetail } from '@aftership/approval-widget-kit';
import '@aftership/approval-widget-kit/dist/index.css';
import { PageHeader, Button } from 'antd';
import { useNavigate, useSearchParams } from 'react-router-dom';
function ApprovalDetailPage() {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const approvalId = searchParams.get('approvalId') || '';
const handleBack = () => {
navigate('/approvals');
};
return (
<PageHeader
title="Approval Detail"
onBack={handleBack}
extra={[
<Button key="print" onClick={() => window.print()}>
Print
</Button>
]}
>
<ApprovalDetail approvalId={approvalId} />
</PageHeader>
);
}
export default ApprovalDetailPage;示例 2: 打印视图
import React, { useRef } from 'react';
import { ApprovalDetail } from '@aftership/approval-widget-kit';
import { Button } from 'antd';
function PrintableApprovalPage({ approvalId }: { approvalId: string }) {
const printRef = useRef<HTMLDivElement>(null);
const handlePrint = () => {
// 隐藏其他内容,只显示审批详情
const printContent = printRef.current;
if (printContent) {
const printWindow = window.open('', '', 'width=800,height=600');
printWindow?.document.write(printContent.innerHTML);
printWindow?.document.close();
printWindow?.print();
}
};
return (
<div>
<Button onClick={handlePrint}>打印审批单</Button>
<div ref={printRef}>
<ApprovalDetail
approvalId={approvalId}
isShowOperation={false} // 打印时隐藏操作按钮
/>
</div>
</div>
);
}示例 3: 审批状态监控
import React, { useState } from 'react';
import { ApprovalDetail } from '@aftership/approval-widget-kit';
import type { TApproval, EApprovalState } from '@aftership/approval-widget-kit';
import { message, Badge } from 'antd';
function ApprovalMonitor({ approvalId }: { approvalId: string }) {
const [status, setStatus] = useState<EApprovalState>();
const handleApprovalChange = (approval: TApproval) => {
setStatus(approval.status);
// 根据状态显示不同提示
switch (approval.status) {
case EApprovalState.APPROVED:
message.success('审批已通过!');
break;
case EApprovalState.REJECTED:
message.error('审批已拒绝!');
break;
case EApprovalState.CANCELLED:
message.warning('审批已取消!');
break;
}
};
return (
<div>
<div style={{ marginBottom: 16 }}>
当前状态: <Badge status="processing" text={status} />
</div>
<ApprovalDetail
approvalId={approvalId}
onApprovalChange={handleApprovalChange}
/>
</div>
);
}🤝 贡献
欢迎提交 Issue 和 Pull Request!
开发流程
- Fork 本仓库
- 创建功能分支 (
git checkout -b feature/AmazingFeature) - 提交更改 (
git commit -m 'feat: Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 提交 Pull Request
📄 License
MIT © AfterShip Team
🔗 相关链接
📮 联系我们
如有问题或建议,欢迎通过以下方式联系:
- 提交 GitHub Issue
- 联系 AfterShip 团队
