You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

589 lines
20 KiB

4 months ago
<template>
<div class="container">
<!-- 顶部信息 -->
<div class="containertop">
<div class="topleft">
<img src="../../../assets/images/detailsicon/1.png" alt="">
<span>项目巡礼</span>
</div>
2 months ago
<div class="topright" v-if="action === 'fill' || !action || action === 'okay'">
4 months ago
<el-button type="primary" size="medium" plain
3 months ago
style="border: none;background-color: rgba(43,98,241,0.1);color: #2B62F1;" @click="openAddDialog">
<img src="../../../assets/images/detailsicon/icon-xz@2x.png" alt="新增"
style="width: 0.6rem; height: 0.6rem; margin-right: 4px;">
新增
</el-button>
4 months ago
</div>
</div>
3 months ago
<!-- 展示区域 -->
<div class="image-container">
3 months ago
<div v-for="(item, index) in projectList" :key="index" class="image-box">
2 months ago
<img :src="baseUrl + item.img" alt="项目图片" class="image">
4 months ago
<div class="close-button" @click="removeImage(index)">
<img src="../../../assets/images/detailsicon/icon-关闭@2x.png" alt="">
</div>
3 months ago
<div class="iconguanbi2" @click="openEditDialog(item)"> <img
src="../../../assets/images/detailsicon/icon-bj@2x.png" alt=""></div>
<div class="dianjibox" @click="handleItemClick(item)"></div>
3 months ago
<div class="bottombox">
3 months ago
<div class="bottomtext"><span>{{ item.xmmc || '未命名项目' }}</span></div>
2 months ago
<div class="bottomtime"><span>{{ item.sj }}</span></div>
3 months ago
</div>
</div>
</div>
3 months ago
<div v-if="projectList.length === 0" class="no-data"
style="width: 100%; display: flex;align-items: center;justify-content: center;color: gray;">
暂无数据
</div>
3 months ago
<!-- 新增弹窗 -->
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="50%">
<el-form :model="form" :rules="rules" ref="projectForm" label-width="100px">
3 months ago
<el-row>
<el-col :span="12">
3 months ago
<el-form-item label="项目名称" prop="xmmc">
3 months ago
<el-input v-model="form.xmmc" placeholder="请输入项目名称"></el-input>
3 months ago
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="年度">
3 months ago
<el-date-picker v-model="form.year" type="year" value-format="yyyy" placeholder="选择年度"
@change="handleYearChange" style="width: 100%;" />
3 months ago
</el-form-item>
</el-col>
</el-row>
3 months ago
<el-row>
<el-col :span="12">
<el-form-item label="网页地址">
<el-input placeholder="选择地址" v-model="form.webUrl" class="input-with-select">
<template slot="prepend">
<el-select v-model="select" style="width: 5.7rem;" @change="handleProtocolChange">
<el-option label="http" value="http"></el-option>
<el-option label="https" value="https"></el-option>
</el-select>
<span class="wangzhispan">://</span>
</template>
</el-input>
3 months ago
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="时间">
<el-date-picker v-model="form.sj" type="date" value-format="yyyy-MM-dd" placeholder="选择日期" style="width: 100%;">
3 months ago
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="图片上传" prop="img">
<ImageUpload v-model="form.img" :file-list="fileList" :multiple="false" :limit="1"
@change="handleImageChange" />
3 months ago
</el-form-item>
<el-form-item label="说明">
3 months ago
<el-input v-model="form.content" type="textarea" :rows="4" placeholder="请输入说明"></el-input>
3 months ago
</el-form-item>
<el-form-item label="大事记">
3 months ago
<el-input v-model="form.bigEvent" type="textarea" :rows="4" placeholder="请输入大事记"></el-input>
3 months ago
</el-form-item>
<el-form-item label="新闻事件">
3 months ago
<el-input v-model="form.newsEvent" type="textarea" :rows="4" placeholder="请输入新闻事件"></el-input>
3 months ago
</el-form-item>
<el-form-item label="附件上传">
2 months ago
<FileUpload @file-uploaded="handleFileUploaded" v-model="form.fj" />
3 months ago
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
3 months ago
<el-button type="primary" @click="submitForm" :loading="loading">{{ isEditMode ? '保存' : '确 定'
}}</el-button>
3 months ago
</span>
</el-dialog>
<!-- 新增详情弹窗 -->
<el-dialog title="项目详情" :visible.sync="detailVisible" width="50%">
<el-form :model="currentItem" label-width="100px" :disabled="true">
<el-row>
<el-col :span="12">
<el-form-item label="项目名称">
<el-input v-model="currentItem.xmmc"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="年度">
<el-input v-model="currentItem.year"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="网页地址">
<el-input v-model="currentItem.webUrl"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="时间">
<el-input v-model="currentItem.sj"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="项目图片">
2 months ago
<img :src="baseUrl + currentItem.img" style="max-width: 100%; max-height: 200px;" v-if="currentItem.img">
3 months ago
<span v-else></span>
</el-form-item>
<el-form-item label="说明">
<el-input v-model="currentItem.content" type="textarea" :rows="4"></el-input>
</el-form-item>
<el-form-item label="大事记">
<el-input v-model="currentItem.bigEvent" type="textarea" :rows="4"></el-input>
</el-form-item>
<el-form-item label="新闻事件">
<el-input v-model="currentItem.newsEvent" type="textarea" :rows="4"></el-input>
</el-form-item>
2 months ago
<el-form-item label="附件">
<el-input v-model="fjFileName" :disabled="true"></el-input>
</el-form-item>
3 months ago
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="detailVisible = false"> </el-button>
</span>
</el-dialog>
4 months ago
</div>
</template>
<script>
3 months ago
import ImageUpload from '@/components/ImageUpload';
import fileUpload from '@/components/FileUpload';
import { addXmxl, getXmxlList, deleteXmxl, updataXmxl } from '@/api/ManageApi/index';
export default {
3 months ago
components: { ImageUpload, fileUpload },
props: {
xmId: {
type: Number,
required: true,
default: 0
},
action: {
type: String,
required: true
}
},
data() {
return {
2 months ago
baseUrl: process.env.VUE_APP_BASE_API,
3 months ago
detailVisible: false,
currentItem: {},
dialogVisible: false,
3 months ago
isEditMode: false,
loading: false,
currentEditId: null,
projectList: [],
3 months ago
fileList: [],
form: {
3 months ago
bigEvent: "",
content: "",
fj: "",
img: "",
newsEvent: "",
sj: "",
webUrl: "",
xmmc: "",
year: ""
},
rules: {
xmmc: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
year: [{ required: true, message: '请选择年度', trigger: 'change' }],
img: [{ required: true, message: '请上传项目图片', trigger: 'change' }]
},
select: 'http' // 默认协议类型
3 months ago
}
},
computed: {
dialogTitle() {
return this.isEditMode ? '编辑项目巡礼' : '新增项目巡礼';
2 months ago
},
fjFileName() {
return this.currentItem.fj ? this.currentItem.fj.split('/').pop() : '无附件';
}
},
created() {
3 months ago
this.fetchProjectList();
},
methods: {
2 months ago
3 months ago
// 处理项目点击
handleItemClick(item) {
// 阻止事件冒泡,避免触发父元素的点击事件
// 检查点击的是否是操作按钮
const isActionButton = event.target.closest('.close-button') ||
event.target.closest('.iconguanbi2');
if (isActionButton) {
return; // 如果是操作按钮,不处理主区域点击
}
if (item.webUrl) {
// 有网址则在新标签页打开
window.open(item.webUrl, '_blank');
} else {
// 无网址则显示详情弹窗
this.currentItem = { ...item };
this.detailVisible = true;
}
},
// 获取项目巡礼列表
fetchProjectList() {
getXmxlList({ xmId: this.xmId })
.then(response => {
if (response.code === 200) {
this.projectList = response.data || [];
} else {
this.$message.error(response.msg || '获取数据失败');
}
})
},
// 删除项目
3 months ago
async removeImage(index, event) {
try {
3 months ago
await this.$confirm('确定要删除该项目巡礼吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
const item = this.projectList[index];
const response = await deleteXmxl([item.id]);
if (response.code === 200) {
this.$message.success('删除成功');
this.projectList.splice(index, 1);
this.$emit('deleted', item.id);
} else {
throw new Error(response.msg || '删除失败');
}
} catch (error) {
3 months ago
if (error !== 'cancel') {
this.$message.error(error.message || '删除失败');
}
}
},
2 months ago
// 处理文件上传结果
handleFileUploaded(fileName) {
this.form.fj = `${this.baseUrl}/${fileName}`; // 添加 baseURL 前缀
},
3 months ago
// 打开新增对话框
openAddDialog() {
this.isEditMode = false;
this.currentEditId = null;
this.resetForm();
this.dialogVisible = true;
},
3 months ago
// 打开编辑对话框
openEditDialog(item) {
this.isEditMode = true;
this.currentEditId = item.id;
this.dialogVisible = true;
// 填充表单数据
this.form = {
bigEvent: item.bigEvent || "",
content: item.content || "",
fj: item.fj || "",
img: item.img || "",
newsEvent: item.newsEvent || "",
sj: item.sj || "",
webUrl: item.webUrl || "",
xmmc: item.xmmc || "",
year: item.year ? item.year.substring(0, 4) : "" // 只取年份部分
};
// 设置图片
this.fileList = item.img ? [{ url: item.img }] : [];
// 设置协议类型
if (item.webUrl) {
if (item.webUrl.startsWith('https://')) {
this.select = 'https';
} else if (item.webUrl.startsWith('http://')) {
this.select = 'http';
} else {
this.select = 'http';
this.form.webUrl = 'http://' + item.webUrl;
}
} else {
this.select = 'http';
}
3 months ago
},
3 months ago
// 处理年份选择
handleYearChange(year) {
if (year) {
const today = new Date();
const currentMonth = String(today.getMonth() + 1).padStart(2, '0');
const currentDay = String(today.getDate()).padStart(2, '0');
this.form.year = `${year}-${currentMonth}-${currentDay}`;
}
},
3 months ago
// 处理协议类型变化
handleProtocolChange() {
if (this.form.webUrl && !this.form.webUrl.startsWith(this.select + '://')) {
this.form.webUrl = this.select + '://' + this.form.webUrl.replace(/^(https?:\/\/)?/, '');
}
},
3 months ago
// 重置表单
resetForm() {
this.$refs.projectForm?.resetFields();
this.form = {
bigEvent: "",
content: "",
fj: "",
img: "",
newsEvent: "",
sj: "",
webUrl: "",
xmmc: "",
year: ""
};
this.fileList = [];
this.select = 'http'; // 重置协议类型
},
3 months ago
// 图片上传处理
handleImageChange(file) {
this.form.img = file.url;
},
3 months ago
// 提交表单
submitForm() {
this.$refs.projectForm.validate(valid => {
if (valid) {
this.loading = true;
if (this.isEditMode) {
this.handleEditXmxl();
} else {
this.handleAddXmxl();
}
}
});
},
3 months ago
// 处理新增请求
handleAddXmxl() {
const submitData = {
...this.form,
xmId: this.xmId,
id: 0,
2 months ago
fj: "",
3 months ago
createTime: "",
createBy: "",
createId: 0,
updateTime: "",
updateBy: "",
updateId: 0,
};
addXmxl(submitData)
.then(response => {
if (response.code === 200) {
this.$message.success('新增成功');
this.dialogVisible = false;
this.fetchProjectList();
} else {
this.$message.error(response.msg || '新增失败');
}
})
.catch(error => {
this.$message.error('请求失败');
console.error(error);
})
.finally(() => {
this.loading = false;
});
},
3 months ago
// 处理编辑请求
handleEditXmxl() {
const submitData = {
...this.form,
id: this.currentEditId,
xmId: this.xmId
3 months ago
};
3 months ago
updataXmxl(submitData)
.then(response => {
if (response.code === 200) {
this.$message.success('编辑成功');
this.dialogVisible = false;
this.fetchProjectList();
} else {
this.$message.error(response.msg || '编辑失败');
}
})
.catch(error => {
this.$message.error('请求失败');
console.error(error);
})
.finally(() => {
this.loading = false;
});
},
3 months ago
// 格式化日期显示
formatDate(date) {
if (!date) return '';
return new Date(date).toLocaleDateString();
}
},
watch: {
xmId(newVal) {
if (newVal) {
this.fetchProjectList();
}
}
}
3 months ago
}
4 months ago
</script>
<style scoped>
.container {
display: flex;
flex-direction: column;
width: 100%;
background-color: #FFFFFF;
box-shadow: 0rem 0.13rem 0.63rem 0rem rgba(177, 177, 177, 0.1);
4 months ago
border-radius: 0.5rem 0.5rem 0.5rem 0.5rem;
2 months ago
padding: .3rem 0 1rem 0;
4 months ago
gap: 1rem;
overflow: auto;
4 months ago
}
.containertop {
4 months ago
height: auto;
display: flex;
justify-content: space-between;
padding: .5rem;
border-bottom: 1px solid #E5E5E5;
4 months ago
}
.topleft {
width: 8rem;
4 months ago
display: flex;
gap: 0.4rem;
align-items: center;
}
.topleft img {
4 months ago
width: 0.81rem;
height: 0.81rem;
}
.topleft span {
4 months ago
width: auto;
2 months ago
height: 1rem;
font-family: aliregular;
4 months ago
font-weight: 500;
2 months ago
font-size: 1rem;
4 months ago
color: #3D424C;
2 months ago
line-height: 1rem;
4 months ago
text-align: right;
font-style: normal;
text-transform: none;
}
.image-container {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
padding: .5rem 1rem;
}
.image-box {
position: relative;
width: 21.75rem;
height: 12.44rem;
background-color: #f0f0f0;
border-radius: 0.5rem;
overflow: hidden;
}
.image {
width: 100%;
height: 100%;
object-fit: cover;
}
.close-button {
width: 1.25rem;
height: 1.25rem;
position: absolute;
top: 0.2rem;
right: 0.2rem;
}
4 months ago
.close-button img {
width: 100%;
height: 100%;
object-fit: cover;
}
3 months ago
.bottombox {
display: flex;
justify-content: space-between;
align-items: center;
position: absolute;
bottom: .5rem;
padding: .2rem;
width: 97%;
}
.bottomtext {
font-family: AlibabaPuHuiTi, AlibabaPuHuiTi;
font-weight: 500;
font-size: 1.13rem;
3 months ago
color: black;
3 months ago
line-height: 1.56rem;
text-align: left;
font-style: normal;
text-transform: none;
}
.bottomtime {
font-family: AlibabaPuHuiTi, AlibabaPuHuiTi;
font-weight: 400;
font-size: 0.75rem;
3 months ago
color: black;
3 months ago
line-height: 1rem;
text-align: left;
font-style: normal;
text-transform: none;
}
3 months ago
.iconguanbi2 {
position: absolute;
top: 1rem;
right: 1rem;
width: 2rem;
height: 2rem;
background-color: rgba(43, 98, 241, 0.1);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.iconguanbi2 img {
width: 1.2rem;
height: 1.2rem;
}
3 months ago
.dianjibox {
3 months ago
width: 18rem;
height: 11rem;
/* background-color: red; */
position: absolute;
bottom: 0rem;
}
</style>