Files
EasyFlow/easyflow-ui-admin/app/src/views/ai/workflow/components/ConfirmItemMulti.vue
陈子默 7e7c236c2a fix: 修复管理端前端 lint 与构建问题
- 收敛 easyflow-ui-admin 的 lint、格式和类型问题

- 修正 demo 页面与管理端前端构建失败点

- 验证 pnpm lint 与 pnpm build 均已通过
2026-04-05 21:39:13 +08:00

217 lines
5.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { Download } from '@element-plus/icons-vue';
import { ElIcon, ElText } from 'element-plus';
import confirmFile from '#/assets/ai/workflow/confirm-file.png';
// 导入你的图片资源
import confirmOther from '#/assets/ai/workflow/confirm-other.png';
// 定义 Props
const props = defineProps({
// v-model 绑定值,多选版本这里是数组
modelValue: {
type: Array as () => any[],
default: () => [],
},
// 数据类型: text, image, video, audio, other, file
selectionDataType: {
type: String,
default: 'text',
},
// 数据列表
selectionData: {
type: Array as () => any[],
default: () => [],
},
});
// 定义 Emits
const emit = defineEmits(['update:modelValue', 'change']);
// 判断是否选中
const isSelected = (item: any) => {
return props.modelValue && props.modelValue.includes(item);
};
// 切换选中状态 (多选逻辑)
const changeValue = (item: any) => {
// 复制一份当前数组,避免直接修改 prop
const currentValues = props.modelValue ? [...props.modelValue] : [];
const index = currentValues.indexOf(item);
if (index === -1) {
// 如果不存在,则添加
currentValues.push(item);
} else {
// 如果已存在,则移除
currentValues.splice(index, 1);
}
// 更新 v-model
emit('update:modelValue', currentValues);
// 触发 Element Plus 表单验证
emit('change', currentValues);
};
// 获取图标
const getIcon = (type: string) => {
return type === 'other' ? confirmOther : confirmFile;
};
// 下载处理
const handleDownload = (url: string) => {
window.open(url, '_blank');
};
</script>
<template>
<div class="custom-radio-group">
<template v-for="(item, index) in selectionData" :key="index">
<!-- 类型: Text -->
<div
v-if="selectionDataType === 'text'"
class="custom-radio-option"
:class="{ selected: isSelected(item) }"
style="flex-shrink: 0; width: 100%"
@click="changeValue(item)"
>
{{ item }}
</div>
<!-- 类型: Image -->
<div
v-else-if="selectionDataType === 'image'"
class="custom-radio-option"
:class="{ selected: isSelected(item) }"
style="padding: 0"
@click="changeValue(item)"
>
<img
:src="item"
alt=""
style="display: block; width: 80px; height: 80px; border-radius: 8px"
/>
</div>
<!-- 类型: Video -->
<div
v-else-if="selectionDataType === 'video'"
class="custom-radio-option"
:class="{ selected: isSelected(item) }"
@click="changeValue(item)"
>
<video controls :src="item" style="width: 162px; height: 141px"></video>
</div>
<!-- 类型: Audio -->
<div
v-else-if="selectionDataType === 'audio'"
class="custom-radio-option"
:class="{ selected: isSelected(item) }"
style="flex-shrink: 0; width: 300px"
@click="changeValue(item)"
>
<audio controls :src="item" style="width: 100%; height: 40px"></audio>
</div>
<!-- 类型: File Other -->
<div
v-else-if="
selectionDataType === 'other' || selectionDataType === 'file'
"
class="custom-radio-option"
:class="{ selected: isSelected(item) }"
style="flex-shrink: 0; width: 100%"
@click="changeValue(item)"
>
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
"
>
<div style="display: flex; align-items: center; width: 92%">
<img
style="width: 20px; height: 20px; margin-right: 8px"
alt=""
:src="getIcon(selectionDataType)"
/>
<!-- 使用 Element Plus 的 Text 组件处理省略号 -->
<ElText truncated>
{{ item }}
</ElText>
</div>
<div class="download-icon-btn" @click.stop="handleDownload(item)">
<ElIcon><Download /></ElIcon>
</div>
</div>
</div>
</template>
</div>
</template>
<style scoped>
/* 这里复用之前的 CSS样式完全一致 */
.custom-radio-group {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.custom-radio-option {
position: relative;
box-sizing: border-box;
padding: 8px;
cursor: pointer;
background-color: var(--el-bg-color);
border-radius: 8px;
box-shadow: 0 0 0 1px var(--el-border-color);
transition: all 0.2s;
}
.custom-radio-option:hover {
box-shadow: 0 0 0 1px var(--el-color-primary-light-5);
}
.custom-radio-option.selected {
padding: 8px;
background: var(--el-color-primary-light-9);
box-shadow: 0 0 0 1px var(--el-color-primary-light-3);
}
.custom-radio-option.selected::after {
position: absolute;
right: 0;
bottom: 0;
box-sizing: border-box;
width: 16px;
height: 16px;
content: '';
background-color: var(--el-color-primary);
border-radius: 6px 2px;
}
.custom-radio-option.selected::before {
position: absolute;
right: 3px;
bottom: 7px;
z-index: 1;
width: 9px;
height: 5px;
content: '';
border-bottom: 1px solid white;
border-left: 1px solid white;
transform: rotate(-45deg);
}
.download-icon-btn {
display: flex;
align-items: center;
margin-right: 10px;
font-size: 18px;
cursor: pointer;
}
</style>