This commit is contained in:
我是个攻城狮
2026-07-31 16:55:24 +08:00
parent 77da721290
commit 85489c4778
2 changed files with 143 additions and 27 deletions
Binary file not shown.
+139 -23
View File
@@ -17,7 +17,7 @@
</div>
<div class="toolbar-actions">
<button type="button" class="ghost-btn" @click="batchDialogVisible = true">批量增加主播</button>
<button type="button" class="ghost-btn" @click="openBatchDialog">批量增加主播</button>
<button type="button" class="primary-btn" @click="goTalentForm()">+ 增加主播</button>
</div>
</div>
@@ -58,8 +58,7 @@
</tbody>
</table>
</div>
<el-dialog :visible.sync="batchDialogVisible" width="760px" custom-class="batch-dialog" append-to-body>
<el-dialog :visible.sync="batchDialogVisible" :show-close="false" width="760px" custom-class="batch-dialog" append-to-body @close="resetBatchUpload">
<div class="batch-body">
<div class="batch-head">
<div>
@@ -71,20 +70,23 @@
<div class="batch-upload-row">
<span class="upload-field">主播信息表</span>
<button type="button" class="upload-btn" @click="triggerBatchUpload">上传文件</button>
<button type="button" class="upload-btn" :disabled="uploadedBatchFiles.length >= 30" @click="triggerBatchUpload">上传文件</button>
<input ref="batchUploader" type="file" class="hidden-input" multiple accept=".doc,.docx" @change="handleBatchUpload" />
<!-- <span class="upload-count">已上传 {{ uploadedBatchFiles.length }}/30</span> -->
</div>
<div class="batch-tip">格式要求word不超过10M可同时上传最多30位主播信息表</div>
<div class="batch-tip">格式要求word不超过10M可同时上传最多30位主播信息表支持多次选择追加</div>
<div class="preview-list">
<div v-for="(item, index) in uploadedBatchFiles" :key="item.name + index" class="preview-card">
<div class="preview-doc"></div>
<div class="preview-name">{{ item.name }}</div>
<div class="preview-doc">
<button type="button" class="preview-remove" @click="removeBatchFile(index)">×</button>
</div>
<div class="preview-name" :title="item.name">{{ item.name }}</div>
</div>
</div>
<div class="batch-actions">
<button type="button" class="dialog-btn ghost" @click="batchDialogVisible = false">取消</button>
<button type="button" class="dialog-btn ghost" @click="closeBatchDialog">取消</button>
<button type="button" class="dialog-btn primary" @click="submitBatch">立即提交</button>
</div>
</div>
@@ -104,6 +106,8 @@ import assetActiveIcon from '@/assets/img/user/申请icon.png';
import assetInactiveIcon from '@/assets/img/user/申请未选中.png';
const TALENT_STORAGE_KEY = 'cog.org.talents';
const MAX_BATCH_FILES = 30;
const MAX_FILE_SIZE = 10 * 1024 * 1024;
const API_ENDPOINTS = {
list: '/api/mcn/anchors/list',
delete: '/api/mcn/anchors/delete',
@@ -195,29 +199,95 @@ export default {
saveTalents(this.talents);
this.$message.success(`已删除,接口待接入:${this.apiEndpoints.delete}`);
},
openBatchDialog() {
this.resetBatchUpload();
this.batchDialogVisible = true;
},
closeBatchDialog() {
this.batchDialogVisible = false;
this.resetBatchUpload();
},
resetBatchUpload() {
this.uploadedBatchFiles = [];
if (this.$refs.batchUploader) {
this.$refs.batchUploader.value = '';
}
},
triggerBatchUpload() {
if (this.uploadedBatchFiles.length >= MAX_BATCH_FILES) {
this.$message.warning(`最多只能上传${MAX_BATCH_FILES}个主播信息表`);
return;
}
this.$refs.batchUploader.click();
},
handleBatchUpload(event) {
const files = Array.from(event.target.files || []);
const invalid = files.some(file => file.size > 10 * 1024 * 1024);
if (invalid) {
this.$message.warning('单个文件大小不能超过10M');
event.target.value = '';
if (!files.length) {
return;
}
this.uploadedBatchFiles = files.slice(0, 30).map(file => ({ name: file.name }));
event.target.value = '';
const invalidSize = files.some(file => file.size > MAX_FILE_SIZE);
if (invalidSize) {
this.$message.warning('单个文件大小不能超过10M');
return;
}
const remain = MAX_BATCH_FILES - this.uploadedBatchFiles.length;
if (remain <= 0) {
this.$message.warning(`最多只能上传${MAX_BATCH_FILES}个主播信息表`);
return;
}
if (files.length > remain) {
this.$message.warning(`最多只能上传${MAX_BATCH_FILES}个主播信息表,本次仅添加${remain}`);
}
const existingNames = new Set(this.uploadedBatchFiles.map(item => item.name));
const nextFiles = [];
files.slice(0, remain).forEach(file => {
if (existingNames.has(file.name)) {
return;
}
existingNames.add(file.name);
nextFiles.push({ name: file.name, file });
});
if (!nextFiles.length) {
this.$message.warning('所选文件已存在或无可添加文件');
return;
}
this.uploadedBatchFiles = this.uploadedBatchFiles.concat(nextFiles);
},
removeBatchFile(index) {
this.uploadedBatchFiles.splice(index, 1);
},
downloadTemplate() {
const content = '主播姓名,手机号,身份证号,全网粉丝总数,全网作品点击量,近一年利润,近一年直播场次,授权截止日期,平台名称,垂类赛道,平台ID,粉丝数量,主播昵称';
const blob = new Blob([content], { type: 'application/msword;charset=utf-8' });
const url = URL.createObjectURL(blob);
const fileName = '主播信息登记表.docx';
const fileUrl = encodeURI(`/img/${fileName}`);
fetch(fileUrl)
.then(res => {
if (!res.ok) {
throw new Error('download failed');
}
return res.blob();
})
.then(blob => {
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = '主播信息模板.doc';
link.download = fileName;
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(url);
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
})
.catch(() => {
this.$message.error('模板下载失败,请稍后重试');
});
},
submitBatch() {
if (!this.uploadedBatchFiles.length) {
@@ -225,7 +295,8 @@ export default {
return;
}
this.batchDialogVisible = false;
this.$message.success(`批量导入已提交,接口待接入:${this.apiEndpoints.batchImport}`);
this.$message.success(`批量导入已提交${this.uploadedBatchFiles.length}个文件),接口待接入:${this.apiEndpoints.batchImport}`);
this.resetBatchUpload();
}
},
watch: {
@@ -237,6 +308,7 @@ export default {
</script>
<style lang="scss" scoped>
.toolbar {
display: flex;
justify-content: space-between;
@@ -411,11 +483,21 @@ export default {
font-size: 20px;
}
.batch-head p,
.batch-head p{
margin-top: 12px;
font-weight: 400;
font-size: 13px;
color: #999FB8;
line-height: 19px;
text-align: left;
}
.batch-tip {
margin-top: 14px;
color: #9aa2bd;
font-size: 14px;
margin-top: 8px;
font-weight: 400;
font-size: 12px;
color: #999FB8;
text-align: left;
margin-left: 108px;
}
.template-btn {
@@ -442,17 +524,29 @@ export default {
height: 34px;
}
.upload-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.upload-count {
font-size: 13px;
color: #999FB8;
}
.preview-list {
display: flex;
gap: 16px;
flex-wrap: wrap;
margin-top: 16px;
min-height: 88px;
margin-left: 108px;
}
.preview-card {
width: 72px;
text-align: center;
position: relative;
}
.preview-doc {
@@ -460,6 +554,23 @@ export default {
border-radius: 8px;
background: linear-gradient(180deg, #f6f8fd 0%, #e7ecfa 100%);
border: 1px solid #d8dfef;
position: relative;
}
.preview-remove {
position: absolute;
top: -6px;
right: -6px;
width: 18px;
height: 18px;
border: 0;
border-radius: 50%;
background: #999fb8;
color: #fff;
font-size: 12px;
line-height: 18px;
cursor: pointer;
padding: 0;
}
.preview-name {
@@ -495,6 +606,11 @@ export default {
color: #1E293B;
}
::v-deep .el-dialog__body{
padding: 0px 32px;
padding-bottom: 37px;
}
@media (max-width: 760px) {
.toolbar,
.search-group,