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