Appearance
业务组件
在现阶段还很难对业务组件进行更深一层面的分类,先以平铺的方式展开叙述
ListPanelView
列表展示面板组件,常见于页面内容左侧的标签列表、分类列表、群组列表等。
自带搜索框,也支持以插槽的形式插入自定义的搜索

html
<ListPanelView v-model:value="searchInput" placeholder="搜索标签" class="w-[17.5rem] flex-shrink-0" @search="onSearch">
<List ref="listRef"></List>
</ListPanelView>API
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| title | 顶部标题 | string | 全部用户 |
| headBg | 顶部背景图 | string | [设计稿背景图oss链接] |
搜索参数和事件同InputSearch
标签 Tag
颜色标签 ColorTag
javascript
import ColorTag from "@/views/components/tags/ColorTag.vue";html
<ColorTag allow-remove size="large" color="info" @remove="handleRemoveTag">颜色标签</ColorTag>参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| color | 标签颜色,可对照参考设计稿颜色变量标注或theme.ts里的颜色标识 | brand purple cyan danger warning success info lime magenta pinkPurple azure fill | brand |
| mode | 深色/浅色标签 | light dark | light |
| size | 组件大小 | small default large | default |
| allowRemove | 移除标签 | boolean | false |
事件
| 事件名称 | 说明 |
|---|---|
| remove | 移除事件 |
头像标签 AvatarTag
头像标签组件,用于显示文字、图片头像和对应文本。
javascript
import AvatarTag from "@/views/components/tags/AvatarTag.vue";html
<AvatarTag size="small" title="市场易"></AvatarTag>参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| type | 头像类型 | default text image | default |
| size | 组件大小 | default small middle large | default |
| title | 头像右侧的文本 | string | |
| src | type为image时的图片链接 | string | |
| allowRemove | 移除标签 | boolean | false |
事件
| 事件名称 | 说明 |
|---|---|
| remove | 移除事件 |
![]()
系统标签 SystemTag
系统标签在使用时,建议只保存tagid,非必要不要将包含标签名称的tag结构保存。所以以下公用组件的两种类型的返回值均只包含了标签的id信息。需要在页面展示标签时,调用公用的SystemTagItem组件即可。
另外由于目前的系统标签选择逻辑限制,跟后端对接时务必要求后端提供标签的全量更新接口
何时使用
- 当前标签的展示和编辑

javascript
import TagListEditor from "@/views/components/systemTag/semiControl/TagListEditor.vue"html
<tag-list-editor v-model:tags="detail.tags" @ok="updateLeadTag" @remove="removeLeadTag"></tag-list-editor>typescript
type TypeItem = { id: string, [key: string]: any } | string参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| tags(v-model) | 选中的标签。 | TypeItem[] | [] |
| itemMode | 希望的返回值的结构 | detail:[{id:string}] ids:[id,id,id] | ids |
| editable | 是否可进行添加标签和移除标签的操作 | boolean | true |
事件
| 事件名称 | 说明 | 回调参数 |
|---|---|---|
| ok | 选中标签变化时的回调,包括移除标签和选择标签模态框点击“确定”后 | TypeItem[] |
| remove | 移除标签时的回调 | tagId |
- 选择系统标签
typescript
import Add from "@/views/components/systemTag/semiControl/Add.vue"
const addRef = ref<InstanceType<typeof Add>>()
addRef.value?.open({
tags: props.tags,
itemMode: 'ids'
})html
<Add ref="addRef" @complete="handleSelect"></Add>参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| tags | 选中的标签 | TypeItem[] | [] |
| itemMode | 希望的返回值的类型 | detail``ids | ids |
- 系统标签的展示
typescript
import SystemTagItem from "@/views/components/systemTag/semiControl/SystemTagItem.vue"html
<system-tag-item :tag-id="tag.id" allow-remove
@remove="handleRemoveTag(tag.id)"></system-tag-item>参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| tagId | 标签id | ||
| allowRemove | boolean | true |
PageHeader
此为全局注册组件
右侧操作栏为默认插槽,可自定义插入按钮等所需控件
面包屑可通过路由meta.breadcrumbParents自动生成,也可通过插槽自行定义
通过路由生成的面包屑,会自动过滤掉没有访问权限的路由
参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| hasSider | 该页面是否有侧边栏 | boolean | false |
| showIcon | 是否展示图标 | boolean | false |
| breadcrumb | 面包屑 | slots |
Sider
Sider
侧边栏组件,目前设计的模式是使用时自行注入菜单数据,组件内部会对没有访问权限的菜单项进行过滤
目前侧边栏的场景还不是很充分,包括各模块的路由设计模式也暂不明确。后续可根据实际情况进行调整
但基于菜单结构变更的可能性,暂时还是建议不要直接使用路由表生成菜单
javascript
import Sider from '@/views/components/sider/Sider.vue'
const route = useRoute(),
selectedKeys = computed({
get: () => {
return [route.matched[1]?.name!as string]
},
set: () => {
}
})
const siderMenus = routes[0].children || []html
<Sider v-if="route.name!=='MiniprogramAuth'" v-model:selected-keys="selectedKeys" :menus="siderMenus">
<template #infoBox="{collapsed}">
<InfoBox v-if="mpInfo" :collapsed="collapsed" class="mb-4"></InfoBox>
</template>
</Sider>参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| menus | 菜单 | RouteRecordRaw[] | |
| selectedKeys | 匹配的路由名称,其他可参考a-menu同名属性 | string[] |
插槽
| 参数 | 说明 | 参数 |
|---|---|---|
| infoBox | 侧边栏展示公众号/小程序等帐号信息 | { collapsed: boolean } |
InfoBox

javascript
import InfoBox from "@/views/components/sider/InfoBox.vue";html
<InfoBox v-if="mpInfo" :collapsed="collapsed" :avatar="mpInfo?.head_img"
:badge="OSS_MINIPROGRAM_IMG+'miniprogram_icon.png'" class="mb-4">
<template #title>{{ mpInfo?.nick_name }}</template>
<template #description>微信小程序</template>
</InfoBox>参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| collapsed | 是否侧边栏收起状态 | boolean | |
| avatar | 头像图片链接 | string | |
| badge | 头像右上角角标图片 | string |
插槽
| 参数 | 说明 |
|---|---|
| title | 主要标题,一般用于帐号名称 |
| description | 描述 |
WaterDropView
小水滴,目前支持checkbox和remove两种样式,如有其他样式可通过icon+customClass的方式使用,或拓展type
javascript
import WaterDropView from "@/views/components/common/WaterDropView.vue";html
<WaterDropView type="remove"></WaterDropView>参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| type | 类型 | checkbox remove | checkbox |
| icon | 自定义图标 | string | |
| customClass | 自定义样式类 | string |
CardCheckbox
卡片复选组件


javascript
import CardCheckbox from '@/views/components/CardCheckbox.vue'
const singleChecked = ref(false)
const list = ref([{
id: '1'
}, {
id: '2'
}])
const listMultipleChecked = ref(['1'])
const listChecked = ref('1')html
<CardCheckbox v-model:checked="singleChecked">
<div class="bg-danger2 p-4"> content</div>
</CardCheckbox>
<CardCheckbox v-for="item of list" :key="item.id" v-model:checked="listMultipleChecked" :value="item.id">
<div class="bg-danger2 p-4"> {{item.id}}</div>
</CardCheckbox>
<CardCheckbox v-for="item of list" :key="item.id" :multiple="false" v-model:checked="listChecked" :value="item.id">
<div class="bg-danger2 p-4"> {{item.id}}</div>
</CardCheckbox>参数说明
CheckboxValueType :
boolean|string|number引用自Antd: ant-design-vue/es/checkbox/interface
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| checked(v-model) | 选中状态或选中项目values | boolean CheckboxValueType[] CheckboxValueType undefined | |
| value | 选项索引,当checked不是boolean类型时需要 | CheckboxValueType | |
| multiple | 是否多选 | boolean | true |
物料选择操作栏

javascript
import OperationBar from '@/views/components/material/OperationBar.vue'搜索框的参数和事件参考InputSearch组件
参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| controls | 包含的操作 | refresh search create | refresh search create |
事件
| 事件名称 | 说明 |
|---|---|
| create | 点击去新建按钮 |
| refresh | 点击刷新按钮 |
物料选择器
useSelectModal
提供给选择器组件使用的composition
TIP
selectedValue 在multiple为true时是数组,为false时是字符串
html
<a-modal v-model:open="visible" width="1175px" @ok="handleOk" v-bind="modalProps">ts
import useSelectModal, {Emits, Props, defaultProps} from "@/views/components/material/useSelectModal"
// 定义props
withDefaults(defineProps<Props>(), defaultProps({title: "选择名片"}))
// 定义emit
const emit = defineEmits<Emits>()
// 通过暴露的方法获取modalProps、selectedValue、visible、handleOk
const {modalProps, selectedValue, visible, handleOk} = useSelectModal()SelectWeChatUser 选择微信用户
WARNING
多选,value和data都为数组;单选,value为字符串、data为object
- 单选
html
<SelectWeChatUser v-model:open="open" @ok="ok"></SelectWeChatUser>- 多选
html
<SelectWeChatUser v-model:open="open" multiple @ok="ok"></SelectWeChatUser>- 双向绑定完整的数据
- 单选
vue
<template>
<SelectWeChatUser v-model:open="open" v-model:data="dataObject"></SelectWeChatUser>
</template>
<script setup lang='ts'>
const valueData = ref({id:'xxx',...})
</script>- 多选
vue
<template>
<SelectWeChatUser v-model:open="open" v-model:data="dataArray" multiple></SelectWeChatUser>
</template>
<script setup lang='ts'>
const dataArray = ref([{id:'xxx',...},...])
</script>- 同时绑定id和data
- 单选
vue
<template>
<SelectWeChatUser v-model:open="open" v-model:value="valueId" v-model:data="dataObject"></SelectWeChatUser>
</template>
<script setup lang='ts'>
const valueId = ref('1'), valueData = ref({id:'xxx',...})
</script>- 多选
vue
<template>
<SelectWeChatUser v-model:open="open" v-model:value="valueIds" v-model:data="dataArray" multiple></SelectWeChatUser>
</template>
<script setup lang='ts'>
const valueIds = ref(['1', '2']), dataArray = ref([{id:'xxx',...},...])
</script>SelectWeChatWorkUser 选择企业微信用户
基本用法同SelectWeChatUser
SelectBusinessCard 选择名片
基本用法同SelectWeChatUser
SelectForm 选择问卷
基本用法同SelectWeChatUser
SelectImage 选择资源管理图片
基本用法同SelectWeChatUser
SelectWeChatTemplate 选择微信模板消息
基本用法同SelectWeChatUser
文件上传
useUpload
文件上传的composition,提供了上传的方法、上传的状态和受控的上传列表
- 选择文件后自动上传
vue
<template>
<a-upload-dragger
:class="{ 'pointer-events-none': uploading }"
v-model:file-list="fileList"
:maxCount="1"
:accept="accept.map((t) => '.' + t).join(',')"
:before-upload="beforeUpload"
:custom-request="uploadFile">
</a-upload-dragger>
</template>
<script lang="ts" setup>
import useUpload, {Props} from "./useUpload"
const props = defineProps<Props>()
const {fileList, beforeUpload, uploading, uploadFile} = useUpload(props)
</script>- 选择文件后手动上传
vue
<template>
<a-upload-dragger
:class="{ 'pointer-events-none': uploading }"
v-model:file-list="fileList"
:maxCount="1"
:accept="accept.map((t) => '.' + t).join(',')"
:before-upload="beforeUpload"
:custom-request="setAction">
</a-upload-dragger>
<a-button @click="uploadAllFiles()">upload</a-button>
</template>
<script lang="ts" setup>
import useUpload, {Props} from "./useUpload"
const props = defineProps<Props>()
const {fileList, beforeUpload, uploading, setAction, uploadAllFiles} = useUpload(props)
</script>TemplateUpload
上传文件的modal组件
vue
<template>
<Upload hasTemplate :action="requestAction" :accept="['csv','xlsx']"
:notes="['请确保上传的文件内容顺序和模板一致','<strong>请勿填写员工id</strong>,以防已有员工的信息被替换','确保新上传的员工和老员工不重复,员工管理将不会合并重复员工']"
v-model:open="open"></Upload>
</template>
<script lang="ts" setup>
function requestAction(file: any, onUploadProgress: any) {
Upload(file, onUploadProgress)
}
// 后端接口
function Upload(file, onUploadProgress) {
return axios.post(url, file, {
onUploadProgress
})
}
</script>UploadDrag
手动上传,也是TemplateUpload所使用的Upload组件
vue
<template>
<UploadDrag ref="uploadRef" :accept="['pdf']" :action="requestAction"></UploadDrag>
<a-button @click="uploadFile()">upload</a-button>
</template>
<script lang="ts" setup>
function requestAction(file: any, onUploadProgress: any) {
Upload(file, onUploadProgress)
}
// 后端接口
function Upload(file, onUploadProgress) {
return axios.post(url, file, {
onUploadProgress
})
}
const uploadRef = ref()
function uploadFile() {
uploadRef.value.uploadAllFiles()
}
</script>自动上传
vue
<template>
<UploadDrag :accept="['pdf']" :action="requestAction" autoUpload></UploadDrag>
</template>
<script lang="ts" setup>
function requestAction(file: any, onUploadProgress: any) {
Upload(file, onUploadProgress)
}
// 后端接口
function Upload(file, onUploadProgress) {
return axios.post(url, file, {
onUploadProgress
})
}
</script>分享类型的组件
ShareLinkInfo
分享链接和二维码
- 基本用法
html
<ShareLinkInfo
v-model:open="shareModal.visible"
:url="shareModal.url"></ShareLinkInfo>- 自定义二维码下载名称
html
<ShareLinkInfo
title="分享标签二维码"
v-model:open="shareModal.visible"
:url="shareModal.url"
:qrCode="{ downloadName: shareModal.downloadName }"></ShareLinkInfo>ShareWeChatCard
微信分享卡片设置
待填坑
PreviewContainer
iframe预览组件
- 基本用法
vue
<template>
<PreviewContainer :src="config.loginUrl" :width="300" :sendMessage="updateConfig"></PreviewContainer>
</template>
<script lang="ts" setup>
function updateConfig(el: HTMLIFrameElement) {
el.contentWindow.postMessage(
{
type: "updateConfig",
data: JSON.parse(JSON.stringify(data))
},
"*"
)
}
</script>ColorPicker
颜色选择器
- 基本用法
vue
<template>
<ColorPicker v-model:value="data.backgroundColor"></ColorPicker>
</template>
<script lang="ts" setup>
import ColorPicker from "@/views/components/colorPicker/ColorPicker.vue"
</script>- 自定义icon
vue
<template>
<ColorPicker v-model:value="data.backgroundColor" icon='...'></ColorPicker>
</template>
<template>
<ColorPicker v-model:value="data.backgroundColor">
<template #icon> ... </icon>
</ColorPicker>
</template>OverflowTooltip
仅在文字溢出时显示的tooltip,基本用法同a-tooltip
vue
<template>
<OverflowTooltip :title="name" custom-class="w-0 flex-grow" arrow-point-at-center></OverflowTooltip>
</template>
<script lang="ts" setup>
import OverflowTooltip from "@/views/components/OverflowTooltip.vue";
</script>ImagePicker
选择资源管理图片后进行展示和编辑
vue
<template>
<ImagePicker v-model:value="data.backgroundImage" title="选择背景"></ImagePicker>
</template>
<script lang="ts" setup>
import OverflowTooltip from "@/views/components/OverflowTooltip.vue";
</script>
知识的殿堂