cd-share

分享组件 - 支持人员选择、权限设置、链接分享、多渠道分享
2,466
Install
npm install cd-share
Latest Version:1.1.13
Vue:3
License:MIT
Last Updated:Mar 30, 2026
Links: npm
Maintainer: zuoxiaoyao

cd-share

分享组件 - 支持人员选择、权限设置、链接分享、多渠道分享、协作者管理

✨ 特性

  • 🎯 完整的分享功能 - 支持人员选择、链接分享、权限设置
  • 👥 集成人员选择器 - 基于 cd-personselector,支持树形结构、搜索
  • 🔐 三级权限控制 - 可阅读/可编辑/可管理,细粒度权限管理
  • 👨‍💼 协作者管理 - 查看、添加、移除协作者,修改协作者权限
  • 🔗 链接分享 - 支持组织范围控制、权限级别设置
  • 🔒 加密连接 - 支持密码保护,组织外用户需密码访问
  • 📱 多渠道分享 - 二维码、邮件、加密链接等
  • ⚙️ 权限设置 - 管理员可配置分享、协作者管理、内容操作等权限
  • 🎨 基于 TDesign - 遵循 TDesign 设计规范

📦 安装

npm install cd-share
# 或
pnpm add cd-share
# 或
yarn add cd-share

🚀 三种使用方法

方法一:基础使用 - 只读权限场景

适用于普通用户查看分享信息,可申请更高权限。

<template>
  <div>
    <t-button @click="visible = true">查看分享</t-button>

    <ShareDialog
      v-model:visible="visible"
      title="文档分享"
      :shareUrl="shareUrl"
      currentPermission="read"
      :owner="owner"
      :collaborators="collaborators"
      :organizations="organizations"
      @request-permission="handleRequestPermission"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { ShareDialog } from 'cd-share'
import 'cd-share/style.css'

const visible = ref(false)
const shareUrl = ref('https://example.com/doc/123')

const owner = ref({
  id: 'owner-1',
  name: '张三',
  avatar: 'https://example.com/avatar/zhangsan.jpg'
})

const collaborators = ref([
  { id: 'c-1', name: '李四', avatar: '', permission: 'edit' },
  { id: 'c-2', name: '王五', avatar: '', permission: 'read' }
])

const organizations = ref([
  { id: 1, name: '总公司' },
  { id: 2, name: '研发中心' },
  { id: 'internet', name: '互联网获得链接的人' }
])

const handleRequestPermission = (permission) => {
  console.log('申请权限:', permission)
  // 发送权限申请到后端
}
</script>

方法二:编辑权限场景

适用于可以添加协作者、修改部分权限的用户。

<template>
  <div>
    <t-button theme="primary" @click="visible = true">分享文档</t-button>

    <ShareDialog
      v-model:visible="visible"
      title="文档分享"
      :shareUrl="shareUrl"
      currentPermission="edit"
      :owner="owner"
      :collaborators="collaborators"
      :tabs="tabs"
      :organizations="organizations"
      @confirm="handleShareConfirm"
      @search="handleSearch"
      @load-users="handleLoadUsers"
      @collaborator-permission-change="handleCollaboratorPermissionChange"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { ShareDialog } from 'cd-share'
import { MessagePlugin } from 'tdesign-vue-next'
import 'cd-share/style.css'

const visible = ref(false)
const shareUrl = ref('https://example.com/doc/123')

const owner = ref({
  id: 'owner-1',
  name: '张三',
  avatar: ''
})

const collaborators = ref([
  { id: 'c-1', name: '李四', avatar: '', permission: 'edit' },
  { id: 'c-2', name: '王五', avatar: '', permission: 'read' },
  { id: 'c-3', name: '赵六', avatar: '', permission: 'manage' }
])

const tabs = ref([
  {
    key: 'department',
    name: '按部门',
    icon: 'folder',
    tree: [
      { id: 'dept-1', name: '研发部', userCount: 15 },
      { id: 'dept-2', name: '产品部', userCount: 8 }
    ]
  }
])

const organizations = ref([
  { id: 1, name: '总公司' },
  { id: 2, name: '研发中心' },
  { id: 'internet', name: '互联网获得链接的人' }
])

const handleShareConfirm = (payload) => {
  console.log('分享结果:', payload)
  MessagePlugin.success(`已分享给 ${payload.sharerIds.length} 位用户`)
  // 提交到后端
}

const handleSearch = ({ keyword, callback }) => {
  // 调用后端搜索接口
  const users = [
    { id: 'u-1', name: '用户A', department: '研发部' }
  ]
  callback(users)
}

const handleLoadUsers = ({ tabKey, nodeId, callback }) => {
  // 加载节点下的用户
  callback([])
}

const handleCollaboratorPermissionChange = ({ id, permission }) => {
  const collaborator = collaborators.value.find(c => c.id === id)
  if (collaborator) {
    collaborator.permission = permission
    MessagePlugin.success('权限已更新')
  }
}
</script>

方法三:管理权限场景(完整功能)

适用于管理员,拥有所有权限,可以管理协作者、设置权限策略。

<template>
  <div>
    <t-button theme="primary" @click="visible = true">管理分享</t-button>

    <ShareDialog
      v-model:visible="visible"
      title="报表分享管理"
      :shareUrl="shareUrl"
      helpUrl="https://help.example.com/share"
      currentPermission="manage"
      :owner="owner"
      :collaborators="collaborators"
      :tabs="tabs"
      :organizations="organizations"
      :defaultPermissionSettings="permissionSettings"
      @confirm="handleShareConfirm"
      @search="handleSearch"
      @load-users="handleLoadUsers"
      @permission-settings-change="handlePermissionSettingsChange"
      @manage-collaborators="handleManageCollaborators"
      @remove-collaborator="handleRemoveCollaborator"
      @collaborator-permission-change="handleCollaboratorPermissionChange"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { ShareDialog } from 'cd-share'
import { MessagePlugin } from 'tdesign-vue-next'
import 'cd-share/style.css'

const visible = ref(false)
const shareUrl = ref('https://example.com/report/123')

const owner = ref({
  id: 'owner-1',
  name: '张三',
  displayName: '张三(产品经理)',
  avatar: 'https://example.com/avatar.jpg'
})

const collaborators = ref([
  { id: 'c-1', name: '李四', displayName: '李四', avatar: '', permission: 'edit' },
  { id: 'c-2', name: '王五', displayName: '王五', avatar: '', permission: 'read' },
  { id: 'c-3', name: '赵六', displayName: '赵六', avatar: '', permission: 'manage' }
])

const tabs = ref([
  {
    key: 'department',
    name: '按部门',
    icon: 'folder',
    tree: [
      { id: 'dept-1', name: '研发部', userCount: 15 },
      { id: 'dept-2', name: '产品部', userCount: 8 }
    ]
  }
])

const organizations = ref([
  { id: 1, name: '总公司' },
  { id: 2, name: '研发中心' },
  { id: 'internet', name: '互联网获得链接的人' }
])

const permissionSettings = ref({
  allowExternalShare: true,
  allowViewCollaborators: true,
  allowAddCollaborators: true
})

const handleShareConfirm = (payload) => {
  console.log('分享数据:', payload)
  // payload 包含:sharerIds, orgId, permission, sendNotification, password, remark
  MessagePlugin.success(`已分享给 ${payload.sharerIds.length} 位用户`)
}

const handleSearch = ({ keyword, callback }) => {
  // 搜索用户
  setTimeout(() => {
    const users = [
      { id: 'u-1', name: '张三', department: '研发部', position: '前端工程师' },
      { id: 'u-2', name: '李四', department: '产品部', position: '产品经理' }
    ]
    callback(users.filter(u => u.name.includes(keyword)))
  }, 300)
}

const handleLoadUsers = ({ tabKey, nodeId, callback }) => {
  // 加载树节点下的用户
  setTimeout(() => {
    callback([
      { id: 'u-3', name: '王五', department: '研发部' }
    ])
  }, 300)
}

const handlePermissionSettingsChange = (settings) => {
  console.log('权限设置变更:', settings)
  MessagePlugin.success('权限设置已保存')
  // 提交到后端
}

const handleManageCollaborators = (persons) => {
  console.log('添加协作者:', persons)
  MessagePlugin.info('添加协作者')
}

const handleRemoveCollaborator = (id) => {
  collaborators.value = collaborators.value.filter(c => c.id !== id)
  MessagePlugin.success('已移除协作者')
}

const handleCollaboratorPermissionChange = ({ id, permission }) => {
  const collaborator = collaborators.value.find(c => c.id === id)
  if (collaborator) {
    collaborator.permission = permission
    MessagePlugin.success(`已修改权限为: ${permission}`)
  }
}
</script>

📚 API 文档

Props

属性 类型 默认值 说明
visible Boolean false 对话框显示状态(支持 v-model)
title String '分享' 对话框标题
shareUrl String '' 分享链接 URL
helpUrl String '' 帮助文档链接
width String '500px' 对话框宽度
currentPermission 'read' | 'edit' | 'manage' 'edit' 当前用户对资源的权限
owner User - 资源所有者信息
collaborators Collaborator[] [] 协作者列表(包含权限)
tabs Array [] 人员选择器的 Tab 配置
organizations Organization[] [] 组织列表(含"互联网获得链接的人")
defaultPermissionSettings PermissionSettings - 默认权限设置

Events

事件名 参数 说明
update:visible (visible: boolean) 对话框显示状态变化
confirm (payload: SharePayload) 确认分享
search ({ keyword, callback }) 搜索用户
load-users ({ tabKey, nodeId, callback }) 加载树节点用户
request-permission (permission: Permission) 申请权限(只读用户)
permission-settings-change (settings: PermissionSettings) 权限设置变更
manage-collaborators (persons?: any[]) 管理协作者(添加)
remove-collaborator (id: string | number) 移除协作者
collaborator-permission-change ({ id, permission }) 协作者权限变更

类型定义

// 用户类型
interface User {
  id: string | number
  name?: string
  displayName?: string
  avatar?: string
}

// 协作者类型
interface Collaborator extends User {
  permission: 'read' | 'edit' | 'manage'
}

// 组织类型
interface Organization {
  id: number | string
  name: string
  displayName?: string
}

// 分享数据类型
interface SharePayload {
  sharerIds: string[]              // 格式:user:id, depot:id, group:id, post:id
  orgId: string | number            // 组织ID
  permission: 'read' | 'edit' | 'manage'  // 权限级别
  sendNotification: boolean         // 是否发送通知
  password?: string                 // 密码(如果设置)
  remark: string                    // 备注信息
}

// 权限设置类型
interface PermissionSettings {
  allowExternalShare?: boolean      // 允许分享到组织外
  allowViewCollaborators?: boolean  // 允许查看协作者
  allowAddCollaborators?: boolean   // 允许添加协作者
  allowCopy?: boolean              // 允许复制
  allowDownload?: boolean          // 允许下载/打印
  allowComment?: boolean           // 允许评论
  showVisitorAvatars?: boolean     // 显示访问者头像
}

🔐 权限说明

三级权限控制

权限级别 功能说明
只读 (read) • 只能查看协作者列表和分享信息
• 不能添加协作者
• 不能修改任何权限
• 可以复制链接、查看二维码
• 可以申请编辑权限
编辑 (edit) • 可以添加协作者
• 可以修改"可阅读"和"可编辑"权限的协作者
• 不能修改"可管理"权限的协作者
• 不能删除协作者
• 可以设置加密连接
管理 (manage) • 拥有所有权限
• 可以设置任何级别的权限
• 可以删除协作者
• 可以配置权限策略
• 完全控制权

权限设计原则

  • ✅ 最小权限原则 - 用户只拥有完成任务所需的最小权限
  • ✅ 分级管理 - 编辑用户不能越权设置管理员
  • ✅ UI + 函数双层防护 - 即使绕过 UI 禁用,函数层仍会验证
  • ✅ 清晰的视觉反馈 - 所有权限限制都有明确提示

🎨 样式定制

组件基于 TDesign,支持通过 CSS 变量自定义样式:

/* 自定义对话框样式 */
.cd-share-dialog {
  /* 你的自定义样式 */
}

🔧 依赖

  • vue ^3.0.0
  • tdesign-vue-next ^1.0.0
  • cd-personselector ^1.2.3
  • cd-usercard ^2.3.1

📄 License

MIT

🤝 贡献

欢迎提交 Issue 和 Pull Request!

Related Packages

cd-personselector

人员选择器组件 - 支持多Tab、树形结构、搜索、懒加载、输入框选择模式

5,431
tdesign-vue

tdesign-vue

747,696 1,032
tdesign-mobile-vue

tdesign-mobile-vue

1,024,396 437
@tdesign/uniapp

TDesign Component for Uniapp

67,985 1,780
@tdesign/uniapp-chat

TDesign Chat Component for Uniapp

28,706 1,781

Version History

Version Released Vue License
1.1.13 ^3.0.0 MIT
1.1.12 ^3.0.0 MIT
1.1.11 ^3.0.0 MIT
1.1.10 ^3.0.0 MIT
1.1.9 ^3.0.0 MIT