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
589 lines
20 KiB
<template>
|
|
<div class="container">
|
|
<!-- 顶部信息 -->
|
|
<div class="containertop">
|
|
<div class="topleft">
|
|
<img src="../../../assets/images/detailsicon/1.png" alt="">
|
|
<span>项目巡礼</span>
|
|
</div>
|
|
<div class="topright" v-if="action === 'fill' || !action || action === 'okay'">
|
|
<el-button type="primary" size="medium" plain
|
|
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>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 展示区域 -->
|
|
<div class="image-container">
|
|
<div v-for="(item, index) in projectList" :key="index" class="image-box">
|
|
<img :src="baseUrl + item.img" alt="项目图片" class="image">
|
|
<div class="close-button" @click="removeImage(index)">
|
|
<img src="../../../assets/images/detailsicon/icon-关闭@2x.png" alt="">
|
|
</div>
|
|
<div class="iconguanbi2" @click="openEditDialog(item)"> <img
|
|
src="../../../assets/images/detailsicon/icon-bj@2x.png" alt=""></div>
|
|
<div class="dianjibox" @click="handleItemClick(item)"></div>
|
|
<div class="bottombox">
|
|
<div class="bottomtext"><span>{{ item.xmmc || '未命名项目' }}</span></div>
|
|
<div class="bottomtime"><span>{{ item.sj }}</span></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-if="projectList.length === 0" class="no-data"
|
|
style="width: 100%; display: flex;align-items: center;justify-content: center;color: gray;">
|
|
暂无数据
|
|
</div>
|
|
|
|
<!-- 新增弹窗 -->
|
|
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="50%">
|
|
<el-form :model="form" :rules="rules" ref="projectForm" label-width="100px">
|
|
<el-row>
|
|
<el-col :span="12">
|
|
<el-form-item label="项目名称" prop="xmmc">
|
|
<el-input v-model="form.xmmc" placeholder="请输入项目名称"></el-input>
|
|
</el-form-item>
|
|
</el-col>
|
|
<el-col :span="12">
|
|
<el-form-item label="年度">
|
|
<el-date-picker v-model="form.year" type="year" value-format="yyyy" placeholder="选择年度"
|
|
@change="handleYearChange" style="width: 100%;" />
|
|
</el-form-item>
|
|
</el-col>
|
|
</el-row>
|
|
<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>
|
|
</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%;">
|
|
</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" />
|
|
</el-form-item>
|
|
<el-form-item label="说明">
|
|
<el-input v-model="form.content" type="textarea" :rows="4" placeholder="请输入说明"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="大事记">
|
|
<el-input v-model="form.bigEvent" type="textarea" :rows="4" placeholder="请输入大事记"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="新闻事件">
|
|
<el-input v-model="form.newsEvent" type="textarea" :rows="4" placeholder="请输入新闻事件"></el-input>
|
|
</el-form-item>
|
|
<el-form-item label="附件上传">
|
|
<FileUpload @file-uploaded="handleFileUploaded" v-model="form.fj" />
|
|
</el-form-item>
|
|
</el-form>
|
|
<span slot="footer" class="dialog-footer">
|
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
|
<el-button type="primary" @click="submitForm" :loading="loading">{{ isEditMode ? '保存' : '确 定'
|
|
}}</el-button>
|
|
</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="项目图片">
|
|
<img :src="baseUrl + currentItem.img" style="max-width: 100%; max-height: 200px;" v-if="currentItem.img">
|
|
<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>
|
|
<el-form-item label="附件">
|
|
<el-input v-model="fjFileName" :disabled="true"></el-input>
|
|
</el-form-item>
|
|
</el-form>
|
|
<span slot="footer" class="dialog-footer">
|
|
<el-button type="primary" @click="detailVisible = false">关 闭</el-button>
|
|
</span>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import ImageUpload from '@/components/ImageUpload';
|
|
import fileUpload from '@/components/FileUpload';
|
|
import { addXmxl, getXmxlList, deleteXmxl, updataXmxl } from '@/api/ManageApi/index';
|
|
|
|
export default {
|
|
components: { ImageUpload, fileUpload },
|
|
props: {
|
|
xmId: {
|
|
type: Number,
|
|
required: true,
|
|
default: 0
|
|
},
|
|
action: {
|
|
type: String,
|
|
required: true
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
baseUrl: process.env.VUE_APP_BASE_API,
|
|
detailVisible: false,
|
|
currentItem: {},
|
|
dialogVisible: false,
|
|
isEditMode: false,
|
|
loading: false,
|
|
currentEditId: null,
|
|
projectList: [],
|
|
fileList: [],
|
|
form: {
|
|
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' // 默认协议类型
|
|
}
|
|
},
|
|
computed: {
|
|
dialogTitle() {
|
|
return this.isEditMode ? '编辑项目巡礼' : '新增项目巡礼';
|
|
},
|
|
fjFileName() {
|
|
return this.currentItem.fj ? this.currentItem.fj.split('/').pop() : '无附件';
|
|
}
|
|
},
|
|
created() {
|
|
this.fetchProjectList();
|
|
},
|
|
methods: {
|
|
|
|
// 处理项目点击
|
|
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 || '获取数据失败');
|
|
}
|
|
})
|
|
},
|
|
|
|
// 删除项目
|
|
async removeImage(index, event) {
|
|
try {
|
|
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) {
|
|
if (error !== 'cancel') {
|
|
this.$message.error(error.message || '删除失败');
|
|
}
|
|
}
|
|
},
|
|
// 处理文件上传结果
|
|
handleFileUploaded(fileName) {
|
|
this.form.fj = `${this.baseUrl}/${fileName}`; // 添加 baseURL 前缀
|
|
},
|
|
// 打开新增对话框
|
|
openAddDialog() {
|
|
this.isEditMode = false;
|
|
this.currentEditId = null;
|
|
this.resetForm();
|
|
this.dialogVisible = true;
|
|
},
|
|
|
|
// 打开编辑对话框
|
|
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';
|
|
}
|
|
},
|
|
|
|
// 处理年份选择
|
|
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}`;
|
|
}
|
|
},
|
|
|
|
// 处理协议类型变化
|
|
handleProtocolChange() {
|
|
if (this.form.webUrl && !this.form.webUrl.startsWith(this.select + '://')) {
|
|
this.form.webUrl = this.select + '://' + this.form.webUrl.replace(/^(https?:\/\/)?/, '');
|
|
}
|
|
},
|
|
|
|
// 重置表单
|
|
resetForm() {
|
|
this.$refs.projectForm?.resetFields();
|
|
this.form = {
|
|
bigEvent: "",
|
|
content: "",
|
|
fj: "",
|
|
img: "",
|
|
newsEvent: "",
|
|
sj: "",
|
|
webUrl: "",
|
|
xmmc: "",
|
|
year: ""
|
|
};
|
|
this.fileList = [];
|
|
this.select = 'http'; // 重置协议类型
|
|
},
|
|
|
|
// 图片上传处理
|
|
handleImageChange(file) {
|
|
this.form.img = file.url;
|
|
},
|
|
|
|
// 提交表单
|
|
submitForm() {
|
|
this.$refs.projectForm.validate(valid => {
|
|
if (valid) {
|
|
this.loading = true;
|
|
if (this.isEditMode) {
|
|
this.handleEditXmxl();
|
|
} else {
|
|
this.handleAddXmxl();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
// 处理新增请求
|
|
handleAddXmxl() {
|
|
const submitData = {
|
|
...this.form,
|
|
xmId: this.xmId,
|
|
id: 0,
|
|
fj: "",
|
|
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;
|
|
});
|
|
},
|
|
|
|
// 处理编辑请求
|
|
handleEditXmxl() {
|
|
const submitData = {
|
|
...this.form,
|
|
id: this.currentEditId,
|
|
xmId: this.xmId
|
|
};
|
|
|
|
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;
|
|
});
|
|
},
|
|
|
|
// 格式化日期显示
|
|
formatDate(date) {
|
|
if (!date) return '';
|
|
return new Date(date).toLocaleDateString();
|
|
}
|
|
},
|
|
watch: {
|
|
xmId(newVal) {
|
|
if (newVal) {
|
|
this.fetchProjectList();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</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);
|
|
border-radius: 0.5rem 0.5rem 0.5rem 0.5rem;
|
|
padding: .3rem 0 1rem 0;
|
|
gap: 1rem;
|
|
overflow: auto;
|
|
}
|
|
|
|
.containertop {
|
|
height: auto;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
padding: .5rem;
|
|
border-bottom: 1px solid #E5E5E5;
|
|
}
|
|
|
|
.topleft {
|
|
width: 8rem;
|
|
display: flex;
|
|
gap: 0.4rem;
|
|
align-items: center;
|
|
}
|
|
|
|
.topleft img {
|
|
width: 0.81rem;
|
|
height: 0.81rem;
|
|
}
|
|
|
|
.topleft span {
|
|
width: auto;
|
|
height: 1rem;
|
|
font-family: aliregular;
|
|
font-weight: 500;
|
|
font-size: 1rem;
|
|
color: #3D424C;
|
|
line-height: 1rem;
|
|
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;
|
|
}
|
|
|
|
.close-button img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.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;
|
|
color: black;
|
|
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;
|
|
color: black;
|
|
line-height: 1rem;
|
|
text-align: left;
|
|
font-style: normal;
|
|
text-transform: none;
|
|
}
|
|
|
|
.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;
|
|
}
|
|
|
|
.dianjibox {
|
|
width: 18rem;
|
|
height: 11rem;
|
|
/* background-color: red; */
|
|
position: absolute;
|
|
bottom: 0rem;
|
|
}
|
|
</style> |