1.修改组件样式
/deep/ :deep() less 的嵌套格式,看起来舒服
:deep(.ant-calendar-picker-input) {
.xxxx {
......
}
}
2. 修改弹框,下拉框全局样式
自定义app.less, 全局导入
// 选择器下拉框 悬浮样式
antdv 定制样式
modifyVars: {
"select-item-selected-color": "#00706B",
"select-selection-item-bg": "#EAFAF9",
}
.ant-select-item-option-active:not(.ant-select-item-option-disabled) {
background-color: xxx !important ;
}
.ant-select-item-option-selected:not(.ant-select-item-option-disabled) {
background-color: xxx !important ;
}
// 特殊的菜单样式,可以加个class 标识 菜单menu 悬浮样式
.myNavDrown {
.ant-dropdown-menu {
padding: 4px!important;
}
.ant-dropdown-menu-item:hover {
background-color: xxx !important;
}
}
// 时间下拉框
li.ant-time-picker-panel-select-option-selected {
background-color: xxx !important;
color: #00706B;
}
.ant-time-picker-panel-select li:hover {
background-color: xxxx !important;
}
3. 日期组件直接展示
getCalendarContainer 挂载到其他标签 open 表示直接展示
<div class="xxx" ref="xxx" @click="Select">
<DatePicker @change="dateChange" :open="true" :disabled="true" :showToday="false" :popupStyle="{
width: 'xxxpx', zIndex: 99
}
:getCalendarContainer="() => $refs.xxxx">
</DatePicker>
</div>
4. button各种状态颜色
自定义class my-hoor-btn, type=default 默认 悬浮 点击 不可点击. type=primary 默认 悬浮 点击 不可点击. Button有图标,使用svg文件,
svg文件修改:
1. width="20" height="20 fill="none"
2. fill, stoke 默认 currentColor, 所以颜色设置可以删除
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="">
<g id="Group 1000004360">
<path id="Rectangle 34625382" d="" stroke-width="1.25"/>
<path id="Union" fill-rule="evenodd" clip-rule="evenodd" d="" fill="currentColor"/>
</g>
</g>
</svg>
.my-hoor-btn {
color: #333!important;
border-color: #ccc!important;
background-color: #fff!important;
}
.my-hoor-btn:hover {
color: #1EABA6!important;
border-color: #1EABA6!important;
background-color: #fff!important;
}
.my-hoor-btn:focus {
color: #006054!important;
border-color: #006054!important;
background-color: #EAFAF9!important;
}
.my-hoor-btn[disabled] {
color: #999!important;
border-color: #ccc!important;
background-color: #eee!important;
}
.my-hoor-btn.ant-btn-primary {
color: #fff!important;
background-color: #00706B!important;
}
.my-hoor-btn.ant-btn-primary:hover {
color: #fff!important;
background-color: #1EABA6!important;
}
.my-hoor-btn.ant-btn-primary:focus {
color: #fff!important;
background-color: #006054!important;
}
.my-hoor-btn.ant-btn-primary[disabled] {
color: #999!important;
background-color: #eee!important;
}
5.二次封装Modal
<MyTip v-model:visible="myDeleteInfo.deleteVisible" :deleteConfirmLoading="myDeleteInfo.deleteLoading"
@ok="deleteOk" msg="该日程"></MyTip>
const myDeleteInfo = reactive({
deleteVisible: false,
deleteLoading: false
})
const deleteOk = async () => {
myDeleteInfo.deleteLoading = true
const res = await xxx
....
myDeleteInfo.deleteLoading = false
myDeleteInfo.deleteVisible = false
}
使用了v-model:visible, 需要定义defineProps(['visible']) 和 defineEmits(['update:visible'])
visible 不能直接使用,通过computed 包装了一层,否则会报错(Cannot read property 'content' of null)
slot 定义other 和默认的视图
<template>
<Modal :visible="tipVisible" @cancel="handleCancle" centered width='592px' title="操作确认">
<div class="delete-content">
<slot>
<img src="@/assets/image/sxxx.png" style="height: 32px;" alt="" srcset="">
<div class="">
<div class="delete-desc-1">
您确定<span style="color: #45B4A7;">删除</span>{{msg}}?</div>
<div class="delete-desc-2">
删除后不可恢复。
</div>
</div>
</slot>
<slot name="other"></slot>
</div>
<template #footer>
<Button class="my-hoor-btn" @click="handleCancle">取消</Button>
<Button class="my-hoor-btn" type="primary" :loading="loading" @click="handleOk">确定</Button>
</template>
</Modal>
</template>
<script setup lang="ts">
import {
defineProps,
defineEmits,
watch,
watchEffect,
ref
} from 'vue'
import {
Button,
Modal,
} from 'ant-design-vue';
const props = defineProps(['msg', 'visible', 'deleteConfirmLoading'])
const emit = defineEmits(['ok', 'update:visible'])
const loading = ref(false)
watch(() => props.deleteConfirmLoading, (val) => {
loading.value = val
})
const tipVisible = computed(() => props.visible)
const handleCancle = () => {
emit('update:visible', false)
}
const handleOk = () => {
emit('ok')
}
</script>
<style scoped lang="less">
.delete-content {
display: flex;
padding: 0 20px;
.delete-desc-1 {
padding-top: 6px;
padding-left: 20px;
font-size: 16px;
font-weight: bold;
color: #333333;
line-height: 24px;
}
.delete-desc-2 {
padding-left: 20px;
padding-top: 10px;
font-size: 14px;
color: #333333;
line-height: 22px;
}
}
</style>
6. 表格分页多选
onSelect 单选 selected 勾选 不勾选, array push splice处理的
onSelectAll 全选 selected 勾选 不勾选。
勾选 array 遍历 + push + 单独局部变量
不勾选 array 转化set + set 存在删除(hash 效率高) + set转array
<a-table ref="tablePage" :scroll="{x: 'max-content'}" :row-selection="{ selectedRowKeys: selectedRowKeys, onSelect, onSelectAll }"></a-table>
const selectedRowKeys = ref < Key[] > ([])
const onSelect = (record: any, selected: boolean) => {
if (selected) {
selectedRowKeys.value.push(record.consNo)
} else {
const ind = selectedRowKeys.value.indexOf(record.consNo)
if (ind != -1) {
selectedRowKeys.value.splice(ind, 1)
}
}
}
const onSelectAll = (selected: boolean, selectedRows: any[], changeRows: any[]) => {
const arr = selectedRowKeys.value
if (selected) {
changeRows.forEach((item) => {
arr.push(item.consNo)
})
selectedRowKeys.value = arr
} else {
const set = new Set(arr)
changeRows.forEach((item) => {
if (set.has(item.consNo)) {
set.delete(item.consNo)
}
})
selectedRowKeys.value = Array.from(set)
}
}
7.自定义选择器(选择框和下拉框) + 下拉框点击出现弹框
- 自定义选择器 Dropdown组件,将v-model:visible 拆开:visible="xxx" @update:visible="xxx".visible手动控制展示隐藏,拆开更自由控制
- 下拉框 queryed:刚点击input 不出现下拉框
- state.fetching 请求中页面
- state.data.length >0 有无数据展示
<Dropdown :visible="alertVisible" @update:visible="alertVisibleChange" :getPopupContainer="triggerNode => triggerNode.parentNode"
:trigger="['click']">
<Input v-model:value="searchValue" @change="searchChange" class="tongSelect" allow-clear placeholder="xxx···" />
<template #overlay>
<div v-if="queryed" class="t_list_wrap">
<div class="t_item_wrap">
<div class="t_i_name">姓名</div>
<div class="t_i_dept">部门</div>
</div>
<div v-if="!state.fetching" class="t_content_wrap">
<div v-if="state.data.length >0" class="t_content_item_wrap"
:class="{cselect: detailInfo ? detailInfo.uuid == item.uuid : false}" v-for="item in state.data" :key="item.uuid"
@click="detailShow(item)">
<div class="t_content_i_name">
{{item.empName}}
</div>
<div class="t_content_i_dept">
{{item.deptName}}
</div>
</div>
<div v-else class="">
<Empty :image="simpleImage"></Empty>
</div>
</div>
<div v-else class="loading_wrap">
<Spin />
</div>
</div>
</template>
</Dropdown>
<Modal class="tongDetailModal" v-model:visible="detailVisible" width="auto" :zIndex="9999" :closable="false" :footer="null" :bodyStyle="{
padding: '0!important',
}" style="margin-left: calc(100% - 360px);margin-top: 200px;">
<div v-if="detailInfo" class="detailWrap">
<div class="info">
....
</div>
</div>
</Modal>
v-model:visible 拆开:visible="xxx" @update:visible="xxx",为了当Modal 隐藏(点击空白处,上面搜索下拉框不会消失)
debounce 做了防抖
import {
Dropdown,
Input,
Modal,
Empty,
Spin
} from 'ant-design-vue';
import {
reactive,
ref,
defineExpose
} from 'vue'
import {
debounce
} from 'lodash-es'
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE
// 搜索列表 展示控制
const alertVisible = ref(false)
// 搜索文字
const searchValue = ref('')
// 搜索列表详情 展示控制
const detailVisible = ref(false)
// 详情提示框展示
const detailInfo = ref(null)
const detailShow = (info) => {
detailInfo.value = info
detailVisible.value = true
}
// 详情 关闭按钮
const closeModal = () => {
detailVisible.value = false
}
// 搜索列表 update:visible 回调
const alertVisibleChange = (value) => {
if (!detailVisible.value) {
alertVisible.value = value
}
}
// 第一次请求已发
const queryed = ref(false)
const state = reactive({
data: [],
fetching: false,
});
const arrTest = {
"msg": "成功",
"code": 200,
"data": [{
"deptName": "xxx",
"email": "xxx",
"empName": "xx",
"mobilePhone": "xxx",
"phone": "xxx",
"uuid": "xxx00xx",
},
{
"deptName": "xxx2",
"email": "xxx2",
"empName": "xx2",
"mobilePhone": "xxx2",
"phone": "xxx2",
"uuid": "xxx00xx2",
}
]
}
const getAddressData = (value) => {
queryed.value = true
state.data = [];
state.fetching = true;
setTimeout(() => {
if (arrTest.code === 200) {
state.data = arrTest.data
}
state.fetching = false;
}, 3000)
}
const searchChange = debounce(getAddressData, 800)