<template>
|
<div :style="{ minWidth: minWidth }">
|
<template v-for="(o, key) in operations" :key="key">
|
<!-- 上传:与原实现一致,走 el-upload 自身的 action 自动上传 -->
|
<el-upload
|
v-if="o.type === 'upload'"
|
v-show="isVisible(o)"
|
:key="uploadKey"
|
:ref="el => setUploadRef(key, el)"
|
:action="uploadAction(o)"
|
:multiple="!!o.multiple"
|
:limit="1"
|
:disabled="isDisabled(o)"
|
:accept="o.accept || DEFAULT_ACCEPT"
|
:headers="currentUploadHeader()"
|
:before-upload="beforeUpload"
|
:on-change="(file, fileList) => onChange(file, fileList, key)"
|
:on-error="() => onError(key)"
|
:on-success="response => onSuccess(response, key)"
|
:on-exceed="onExceed"
|
:show-file-list="false"
|
style="display: inline-block; width: 50px"
|
>
|
<el-button link :size="normalizeSize(o.size) || 'small'" :disabled="isDisabled(o)">{{ o.name }}</el-button>
|
</el-upload>
|
|
<el-button
|
v-else
|
v-show="isVisible(o)"
|
size="small"
|
:disabled="isDisabled(o)"
|
:icon="$icon(iconName(o))"
|
:plain="o.plain"
|
:link="isTextButton(o)"
|
:style="{ color: o.color }"
|
:type="buttonType(o)"
|
@click="onClick(o)"
|
>
|
{{ o.name }}
|
</el-button>
|
</template>
|
</div>
|
</template>
|
|
<script setup>
|
import { ElMessage } from 'element-plus'
|
import { actionWidth } from './action-width'
|
|
const DEFAULT_ACCEPT = '.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
|
|
const props = defineProps({
|
operations: {
|
type: Array,
|
default: () => []
|
},
|
row: {
|
type: Object,
|
default: () => ({})
|
}
|
})
|
|
const { proxy } = getCurrentInstance()
|
|
// 每个实例只服务一行,用 Map 收函数 ref,避免原实现「以 $index 为 key 的全局 record」带来的串行
|
const uploadRefs = new Map()
|
const uploadKey = ref(Date.now())
|
|
const minWidth = computed(() => `${actionWidth(props.operations, props.row)}px`)
|
|
function setUploadRef(key, el) {
|
if (el) {
|
uploadRefs.set(key, el)
|
} else {
|
uploadRefs.delete(key)
|
}
|
}
|
|
function isVisible(o) {
|
return o.showHide ? o.showHide(props.row) : true
|
}
|
|
function isDisabled(o) {
|
return o.disabled ? o.disabled(props.row) : false
|
}
|
|
// 操作按钮回调:页面在 operation 项里用 clickFun(row) 声明点击行为
|
function onClick(o) {
|
if (typeof o.clickFun === 'function') {
|
o.clickFun(props.row)
|
}
|
}
|
|
// o.type 可能是函数,取值与原实现的 typeFn 过滤器一致
|
function resolveButtonType(o) {
|
return typeof o.type === 'function' ? o.type(props.row) : o.type
|
}
|
|
// element-ui 的 type="text" 在 element-plus 里已废弃,等价形态是 link 布尔属性
|
function isTextButton(o) {
|
return resolveButtonType(o) === 'text'
|
}
|
|
function buttonType(o) {
|
// 删除类操作统一走 danger 语义色,避免内联 #f56c6c 绕过 token(暗色模式会失效)
|
if (o.name === '删除') return 'danger'
|
const t = resolveButtonType(o)
|
// element-ui 的 type="text" 等价于 element-plus 的 link 按钮;显式给 primary,
|
// 与各页面手写的 <el-button link type="primary"> 保持一致(否则默认是灰色文字)
|
return t === 'text' ? 'primary' : t
|
}
|
|
function iconName(o) {
|
if (Object.prototype.hasOwnProperty.call(o, 'icon')) return o.icon
|
if (o.name === '编辑' || o.name === '修改') return 'el-icon-edit'
|
if (o.name === '查看') return 'el-icon-view'
|
return o.icon
|
}
|
|
// element-plus 只认 large/default/small,旧值 mini/medium 会触发 prop 校验告警
|
function normalizeSize(size) {
|
if (size === 'mini') return 'small'
|
if (size === 'medium') return 'default'
|
return size
|
}
|
|
function uploadAction(o) {
|
const id = o.uploadIdFun ? o.uploadIdFun(props.row) : props.row.id
|
return proxy.javaApi + o.url + '?id=' + id
|
}
|
|
function currentUploadHeader() {
|
return proxy.uploadHeader
|
}
|
|
function beforeUpload(file) {
|
if (file.size > 1024 * 1024 * 10) {
|
ElMessage.error('上传文件不超过10M')
|
return false
|
}
|
return true
|
}
|
|
function onChange(file, fileList, key) {
|
// 超出限制时移除最早的文件
|
if (fileList.length > 1) {
|
uploadRefs.get(key)?.handleRemove(fileList[0])
|
}
|
}
|
|
function onSuccess(response, key) {
|
if (response.code == 200) {
|
uploadRefs.get(key)?.clearFiles()
|
ElMessage.success('上传成功')
|
// 换 key 强制重建组件,清掉内部文件列表
|
uploadKey.value = Date.now()
|
} else {
|
ElMessage.error(response.message)
|
}
|
}
|
|
// 必须清空内部文件列表,否则 limit=1 会让下一次选择直接触发 on-exceed
|
function onError(key) {
|
ElMessage.error('文件上传失败,请重试')
|
uploadRefs.get(key)?.clearFiles()
|
}
|
|
function onExceed() {
|
ElMessage.warning('超出文件个数')
|
}
|
</script>
|