| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- <script setup lang="ts">
- import type { Recordable } from '@vben/types';
- import { computed, type PropType, useSlots } from 'vue';
- import { Tooltip } from 'ant-design-vue';
- import { Icon } from '#/components/icon';
- import defaultImg from './images/head-default.png';
- import FemaleImg from './images/head-female.png';
- import MaleImg from './images/head-male.png';
- import RoleImg from './images/role.png';
- defineOptions({
- name: 'SelectCardItem',
- });
- const props = defineProps({
- model: {
- type: Object as PropType<Recordable<any>>,
- default: () => ({}),
- },
- fieldNames: {
- type: Array as PropType<Array<any>>,
- default: () => [
- { title: '名称', value: 'title', maxLength: 12 },
- { title: '电话', value: 'phone', maxLength: 8 },
- ],
- },
- config: {
- type: Object as PropType<{
- bgcolor: string;
- color: string;
- fillColor: string;
- type: string;
- }>,
- default: () => ({
- type: 'none',
- fillColor: '#f1ecfe',
- bgcolor: '#f5f1fd',
- color: '#b389ff',
- }),
- },
- disabled: {
- type: Boolean as PropType<boolean>,
- default: false,
- },
- showTree: {
- type: Boolean as PropType<boolean>,
- default: false,
- },
- });
- const hasCheckSlot = computed(() => {
- return !!useSlots().check;
- });
- const getImage = computed(() => {
- switch (props.config.type) {
- case 'role': {
- return RoleImg;
- }
- case 'user': {
- return props.model.sex === 1 ? MaleImg : FemaleImg;
- }
- default: {
- return defaultImg;
- }
- }
- });
- const getFillColor = computed(() => {
- if (props.config.type === 'user') {
- return props.model.sex === 1 ? '#e9f0fe' : '#ffedf5';
- } else {
- return props.config.fillColor || '#f1ecfe';
- }
- });
- const getFontColor = computed(() => {
- if (props.config.type === 'user') {
- return props.model.sex === 1 ? '#3c7eff' : '#ffd1d7';
- } else {
- return props.config.color || '#b389ff';
- }
- });
- const getBgcolor = computed(() => {
- if (props.config.type === 'user') {
- return props.model.sex === 1 ? '#f3f8ff' : '#fef6fa';
- } else {
- return props.config.bgcolor || '#f5f1fd';
- }
- });
- const itemleftwidth = computed(() => {
- return props.showTree ? '30%' : '25%';
- });
- </script>
- <template>
- <div class="select-card-item">
- <div class="select-card-item-box">
- <div class="select-card-item-left">
- <img :src="getImage" />
- </div>
- <div class="z-10">
- <div
- v-for="(item, index) in fieldNames"
- :key="index"
- class="select-card-item-right flex items-center"
- >
- <div class="select-card-item-right-title">
- {{ item.title }}
- </div>
- <Tooltip
- v-if="
- model[item.value] &&
- model[item.value].length > model[item.value].maxLength
- "
- :title="model[item.value]"
- >
- <div class="select-card-item-right-name">
- {{
- `${model[item.value].slice(0, model[item.value].maxLength)}...`
- }}
- </div>
- </Tooltip>
- <div v-else class="select-card-item-right-name">
- {{ model[item.value] || '-' }}
- </div>
- </div>
- </div>
- <!-- <div v-if="props.disabled">
- <div class="fixed-checked"> 禁用 </div>
- </div> -->
- <div v-if="hasCheckSlot" class="fixed-checked">
- <slot name="check"></slot>
- </div>
- <div class="fixed-icon">
- <Icon :color="getFillColor" class="size-16" icon="fa6-solid:user-tie" />
- </div>
- </div>
- </div>
- </template>
- <style lang="less" scoped>
- .select-card-item {
- width: 30%;
- margin-bottom: 20px;
- margin-left: 20px;
- overflow: hidden;
- border-radius: 8px;
- border-color: transparent;
- background: v-bind(getBgcolor);
- &:hover {
- border: 1px dotted v-bind(getFontColor);
- }
- &-box {
- display: flex;
- position: relative;
- margin: 14px;
- }
- &-left {
- width: v-bind(itemleftwidth);
- margin-right: 14px;
- img {
- width: 100%;
- height: 100%;
- }
- }
- &-right {
- &-title {
- margin: 10px 10px 4px 0;
- opacity: 0.8;
- color: #999;
- font-size: 12px;
- font-weight: bold;
- }
- &-name {
- margin: 8px 0 4px;
- opacity: 0.8;
- color: #303133;
- font-size: 14px;
- font-weight: bold;
- }
- }
- .fixed-checked {
- position: absolute;
- z-index: 1;
- right: -6px;
- bottom: -4px;
- }
- .fixed-icon {
- position: absolute;
- z-index: 0;
- top: -24px;
- right: -24px;
- transform: rotate(48deg);
- }
- }
- :deep(.ant-checkbox-inner) {
- border-color: v-bind(getFontColor);
- }
- :deep(.ant-checkbox-checked .ant-checkbox-inner) {
- border-color: v-bind(getFontColor);
- background-color: v-bind(getFontColor);
- }
- :deep(.ant-checkbox-checked::after),
- :deep(.ant-checkbox-wrapper:hover .ant-checkbox-inner, .ant-checkbox:hover),
- :deep(.ant-checkbox-inner),
- :deep(.ant-checkbox:hover),
- :deep(.ant-checkbox-input:focus + .ant-checkbox-inner) {
- border-color: v-bind(getFontColor);
- }
- .picked {
- border-width: 1px;
- border-style: dotted;
- border-color: v-bind(getFontColor);
- }
- .not-picked {
- border-width: 1px;
- border-style: dotted;
- }
- </style>
|