|
|
|
|
<template>
|
|
|
|
|
<div>
|
|
|
|
|
<!-- 项目手册管理 -->
|
|
|
|
|
<!-- 表单查询项 -->
|
|
|
|
|
<div v-if="!previewMode" class="headerbox">
|
|
|
|
|
<div class="search-form">
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<span class="label">手册名称</span>
|
|
|
|
|
<el-input
|
|
|
|
|
v-model="queryParams.title"
|
|
|
|
|
placeholder="请输入模板标题"
|
|
|
|
|
clearable
|
|
|
|
|
class="search-input"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-item">
|
|
|
|
|
<span class="label">创建时间</span>
|
|
|
|
|
<el-date-picker
|
|
|
|
|
v-model="queryParams.startTime"
|
|
|
|
|
type="date"
|
|
|
|
|
placeholder="选择日期"
|
|
|
|
|
class="search-date"
|
|
|
|
|
></el-date-picker>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-item btn-group">
|
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
icon="el-icon-search"
|
|
|
|
|
@click="handleQuery"
|
|
|
|
|
>查询</el-button>
|
|
|
|
|
<el-button icon="el-icon-refresh" @click="resetQuery"
|
|
|
|
|
>重置</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 表格内容区 -->
|
|
|
|
|
<div v-if="!previewMode" class="tablebox">
|
|
|
|
|
<div class="tablebtntwo">
|
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
icon="el-icon-plus"
|
|
|
|
|
size="mini"
|
|
|
|
|
@click="handleAdd"
|
|
|
|
|
>项目手册导出</el-button
|
|
|
|
|
>
|
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
icon="el-icon-plus"
|
|
|
|
|
size="mini"
|
|
|
|
|
@click="handleAdd"
|
|
|
|
|
>新增</el-button
|
|
|
|
|
>
|
|
|
|
|
</div>
|
|
|
|
|
<el-table
|
|
|
|
|
v-loading="loading"
|
|
|
|
|
:data="postList"
|
|
|
|
|
@selection-change="handleSelectionChange"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column type="selection" width="55" align="center" />
|
|
|
|
|
<el-table-column label="序号" align="center" prop="id" />
|
|
|
|
|
<el-table-column label="手册名称" align="center" prop="title" />
|
|
|
|
|
<!-- <el-table-column label="发布单位" align="center" prop="unit" /> -->
|
|
|
|
|
<!-- <el-table-column label="发布人" align="center" prop="author" /> -->
|
|
|
|
|
<el-table-column label="创建时间" align="center" prop="createTime" />
|
|
|
|
|
<el-table-column label="操作" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<el-button
|
|
|
|
|
size="mini"
|
|
|
|
|
type="text"
|
|
|
|
|
style="color: gray"
|
|
|
|
|
@click="handlePreview(scope.row)"
|
|
|
|
|
>预览</el-button
|
|
|
|
|
>
|
|
|
|
|
<el-button
|
|
|
|
|
size="mini"
|
|
|
|
|
type="text"
|
|
|
|
|
style="color: #67c23a"
|
|
|
|
|
@click="handleEdit(scope.row)"
|
|
|
|
|
>编辑</el-button
|
|
|
|
|
>
|
|
|
|
|
<el-button
|
|
|
|
|
size="mini"
|
|
|
|
|
type="text"
|
|
|
|
|
style="color: #f56c6c"
|
|
|
|
|
@click="handleDelete(scope.row)"
|
|
|
|
|
>删除</el-button
|
|
|
|
|
>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
<pagination
|
|
|
|
|
v-show="total > 0"
|
|
|
|
|
:total="total"
|
|
|
|
|
:page.sync="queryParams.current"
|
|
|
|
|
:limit.sync="queryParams.size"
|
|
|
|
|
@pagination="getList"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- DOCX预览区域 -->
|
|
|
|
|
<div v-if="previewMode" class="previewbox">
|
|
|
|
|
<div class="previewhead">
|
|
|
|
|
<h3>{{ previewData.title }}</h3>
|
|
|
|
|
<div class="headtwo">
|
|
|
|
|
<el-button size="mini" @click="previewMode = false">返回</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="previewcontent">
|
|
|
|
|
<vue-office-docx
|
|
|
|
|
:src="docxFileData"
|
|
|
|
|
style="
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: calc(100vh - 250px);
|
|
|
|
|
border: 1px solid #eee;
|
|
|
|
|
"
|
|
|
|
|
@rendered="renderedHandler"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 创建新手册弹框 -->
|
|
|
|
|
<el-dialog
|
|
|
|
|
title="创建新手册"
|
|
|
|
|
:visible.sync="addDialogVisible"
|
|
|
|
|
width="70%"
|
|
|
|
|
:close-on-click-modal="false"
|
|
|
|
|
:show-close="true"
|
|
|
|
|
:before-close="handleAddDialogClose"
|
|
|
|
|
class="handbook-dialog"
|
|
|
|
|
>
|
|
|
|
|
<div class="step-container">
|
|
|
|
|
<el-steps :active="activeStep" align-center finish-status="finish ">
|
|
|
|
|
<el-step title="封面设置"></el-step>
|
|
|
|
|
<el-step title="选择项目"></el-step>
|
|
|
|
|
<el-step title="封尾设计"></el-step>
|
|
|
|
|
</el-steps>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 步骤1:封面设置 -->
|
|
|
|
|
<div v-if="activeStep === 1" class="step-content">
|
|
|
|
|
<div class="cover-form">
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<div class="form-col">
|
|
|
|
|
<label class="form-label">手册名称</label>
|
|
|
|
|
<el-input v-model="coverForm.title" placeholder="请输入"></el-input>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-col">
|
|
|
|
|
<label class="form-label">副标题</label>
|
|
|
|
|
<el-input v-model="coverForm.subtitle" placeholder="请输入"></el-input>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<div class="form-col-full">
|
|
|
|
|
<label class="form-label">封面图片</label>
|
|
|
|
|
<div class="upload-area">
|
|
|
|
|
<img
|
|
|
|
|
v-if="coverForm.imageUrl"
|
|
|
|
|
:src="coverForm.imageUrl"
|
|
|
|
|
class="preview-image"
|
|
|
|
|
@click="triggerUpload"
|
|
|
|
|
/>
|
|
|
|
|
<div v-else @click="triggerUpload" class="upload-box">
|
|
|
|
|
<i class="el-icon-upload upload-icon"></i>
|
|
|
|
|
<div class="upload-text">
|
|
|
|
|
上传图片 或拖拽到此处
|
|
|
|
|
<p class="upload-tip">PNG, JPG, GIF 最大 10MB</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 步骤2:选择项目 -->
|
|
|
|
|
<div v-if="activeStep === 2" class="step-content project-step">
|
|
|
|
|
<div class="cover-form">
|
|
|
|
|
<div class="project-top">
|
|
|
|
|
<div class="search-container">
|
|
|
|
|
<div class="search-label">项目名称:</div>
|
|
|
|
|
<el-input
|
|
|
|
|
v-model="projectSearch"
|
|
|
|
|
placeholder="请输入"
|
|
|
|
|
class="search-input"
|
|
|
|
|
></el-input>
|
|
|
|
|
<el-button type="primary" @click="searchProjects" class="search-btn">查询</el-button>
|
|
|
|
|
<el-button @click="resetProjectSearch" class="search-btn">重置</el-button>
|
|
|
|
|
<el-button type="primary" @click="confirmSelection" class="search-btn">确认勾选</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="project-table">
|
|
|
|
|
<el-table
|
|
|
|
|
ref="projectTable"
|
|
|
|
|
:data="projectList"
|
|
|
|
|
@selection-change="handleProjectSelectionChange"
|
|
|
|
|
@row-click="handleRowClick"
|
|
|
|
|
border
|
|
|
|
|
>
|
|
|
|
|
<el-table-column
|
|
|
|
|
type="selection"
|
|
|
|
|
width="55"
|
|
|
|
|
align="center"
|
|
|
|
|
></el-table-column>
|
|
|
|
|
<el-table-column label="序号" width="60" align="center">
|
|
|
|
|
<template slot-scope="scope">{{ scope.$index + 1 }}</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column
|
|
|
|
|
prop="name"
|
|
|
|
|
label="项目名称"
|
|
|
|
|
align="center"
|
|
|
|
|
></el-table-column>
|
|
|
|
|
<el-table-column
|
|
|
|
|
prop="status"
|
|
|
|
|
label="现状分类"
|
|
|
|
|
align="center"
|
|
|
|
|
></el-table-column>
|
|
|
|
|
<el-table-column
|
|
|
|
|
prop="company"
|
|
|
|
|
label="项目法人单位"
|
|
|
|
|
align="center"
|
|
|
|
|
></el-table-column>
|
|
|
|
|
<el-table-column
|
|
|
|
|
prop="buildTime"
|
|
|
|
|
label="项目建设起止时间"
|
|
|
|
|
align="center"
|
|
|
|
|
></el-table-column>
|
|
|
|
|
<el-table-column
|
|
|
|
|
prop="investment"
|
|
|
|
|
label="总投资额(万元)"
|
|
|
|
|
align="center"
|
|
|
|
|
></el-table-column>
|
|
|
|
|
<el-table-column
|
|
|
|
|
prop="area"
|
|
|
|
|
label="总用地面积(平方米)"
|
|
|
|
|
align="center"
|
|
|
|
|
></el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
|
|
|
|
|
<div class="pagination-box">
|
|
|
|
|
<pagination
|
|
|
|
|
v-show="projectTotal > 0"
|
|
|
|
|
:total="projectTotal"
|
|
|
|
|
:page.sync="projectParams.pageNum"
|
|
|
|
|
:limit.sync="projectParams.pageSize"
|
|
|
|
|
@pagination="handleProjectPagination"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="selected-projects-container" v-if="selectedProjects.length > 0">
|
|
|
|
|
<div class="selected-header">已选中项目</div>
|
|
|
|
|
<div class="selected-list">
|
|
|
|
|
<div
|
|
|
|
|
v-for="(project, index) in selectedProjects"
|
|
|
|
|
:key="index"
|
|
|
|
|
class="selected-item"
|
|
|
|
|
@click="removeSelectedProject(project)"
|
|
|
|
|
>
|
|
|
|
|
<div class="dot-indicator"></div>
|
|
|
|
|
<span class="project-name">{{ project.name }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 步骤3:封尾设计 -->
|
|
|
|
|
<div v-if="activeStep === 3" class="step-content">
|
|
|
|
|
<div class="cover-form">
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<div class="form-col-full">
|
|
|
|
|
<label class="form-label">封尾图片</label>
|
|
|
|
|
<div class="upload-area">
|
|
|
|
|
<img
|
|
|
|
|
v-if="endForm.imageUrl"
|
|
|
|
|
:src="endForm.imageUrl"
|
|
|
|
|
class="preview-image"
|
|
|
|
|
@click="triggerEndUpload"
|
|
|
|
|
/>
|
|
|
|
|
<div v-else @click="triggerEndUpload" class="upload-box">
|
|
|
|
|
<i class="el-icon-upload upload-icon"></i>
|
|
|
|
|
<div class="upload-text">
|
|
|
|
|
上传图片 或拖拽到此处
|
|
|
|
|
<p class="upload-tip">PNG, JPG, GIF 最大 10MB</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="form-row">
|
|
|
|
|
<div class="form-col">
|
|
|
|
|
<label class="form-label">副标题</label>
|
|
|
|
|
<el-input v-model="endForm.subtitle" placeholder="请输入" style="width: 60%;"></el-input>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
|
|
|
<el-button @click="prevStep" v-if="activeStep > 1" size="small"
|
|
|
|
|
>上一步</el-button
|
|
|
|
|
>
|
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
class="btn-next"
|
|
|
|
|
@click="nextStep"
|
|
|
|
|
v-if="activeStep < 3"
|
|
|
|
|
size="small"
|
|
|
|
|
>下一步</el-button
|
|
|
|
|
>
|
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
class="btn-next"
|
|
|
|
|
@click="submitHandbook"
|
|
|
|
|
v-if="activeStep === 3"
|
|
|
|
|
size="small"
|
|
|
|
|
>生成手册</el-button
|
|
|
|
|
>
|
|
|
|
|
</div>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import VueOfficeDocx from "@vue-office/docx";
|
|
|
|
|
import axios from "axios";
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
components: {
|
|
|
|
|
"vue-office-docx": VueOfficeDocx,
|
|
|
|
|
Pagination: () => import("@/components/Pagination"),
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
// 查询参数
|
|
|
|
|
queryParams: {
|
|
|
|
|
current: 1,
|
|
|
|
|
size: 10,
|
|
|
|
|
title: undefined,
|
|
|
|
|
startTime: undefined,
|
|
|
|
|
},
|
|
|
|
|
// 所有数据(模拟从后端获取)
|
|
|
|
|
allPostList: [
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
|
|
|
|
title: "xxxx项目单体材料模板",
|
|
|
|
|
unit: "经发委",
|
|
|
|
|
author: "",
|
|
|
|
|
createTime: "2024-08-20",
|
|
|
|
|
fileUrl: "docx/单体材料模板.docx",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
// 表格显示的数据
|
|
|
|
|
postList: [],
|
|
|
|
|
// 加载状态
|
|
|
|
|
loading: false,
|
|
|
|
|
// 总条数
|
|
|
|
|
total: 0,
|
|
|
|
|
// 预览模式
|
|
|
|
|
previewMode: false,
|
|
|
|
|
// 预览数据
|
|
|
|
|
previewData: {},
|
|
|
|
|
// DOCX文件数据
|
|
|
|
|
docxFileData: null,
|
|
|
|
|
|
|
|
|
|
// 新增手册弹框相关
|
|
|
|
|
addDialogVisible: false,
|
|
|
|
|
activeStep: 1,
|
|
|
|
|
|
|
|
|
|
// 封面表单
|
|
|
|
|
coverForm: {
|
|
|
|
|
title: "",
|
|
|
|
|
subtitle: "",
|
|
|
|
|
imageUrl: "",
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 项目选择相关
|
|
|
|
|
projectSearch: "",
|
|
|
|
|
projectList: [],
|
|
|
|
|
selectedProjects: [],
|
|
|
|
|
projectParams: {
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
},
|
|
|
|
|
projectTotal: 0,
|
|
|
|
|
|
|
|
|
|
// 封尾设计
|
|
|
|
|
endForm: {
|
|
|
|
|
imageUrl: "",
|
|
|
|
|
subtitle: "",
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
created() {
|
|
|
|
|
this.getList();
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
// 获取表格数据
|
|
|
|
|
getList() {
|
|
|
|
|
this.loading = true;
|
|
|
|
|
|
|
|
|
|
// 根据查询条件过滤数据
|
|
|
|
|
let filteredData = this.allPostList.filter((item) => {
|
|
|
|
|
if (
|
|
|
|
|
this.queryParams.title &&
|
|
|
|
|
!item.title.includes(this.queryParams.title)
|
|
|
|
|
) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
this.queryParams.startTime &&
|
|
|
|
|
new Date(item.createTime) < new Date(this.queryParams.startTime)
|
|
|
|
|
) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 分页处理
|
|
|
|
|
const start = (this.queryParams.current - 1) * this.queryParams.size;
|
|
|
|
|
const end = start + this.queryParams.size;
|
|
|
|
|
this.postList = filteredData.slice(start, end);
|
|
|
|
|
this.total = filteredData.length;
|
|
|
|
|
|
|
|
|
|
this.loading = false;
|
|
|
|
|
},
|
|
|
|
|
// 查询
|
|
|
|
|
handleQuery() {
|
|
|
|
|
this.queryParams.current = 1;
|
|
|
|
|
this.getList();
|
|
|
|
|
},
|
|
|
|
|
// 重置查询
|
|
|
|
|
resetQuery() {
|
|
|
|
|
this.queryParams = {
|
|
|
|
|
current: 1,
|
|
|
|
|
size: 10,
|
|
|
|
|
title: undefined,
|
|
|
|
|
startTime: undefined,
|
|
|
|
|
};
|
|
|
|
|
this.handleQuery();
|
|
|
|
|
},
|
|
|
|
|
// 表格选择变化
|
|
|
|
|
handleSelectionChange(selection) {
|
|
|
|
|
this.ids = selection.map((item) => item.id);
|
|
|
|
|
this.single = selection.length !== 1;
|
|
|
|
|
this.multiple = !selection.length;
|
|
|
|
|
},
|
|
|
|
|
// 预览文档
|
|
|
|
|
handlePreview(row) {
|
|
|
|
|
this.previewMode = true;
|
|
|
|
|
this.previewData = row;
|
|
|
|
|
this.loadDocxFile(row.fileUrl);
|
|
|
|
|
},
|
|
|
|
|
// 加载DOCX文件
|
|
|
|
|
loadDocxFile(url) {
|
|
|
|
|
this.docxFileData = null;
|
|
|
|
|
axios
|
|
|
|
|
.get(url, { responseType: "arraybuffer" })
|
|
|
|
|
.then((response) => {
|
|
|
|
|
this.docxFileData = response.data;
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
console.error("加载文档失败:", error);
|
|
|
|
|
this.$message.error("文档加载失败");
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
renderedHandler() {
|
|
|
|
|
console.log("文档渲染完成");
|
|
|
|
|
},
|
|
|
|
|
handleAdd() {
|
|
|
|
|
this.addDialogVisible = true;
|
|
|
|
|
this.activeStep = 1;
|
|
|
|
|
this.resetAddForm();
|
|
|
|
|
this.getProjectList();
|
|
|
|
|
},
|
|
|
|
|
handleAddDialogClose(done) {
|
|
|
|
|
// this.$confirm("确认关闭?未保存的数据将会丢失", "提示", {
|
|
|
|
|
// confirmButtonText: "确定",
|
|
|
|
|
// cancelButtonText: "取消",
|
|
|
|
|
// type: "warning",
|
|
|
|
|
// })
|
|
|
|
|
// .then(() => {
|
|
|
|
|
this.resetAddForm();
|
|
|
|
|
done();
|
|
|
|
|
// })
|
|
|
|
|
// .catch(() => {});
|
|
|
|
|
},
|
|
|
|
|
resetAddForm() {
|
|
|
|
|
this.coverForm = {
|
|
|
|
|
title: "",
|
|
|
|
|
subtitle: "",
|
|
|
|
|
imageUrl: "",
|
|
|
|
|
};
|
|
|
|
|
this.projectSearch = "";
|
|
|
|
|
this.selectedProjects = [];
|
|
|
|
|
this.endForm = {
|
|
|
|
|
imageUrl: "",
|
|
|
|
|
subtitle: "",
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
// 下一步
|
|
|
|
|
nextStep() {
|
|
|
|
|
if (this.activeStep === 1) {
|
|
|
|
|
// 可以添加表单验证
|
|
|
|
|
if (!this.coverForm.title) {
|
|
|
|
|
this.$message.warning("请输入手册名称");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.activeStep++;
|
|
|
|
|
},
|
|
|
|
|
// 上一步
|
|
|
|
|
prevStep() {
|
|
|
|
|
this.activeStep--;
|
|
|
|
|
},
|
|
|
|
|
// 上传前检查
|
|
|
|
|
beforeUpload(file) {
|
|
|
|
|
const isImage = file.type.indexOf("image/") !== -1;
|
|
|
|
|
const isLt10M = file.size / 1024 / 1024 < 10;
|
|
|
|
|
|
|
|
|
|
if (!isImage) {
|
|
|
|
|
this.$message.error("只能上传图片文件!");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isLt10M) {
|
|
|
|
|
this.$message.error("图片大小不能超过 10MB!");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
// 处理封尾上传
|
|
|
|
|
handleEndUpload(options) {
|
|
|
|
|
const file = options.file;
|
|
|
|
|
// 模拟上传过程
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
reader.readAsDataURL(file);
|
|
|
|
|
reader.onload = () => {
|
|
|
|
|
this.endForm.imageUrl = reader.result;
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
// 触发上传
|
|
|
|
|
triggerUpload() {
|
|
|
|
|
// 创建一个隐藏的文件输入
|
|
|
|
|
const input = document.createElement("input");
|
|
|
|
|
input.type = "file";
|
|
|
|
|
input.accept = "image/png, image/jpeg, image/gif";
|
|
|
|
|
input.onchange = (e) => {
|
|
|
|
|
const file = e.target.files[0];
|
|
|
|
|
if (file) {
|
|
|
|
|
this.beforeUpload(file) && this.handleManualUpload(file);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
input.click();
|
|
|
|
|
},
|
|
|
|
|
// 手动处理上传
|
|
|
|
|
handleManualUpload(file) {
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
reader.readAsDataURL(file);
|
|
|
|
|
reader.onload = () => {
|
|
|
|
|
this.coverForm.imageUrl = reader.result;
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
// 触发封尾图片上传
|
|
|
|
|
triggerEndUpload() {
|
|
|
|
|
const input = document.createElement("input");
|
|
|
|
|
input.type = "file";
|
|
|
|
|
input.accept = "image/png, image/jpeg, image/gif";
|
|
|
|
|
input.onchange = (e) => {
|
|
|
|
|
const file = e.target.files[0];
|
|
|
|
|
if (file) {
|
|
|
|
|
this.beforeUpload(file) && this.handleEndUpload({file});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
input.click();
|
|
|
|
|
},
|
|
|
|
|
// 获取项目列表
|
|
|
|
|
getProjectList() {
|
|
|
|
|
// 模拟后端数据
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.projectList = [
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
|
|
|
|
name: "大众电脑生产制造基地",
|
|
|
|
|
status: "已建",
|
|
|
|
|
company: "大众电脑(苏州)有限公司",
|
|
|
|
|
buildTime: "2004.12-2006.12",
|
|
|
|
|
investment: 20000,
|
|
|
|
|
area: 38533.33,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 2,
|
|
|
|
|
name: "THI SIP高端装备工业港",
|
|
|
|
|
status: "已建",
|
|
|
|
|
company: "泰和医药(中国)有限公司",
|
|
|
|
|
buildTime: "2005.03-2006.05",
|
|
|
|
|
investment: 35000,
|
|
|
|
|
area: 9655.9,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
this.projectTotal = 2;
|
|
|
|
|
}, 500);
|
|
|
|
|
},
|
|
|
|
|
// 搜索项目
|
|
|
|
|
searchProjects() {
|
|
|
|
|
this.projectParams.pageNum = 1;
|
|
|
|
|
this.getProjectList();
|
|
|
|
|
},
|
|
|
|
|
// 重置项目搜索
|
|
|
|
|
resetProjectSearch() {
|
|
|
|
|
this.projectSearch = "";
|
|
|
|
|
this.projectParams.pageNum = 1;
|
|
|
|
|
this.getProjectList();
|
|
|
|
|
},
|
|
|
|
|
// 确认勾选项目
|
|
|
|
|
confirmSelection() {
|
|
|
|
|
if (this.selectedProjects.length === 0) {
|
|
|
|
|
this.$message.warning("请至少选择一个项目");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.$message.success(`已选择 ${this.selectedProjects.length} 个项目`);
|
|
|
|
|
},
|
|
|
|
|
// 处理项目选择变化
|
|
|
|
|
handleProjectSelectionChange(selection) {
|
|
|
|
|
console.log(selection);
|
|
|
|
|
this.selectedProjects = selection;
|
|
|
|
|
},
|
|
|
|
|
// 移除已选项目
|
|
|
|
|
removeSelectedProject(project) {
|
|
|
|
|
// 从已选列表中移除
|
|
|
|
|
this.selectedProjects = this.selectedProjects.filter(
|
|
|
|
|
(item) => item.id !== project.id
|
|
|
|
|
);
|
|
|
|
|
// 取消表格中的选中状态
|
|
|
|
|
this.$refs.projectTable.toggleRowSelection(
|
|
|
|
|
this.projectList.find((item) => item.id === project.id),
|
|
|
|
|
false
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
// 项目分页变化处理
|
|
|
|
|
handleProjectPagination() {
|
|
|
|
|
this.getProjectList();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 处理行点击
|
|
|
|
|
handleRowClick(row) {
|
|
|
|
|
// 切换选中状态
|
|
|
|
|
this.$refs.projectTable.toggleRowSelection(row);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 项目分页大小变化
|
|
|
|
|
handleProjectSizeChange(size) {
|
|
|
|
|
this.projectParams.pageSize = size;
|
|
|
|
|
this.getProjectList();
|
|
|
|
|
},
|
|
|
|
|
// 项目分页页码变化
|
|
|
|
|
handleProjectCurrentChange(page) {
|
|
|
|
|
this.projectParams.pageNum = page;
|
|
|
|
|
this.getProjectList();
|
|
|
|
|
},
|
|
|
|
|
// 提交生成手册
|
|
|
|
|
submitHandbook() {
|
|
|
|
|
if (this.selectedProjects.length === 0) {
|
|
|
|
|
this.$message.warning("请至少选择一个项目");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 模拟提交数据
|
|
|
|
|
const data = {
|
|
|
|
|
cover: this.coverForm,
|
|
|
|
|
projects: this.selectedProjects,
|
|
|
|
|
end: this.endForm,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
console.log("提交的数据:", data);
|
|
|
|
|
|
|
|
|
|
// 模拟提交成功
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.$message.success("手册生成成功");
|
|
|
|
|
this.addDialogVisible = false;
|
|
|
|
|
this.getList();
|
|
|
|
|
}, 1000);
|
|
|
|
|
},
|
|
|
|
|
// 编辑按钮操作
|
|
|
|
|
handleEdit(row) {
|
|
|
|
|
// TODO: 实现编辑功能
|
|
|
|
|
this.$message.success("编辑功能待实现");
|
|
|
|
|
},
|
|
|
|
|
// 删除按钮操作
|
|
|
|
|
handleDelete(row) {
|
|
|
|
|
this.$confirm("是否确认删除该手册?", "警告", {
|
|
|
|
|
confirmButtonText: "确定",
|
|
|
|
|
cancelButtonText: "取消",
|
|
|
|
|
type: "warning",
|
|
|
|
|
})
|
|
|
|
|
.then(() => {
|
|
|
|
|
this.$message.success("删除成功");
|
|
|
|
|
this.getList();
|
|
|
|
|
})
|
|
|
|
|
.catch(() => {});
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.headerbox {
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
border-radius: 0.5rem;
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
margin: 0.5rem;
|
|
|
|
|
border: 1px solid #eee;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-form {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-item {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-right: 20px;
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.label {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #606266;
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-input, .search-date {
|
|
|
|
|
width: 220px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-group {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tablebox {
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
border-radius: 0.5rem;
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
margin: 0.5rem;
|
|
|
|
|
border: 1px solid #eee;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tablebtntwo {
|
|
|
|
|
width: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.previewbox {
|
|
|
|
|
width: 99%;
|
|
|
|
|
margin-left: 0.5%;
|
|
|
|
|
height: 92rem;
|
|
|
|
|
margin-top: 0.3rem;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
padding: 1rem;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.previewhead {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 2rem;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.headtwo {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.previewinfo {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 1rem;
|
|
|
|
|
justify-content: flex-start;
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.previewcontent {
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
.handbook-dialog {
|
|
|
|
|
::v-deep .el-dialog__header{
|
|
|
|
|
background-color: #1890ff;
|
|
|
|
|
.el-dialog__title{
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
::v-deep .el-dialog__headerbtn .el-dialog__close{
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
// ::v-deep .el-step__head.is-wait{
|
|
|
|
|
// border: #1890ff;
|
|
|
|
|
// }
|
|
|
|
|
::v-deep .el-step__icon {
|
|
|
|
|
width: 15px;
|
|
|
|
|
height: 15px;
|
|
|
|
|
font-size: 0;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
position: relative;
|
|
|
|
|
z-index: 2;
|
|
|
|
|
border: 2px solid rgb(255, 255, 255);
|
|
|
|
|
box-shadow: 0 0 0 2px rgba(136, 137, 137, 0.1);
|
|
|
|
|
// background-color: #1890ff!important;
|
|
|
|
|
}
|
|
|
|
|
::v-deep {
|
|
|
|
|
.is-process {
|
|
|
|
|
color: #c0c4cc !important;
|
|
|
|
|
font-weight: normal !important;
|
|
|
|
|
// ::-webkit-scrollbar-trackground-color: #1890ff !important;
|
|
|
|
|
.el-step__icon{
|
|
|
|
|
background: none!important;
|
|
|
|
|
background-color: #c0c4cc!important;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.is-finish .el-step__icon{
|
|
|
|
|
background: none!important;
|
|
|
|
|
background-color: #1890ff!important;
|
|
|
|
|
}
|
|
|
|
|
.is-wait .el-step__icon{
|
|
|
|
|
background: none!important;
|
|
|
|
|
background-color: #c0c4cc!important;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.form-label {
|
|
|
|
|
width: 70px;
|
|
|
|
|
text-align: right;
|
|
|
|
|
padding-right: 10px;
|
|
|
|
|
line-height: 32px;
|
|
|
|
|
color: #333;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
|
|
|
|
.el-input {
|
|
|
|
|
flex: 1;
|
|
|
|
|
max-width: 80%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-area {
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-box {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 120px;
|
|
|
|
|
border: 1px dashed #dcdfe6;
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-box:hover {
|
|
|
|
|
border-color: #409eff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-icon {
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
color: #8c939d;
|
|
|
|
|
margin-bottom: 5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-text {
|
|
|
|
|
color: #606266;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-tip {
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: #909399;
|
|
|
|
|
margin-top: 5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-image {
|
|
|
|
|
width: 100%;
|
|
|
|
|
max-height: 250px;
|
|
|
|
|
object-fit: contain;
|
|
|
|
|
border: 1px solid #dcdfe6;
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.handbook-dialog .el-dialog {
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.handbook-dialog .el-button--primary {
|
|
|
|
|
background-color: #1890ff;
|
|
|
|
|
border-color: #1890ff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.cover-form {
|
|
|
|
|
width: 100%;
|
|
|
|
|
max-width: 1200px;
|
|
|
|
|
}
|
|
|
|
|
.project-top{
|
|
|
|
|
border: 1px solid #1890ff;
|
|
|
|
|
padding: 15px 15px 0px 15px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
}
|
|
|
|
|
.form-row {
|
|
|
|
|
display: flex;
|
|
|
|
|
margin-bottom:60px;
|
|
|
|
|
justify-content: space-around;
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-col {
|
|
|
|
|
flex: 1;
|
|
|
|
|
margin-right: 20px;
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-col-full {
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-area {
|
|
|
|
|
border: 1px dashed #d9d9d9;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
border-color: #409EFF;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-box {
|
|
|
|
|
height: 180px;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
background-color: #fafafa;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-icon {
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
color: #8c939d;
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-text {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #606266;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.upload-tip {
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: #909399;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-image {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 180px;
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-container {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-label {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
color: #606266;
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-input {
|
|
|
|
|
width: 220px;
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-btn {
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.project-table {
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.project-table ::v-deep .el-table__row {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.project-table ::v-deep .el-table__row:hover {
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pagination-box {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: right;
|
|
|
|
|
margin: 16px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.selected-projects-container {
|
|
|
|
|
border: 1px solid #1890ff;
|
|
|
|
|
padding: 15px 15px 10px 15px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.selected-header {
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
color: #333;
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.selected-list {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.selected-item {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
padding: 8px 15px;
|
|
|
|
|
background-color: #F8F8F8;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dot-indicator {
|
|
|
|
|
width: 8px;
|
|
|
|
|
height: 8px;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
background-color: #409EFF;
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.project-name {
|
|
|
|
|
flex: 1;
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.remove-icon {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
color: #C0C4CC;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.remove-icon:hover {
|
|
|
|
|
color: #F56C6C;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
::v-deep .el-dialog__body {
|
|
|
|
|
padding: 20px 15px!important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.step-content {
|
|
|
|
|
padding: 10px 10%;
|
|
|
|
|
min-height: 400px;
|
|
|
|
|
}
|
|
|
|
|
</style>
|