235 lines
7.2 KiB
Vue
235 lines
7.2 KiB
Vue
<template>
|
|
<el-dialog :title="title" :visible.sync="dialogFormVisible" width="700px" @close="close">
|
|
<el-form ref="form" label-width="100px" :model="form" :rules="rules">
|
|
<el-form-item label="话题标题" prop="title">
|
|
<el-input v-model="form.title" placeholder="请输入话题标题" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="话题分类" prop="categoryId">
|
|
<el-select
|
|
v-model="form.categoryId"
|
|
v-loadmore="loadMoreCategories"
|
|
filterable
|
|
placeholder="请选择话题分类"
|
|
:popper-append-to-body="false"
|
|
style="width: 100%"
|
|
>
|
|
<el-option v-for="item in categoryList" :key="item.id" :label="item.title" :value="item.id" />
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="评价项" required>
|
|
<div class="participants-container">
|
|
<div v-for="(item, index) in form.participants" :key="index" class="participant-item">
|
|
<div class="participant-avatar">
|
|
<single-upload v-model="item.avatar" style="width: 60px; height: 60px" :upload-url="uploadUrl" />
|
|
</div>
|
|
<div class="participant-name">
|
|
<el-input v-model="item.name" placeholder="请输入评价项名称" />
|
|
</div>
|
|
<div class="participant-action">
|
|
<el-button circle icon="el-icon-delete" type="danger" @click="removeParticipant(index)" />
|
|
</div>
|
|
</div>
|
|
<el-button icon="el-icon-plus" plain style="width: 100%; margin-top: 10px" @click="addParticipant">添加评价项</el-button>
|
|
</div>
|
|
</el-form-item>
|
|
</el-form>
|
|
<div slot="footer" class="dialog-footer">
|
|
<el-button @click="close">取 消</el-button>
|
|
<el-button :loading="saving" type="primary" @click="save">确 定</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script>
|
|
import { doAdd } from '@/api/rating/topic'
|
|
import { getList as getCategoryList } from '@/api/rating/topicCategory'
|
|
import SingleUpload from '@/components/SingleUpload'
|
|
|
|
export default {
|
|
name: 'TopicEdit',
|
|
components: { SingleUpload },
|
|
directives: {
|
|
loadmore: {
|
|
bind(el, binding) {
|
|
setTimeout(() => {
|
|
const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
|
|
if (SELECTWRAP_DOM) {
|
|
SELECTWRAP_DOM.addEventListener('scroll', function () {
|
|
const condition = this.scrollHeight - this.scrollTop <= this.clientHeight + 2
|
|
if (condition) {
|
|
binding.value()
|
|
}
|
|
})
|
|
}
|
|
}, 0)
|
|
},
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
title: '创建话题',
|
|
dialogFormVisible: false,
|
|
saving: false,
|
|
form: {
|
|
title: '',
|
|
categoryId: '',
|
|
participants: [{ name: '', avatar: '' }],
|
|
},
|
|
rules: {
|
|
title: [{ required: true, trigger: 'blur', message: '请输入话题标题' }],
|
|
categoryId: [{ required: true, trigger: 'change', message: '请选择话题分类' }],
|
|
},
|
|
categoryList: [],
|
|
categoryTotal: 0,
|
|
categoryQuery: {
|
|
pageNo: 1,
|
|
pageSize: 20,
|
|
},
|
|
fetchingCategories: false,
|
|
}
|
|
},
|
|
computed: {
|
|
uploadUrl() {
|
|
return `${process.env.VUE_APP_API_BASE_URL}/management/api/common/upload`
|
|
},
|
|
},
|
|
methods: {
|
|
showEdit() {
|
|
this.title = '创建话题'
|
|
this.form = this.$options.data().form
|
|
this.dialogFormVisible = true
|
|
this.fetchCategoryList(true)
|
|
},
|
|
close() {
|
|
this.$refs['form'].resetFields()
|
|
this.form = this.$options.data().form
|
|
this.dialogFormVisible = false
|
|
this.saving = false
|
|
},
|
|
async fetchCategoryList(refresh = false) {
|
|
if (refresh) {
|
|
this.categoryQuery.pageNo = 1
|
|
this.categoryList = []
|
|
}
|
|
this.fetchingCategories = true
|
|
try {
|
|
const { data } = await getCategoryList(this.categoryQuery)
|
|
if (refresh) {
|
|
this.categoryList = data.list || []
|
|
} else {
|
|
this.categoryList = this.categoryList.concat(data.list || [])
|
|
}
|
|
this.categoryTotal = data.totalCount || 0
|
|
} catch (error) {
|
|
console.error(error)
|
|
} finally {
|
|
this.fetchingCategories = false
|
|
}
|
|
},
|
|
loadMoreCategories() {
|
|
if (this.categoryList.length >= this.categoryTotal || this.fetchingCategories) {
|
|
return
|
|
}
|
|
this.categoryQuery.pageNo += 1
|
|
this.fetchCategoryList()
|
|
},
|
|
addParticipant() {
|
|
this.form.participants.push({ name: '', avatar: '' })
|
|
},
|
|
removeParticipant(index) {
|
|
this.form.participants.splice(index, 1)
|
|
},
|
|
save() {
|
|
this.$refs['form'].validate(async (valid) => {
|
|
if (valid) {
|
|
// 验证 participants
|
|
if (this.form.participants.length === 0) {
|
|
this.$message.error('请至少添加一个评价项')
|
|
return
|
|
}
|
|
for (let i = 0; i < this.form.participants.length; i++) {
|
|
const p = this.form.participants[i]
|
|
if (!p.name) {
|
|
this.$message.error(`第 ${i + 1} 个评价项名称不能为空`)
|
|
return
|
|
}
|
|
}
|
|
|
|
// 处理提交数据:去掉 avatar 的域名前缀
|
|
const submitData = {
|
|
...this.form,
|
|
participants: this.form.participants.map((p) => {
|
|
let avatar = p.avatar || ''
|
|
if (avatar.startsWith('https://file.lihailezzc.com/')) {
|
|
avatar = avatar.replace('https://file.lihailezzc.com/', '')
|
|
}
|
|
return {
|
|
...p,
|
|
avatar,
|
|
}
|
|
}),
|
|
}
|
|
|
|
this.saving = true
|
|
try {
|
|
const { msg } = await doAdd(submitData)
|
|
this.$baseMessage(msg || '创建成功', 'success')
|
|
this.$emit('fetch-data')
|
|
this.close()
|
|
} catch (error) {
|
|
console.error(error)
|
|
} finally {
|
|
this.saving = false
|
|
}
|
|
} else {
|
|
return false
|
|
}
|
|
})
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.participants-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
}
|
|
.participant-item {
|
|
display: flex;
|
|
align-items: center;
|
|
background-color: #f5f7fa;
|
|
padding: 10px;
|
|
border-radius: 4px;
|
|
gap: 15px;
|
|
height: 80px; /* 固定高度确保内容居中对齐 */
|
|
}
|
|
.participant-avatar {
|
|
flex-shrink: 0;
|
|
width: 60px;
|
|
height: 60px;
|
|
overflow: hidden;
|
|
border-radius: 4px;
|
|
}
|
|
/* 深度覆盖 SingleUpload 的默认宽高 */
|
|
::v-deep .participant-avatar .single-upload .uploader-icon,
|
|
::v-deep .participant-avatar .single-upload .avatar {
|
|
width: 60px !important;
|
|
height: 60px !important;
|
|
line-height: 60px !important;
|
|
}
|
|
.participant-name {
|
|
flex-grow: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.participant-action {
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
</style>
|