fix: rating

This commit is contained in:
zzc
2026-06-08 23:07:09 +08:00
parent 0dc2c2f0c3
commit ffbd355393
4 changed files with 265 additions and 1 deletions

View File

@@ -0,0 +1,234 @@
<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>