优化线索、商机、项目相关开发
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<div class="detail-attach">
|
||||
<div class="tab-toolbar">
|
||||
<el-upload :show-file-list="false" :http-request="handleUpload" :disabled="uploading">
|
||||
<el-button type="primary" size="small" :icon="Upload" :loading="uploading">上传附件</el-button>
|
||||
</el-upload>
|
||||
<span v-if="tip" class="tip">{{ tip }}</span>
|
||||
</div>
|
||||
<el-table :data="list" v-loading="loading" stripe border size="small">
|
||||
<el-table-column label="文件名" min-width="170" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<a :href="row.file_url" target="_blank" class="file-link">{{ row.file_name || "-" }}</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="showStage" label="阶段" min-width="62" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small" effect="plain" :type="pipelineStageTag(row.related_type)">
|
||||
{{ pipelineStageText(row.related_type) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="大小" min-width="78" align="right">
|
||||
<template #default="{ row }">{{ formatFileSize(row.file_size) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="uploader_name" label="上传人" min-width="78" show-overflow-tooltip />
|
||||
<el-table-column label="上传时间" min-width="140">
|
||||
<template #default="{ row }">{{ formatDateTime(row.create_time) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="76" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="danger" size="small" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty><el-empty description="暂无附件" :image-size="60" /></template>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Upload } from "@element-plus/icons-vue";
|
||||
import { getAttachList, addAttach, deleteAttach } from "@/api/crmPipeline";
|
||||
import { uploadFile } from "@/api/file";
|
||||
import { formatDateTime, pipelineStageText, pipelineStageTag } from "../../dict";
|
||||
|
||||
const props = defineProps({
|
||||
// 关联对象ID
|
||||
relatedId: { type: [Number, String], default: null },
|
||||
// 关联类型:1=线索 2=商机 3=项目
|
||||
relatedType: { type: Number, default: 3 },
|
||||
// 工具栏提示文案
|
||||
tip: { type: String, default: "" },
|
||||
// 是否累积展示上游链路的附件(线索 + 商机 + 项目)
|
||||
includeSource: { type: Boolean, default: false },
|
||||
// 是否展示「阶段」列
|
||||
showStage: { type: Boolean, default: false },
|
||||
});
|
||||
const emit = defineEmits(["count"]);
|
||||
|
||||
const loading = ref(false);
|
||||
const uploading = ref(false);
|
||||
const list = ref([]);
|
||||
|
||||
/** 供父组件(detail.vue)在抽屉打开时调用 */
|
||||
async function reload() {
|
||||
if (!props.relatedId) {
|
||||
list.value = [];
|
||||
emit("count", 0);
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
try {
|
||||
const params = {
|
||||
related_type: props.relatedType,
|
||||
related_id: props.relatedId,
|
||||
};
|
||||
if (props.includeSource) params.include_source = 1;
|
||||
const res = await getAttachList(params);
|
||||
list.value = res?.data?.list || [];
|
||||
} catch (e) {
|
||||
list.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
emit("count", list.value.length);
|
||||
}
|
||||
|
||||
async function handleUpload(options) {
|
||||
const file = options.file;
|
||||
uploading.value = true;
|
||||
try {
|
||||
const fd = new FormData();
|
||||
fd.append("file", file);
|
||||
const res = await uploadFile(fd);
|
||||
const data = res?.data || {};
|
||||
await addAttach({
|
||||
related_type: props.relatedType,
|
||||
related_id: props.relatedId,
|
||||
file_id: data.id || 0,
|
||||
file_name: data.name || file.name,
|
||||
file_url: data.url || "",
|
||||
file_size: file.size || 0,
|
||||
});
|
||||
ElMessage.success("上传成功");
|
||||
reload();
|
||||
} catch (e) {
|
||||
ElMessage.error(e.message || "上传失败");
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row) {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定删除附件「${row.file_name}」吗?`, "删除确认", { type: "warning" });
|
||||
await deleteAttach({ id: row.id });
|
||||
ElMessage.success("删除成功");
|
||||
reload();
|
||||
} catch (e) {
|
||||
if (e !== "cancel") ElMessage.error(e.message || "删除失败");
|
||||
}
|
||||
}
|
||||
|
||||
function formatFileSize(size) {
|
||||
const n = Number(size) || 0;
|
||||
if (n < 1024) return `${n} B`;
|
||||
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
||||
return `${(n / 1024 / 1024).toFixed(2)} MB`;
|
||||
}
|
||||
|
||||
defineExpose({ reload });
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tab-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
|
||||
.tip {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
.file-link {
|
||||
color: var(--el-color-primary);
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user