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.

1419 lines
36 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="container">
<!-- 项目手册管理 -->
<!-- 表单查询项 -->
<div v-if="!previewMode" class="headerbox">
<el-form size="small" :inline="true" label-width="200">
<el-row>
<el-col :span="5">
<el-form-item label="手册名称" style="width: 100%">
<el-input
v-model="queryParams.name"
placeholder="请输入手册名称"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="5">
<el-form-item label="创建时间">
<el-date-picker
v-model="queryParams.startTime"
type="date"
placeholder="选择日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd HH:mm:ss"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
@click="handleQuery"
>查询</el-button
>
<el-button icon="el-icon-refresh" @click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<!-- 表格内容区 -->
<div v-if="!previewMode" class="tablebox table-container">
<div class="tablebtntwo">
<!-- <el-button
type="primary"
icon="el-icon-plus"
:loading="exportLoading"
@click="handleExport"
>项目手册导出</el-button
> -->
<el-button
type="primary"
icon="el-icon-plus"
size="small"
@click="handleAdd"
>新增</el-button
>
</div>
<div class="table-wrapper">
<el-table v-loading="loading" :data="postList" height="100%">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center">
<template slot-scope="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column label="手册名称" align="center" prop="name" />
<el-table-column label="创建时间" align="center" prop="createTime" />
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button
type="text"
style="color: #409eff"
@click="handlePreview(scope.row)"
>预览</el-button
>
<el-button
type="text"
style="color: #67c23a"
@click="handleEdit(scope.row)"
>编辑</el-button
>
<el-button
type="text"
style="color: #409eff"
@click="handleExport(scope.row.id)"
>项目手册导出</el-button
>
<el-button
type="text"
style="color: #f56c6c"
@click="handleDelete(scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.current"
:limit.sync="queryParams.size"
@pagination="getList"
/>
</div>
<div v-if="previewMode" class="previewbox">
<div class="preview-header">
<div class="preview-title">
<i class="el-icon-document"></i>
<span>{{ previewData.name || "项目手册预览" }}</span>
</div>
<div class="preview-controls">
<div class="page-counter" v-if="pageCount > 0">
<span>{{ currentPage }} / {{ pageCount }}</span>
</div>
<el-button-group class="navigation-buttons">
<el-button
type="primary"
icon="el-icon-arrow-left"
:disabled="currentPage <= 1"
@click="prevPage"
>上一页</el-button
>
<el-button
type="primary"
icon="el-icon-arrow-right"
:disabled="currentPage >= pageCount"
@click="nextPage"
>下一页</el-button
>
</el-button-group>
<el-button
type="info"
icon="el-icon-back"
@click="previewMode = false"
>返回</el-button
>
</div>
</div>
<div class="preview-content" v-loading="loadingPdf">
<pdf
v-if="pdfData"
:src="pdfData"
:page="currentPage"
@num-pages="pageCount = $event"
@page-loaded="pageLoaded"
@loaded="pdfLoaded"
@error="pdfError"
:scale="pdfScale"
></pdf>
</div>
</div>
<!-- 创建新手册弹框 -->
<el-dialog
:title="editingHandbook ? '编辑手册' : '创建新手册'"
: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" style="margin-bottom: 10px">
<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">副标题1</label>
<el-input
v-model="coverForm.subtitle1"
placeholder="请输入"
></el-input>
</div>
</div>
<div class="form-row">
<div class="form-col">
<label class="form-label">副标题2</label>
<el-input
v-model="coverForm.subtitle2"
placeholder="请输入"
></el-input>
</div>
<div class="form-col" style="visibility: hidden">
<label class="form-label">手册名称</label>
<el-input
v-model="coverForm.title"
placeholder="请输入"
></el-input>
</div>
</div>
<!-- <div class="form-row">
<div class="form-col-full">
<label class="form-label">封面图片</label>
<file-upload
v-model="coverForm.imageUrl"
:limit="1"
:file-size="10"
:file-type="['png', 'jpg', 'jpeg', 'gif']"
></file-upload>
</div>
</div> -->
</div>
</div>
<!-- 步骤2选择项目 -->
<div v-show="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
>
</div>
<div class="project-table">
<el-table
ref="projectTable"
:data="projectList"
@row-click="handleRowClick"
height="200"
:row-key="(row) => row.id"
v-loading="loading"
@select="handleSelect"
@select-all="handleSelectAll"
>
<el-table-column
type="selection"
width="55"
align="center"
:reserve-selection="true"
></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="xzfl" label="现状分类" align="center">
<template slot-scope="scope">
<dict-tag
:options="dict.type.xzfl"
:value="scope.row.xzfl"
/>
</template>
</el-table-column>
<el-table-column
prop="xmfrdwxz"
label="项目法人单位"
align="center"
>
</el-table-column>
<el-table-column label="项目建设起止时间" align="center">
<template slot-scope="scope">
<span
>{{
scope.row.begainTime
? scope.row.begainTime.replace(/-/g, ".")
: ""
}}-{{
scope.row.endTime
? scope.row.endTime.replace(/-/g, ".")
: ""
}}</span
>
</template>
</el-table-column>
<el-table-column
prop="ztze"
label="总投资额(万元)"
align="center"
></el-table-column>
<el-table-column
prop="zydmj"
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"
>
<div class="dot-indicator"></div>
<span class="project-name">{{ project.name }}</span>
<el-button
type="text"
icon="el-icon-close"
class="remove-btn"
@click="removeSelectedProject(project)"
></el-button>
</div>
</div>
</div>
</div>
</div>
<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>
<file-upload
v-model="endForm.imageUrl"
:limit="1"
:file-size="10"
:file-type="['png', 'jpg', 'jpeg', 'gif']"
></file-upload>
</div>
</div> -->
<div class="form-row" style="margin-bottom: 10px">
<div class="form-col">
<label class="form-label">单位名称</label>
<el-input
v-model="endForm.dwname"
placeholder="请输入"
></el-input>
</div>
<div class="form-col">
<label class="form-label">联系人</label>
<el-input
v-model="endForm.lxname"
placeholder="请输入"
></el-input>
</div>
</div>
<div class="form-row" style="margin-bottom: 10px">
<div class="form-col">
<label class="form-label">联系方式</label>
<el-input v-model="endForm.phone" placeholder="请输入"></el-input>
</div>
<div class="form-col">
<label class="form-label">时间</label>
<el-date-picker
v-model="endForm.date"
type="date"
placeholder="请选择日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
style="width: 100%"
/>
</div>
</div>
<div class="form-row">
<div class="form-col">
<label class="form-label">地址</label>
<el-input
v-model="endForm.address"
placeholder="请输入"
></el-input>
</div>
<div class="form-col">
</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"
>{{ editingHandbook ? "更新手册" : "生成手册" }}</el-button
>
</div>
</el-dialog>
</div>
</template>
<script>
import VueOfficeDocx from "@vue-office/docx";
import pdf from "vue-pdf";
import {
getHandbookPage,
addHandbook,
updateHandbook,
deleteHandbook,
getHandbookDetail,
exportHandbook,
getBasicInformationPage,
} from "@/api/ManageApi/index";
import FileUpload from "@/components/FileUpload3";
export default {
components: {
"vue-office-docx": VueOfficeDocx,
pdf: pdf,
Pagination: () => import("@/components/Pagination"),
FileUpload,
},
// 声明需要使用的字典
dicts: ["xzfl"],
data() {
return {
queryParams: {
current: 1,
size: 20,
name: "",
startTime: "",
},
allPostList: [],
postList: [],
loading: false,
total: 0,
previewMode: false,
previewData: {},
// DOCX文件数据
docxFileData: null,
addDialogVisible: false,
activeStep: 1,
coverForm: {
title: "",
subtitle1: "",
subtitle2: "",
imageUrl: "",
},
// 项目选择相关
projectSearch: "",
projectList: [],
selectedProjects: [],
projectParams: {
pageNum: 1,
pageSize: 10,
},
projectTotal: 0,
// 封尾设计
endForm: {
imageUrl: "",
dwname: "",
name: "",
phone: "",
lxname: "",
address: "",
},
// 导出相关
selectedRows: [],
exportLoading: false,
selectedProjectIds: [], // 新增存储选中项目的id
// PDF预览相关
pdfData: null,
currentPage: 1,
pageCount: 0,
loadingPdf: false,
pdfScale: 0.9, // 控制PDF缩放比例
editingHandbook: null, // 当前正在编辑的手册对象
};
},
mounted() {
this.getList();
},
methods: {
getList() {
this.loading = true;
getHandbookPage(this.queryParams)
.then((res) => {
this.postList = res.data.records;
this.total = res.data.total;
this.loading = false;
})
.catch(() => {
this.loading = false;
});
},
getHandbookDetail(id) {
getHandbookDetail(id)
.then((res) => {
this.previewData = res.data;
})
.catch(() => {
this.loading = false;
});
},
// 查询
handleQuery() {
this.queryParams.current = 1;
this.getList();
},
// 重置查询
resetQuery() {
this.queryParams = {
current: 1,
size: 10,
title: undefined,
startTime: undefined,
};
this.handleQuery();
},
// 预览文档
handlePreview(row) {
this.previewMode = true;
this.previewData = row;
this.currentPage = 1;
this.pageCount = 0;
this.loadingPdf = true;
this.loadPdfFromApi(row.id);
},
async loadPdfFromApi(id) {
try {
const res = await exportHandbook([id]);
if (!res) {
throw new Error("获取PDF文件失败返回为空");
}
const blob = new Blob([res], { type: "application/pdf" });
this.pdfData = URL.createObjectURL(blob);
} catch (error) {
this.$message.error("PDF加载失败: " + (error.message || "未知错误"));
this.loadingPdf = false;
}
},
pageLoaded() {
this.loadingPdf = false;
},
pdfLoaded() {
this.loadingPdf = false;
},
pdfError(error) {
this.$message.error("PDF渲染失败: " + (error.message || "未知错误"));
this.loadingPdf = false;
},
prevPage() {
if (this.currentPage > 1) {
this.currentPage--;
}
},
nextPage() {
if (this.currentPage < this.pageCount) {
this.currentPage++;
}
},
// 项目手册导出
async handleExport(id) {
try {
this.exportLoading = true;
// const idList = this.selectedRows.map((item) => item.id);
// const res = await exportHandbook(idList);
const res = await exportHandbook([id]);
this.$download.saveAs(res, "项目手册.pdf");
this.$message.success("导出成功");
} catch (error) {
this.$message.error("导出过程中发生错误");
} finally {
this.exportLoading = false;
}
},
handleAdd() {
this.addDialogVisible = true;
this.activeStep = 1;
this.resetAddForm();
this.editingHandbook = null;
this.selectedProjectIds = [];
this.selectedProjects = [];
this.projectParams.pageNum = 1;
this.getProjectList();
},
handleAddDialogClose(done) {
this.resetAddForm();
this.editingHandbook = null;
this.selectedProjectIds = [];
this.selectedProjects = [];
done();
},
resetAddForm() {
this.coverForm = {
title: "",
subtitle1: "",
subtitle2: "",
imageUrl: "",
};
this.projectSearch = "";
this.endForm = {
imageUrl: "",
dwname: "",
date: "",
phone: "",
lxname: "",
address: "",
};
},
nextStep() {
this.activeStep++;
},
prevStep() {
this.activeStep--;
},
getProjectList() {
this.loading = true;
const params = {
current: this.projectParams.pageNum,
size: this.projectParams.pageSize,
name: this.projectSearch || undefined,
};
getBasicInformationPage(params)
.then((response) => {
this.projectList = response.data.records;
this.projectTotal = response.data.total;
if (this.selectedProjectIds.length > 0) {
this.$nextTick(() => {
this.restoreSelection();
});
}
this.loading = false;
})
.catch((error) => {
this.loading = false;
this.$message.error("获取项目列表失败");
});
},
searchProjects() {
this.projectParams.pageNum = 1;
this.getProjectList();
},
resetProjectSearch() {
this.projectSearch = "";
this.projectParams.pageNum = 1;
this.getProjectList();
},
handleRowClick(row) {
this.$refs.projectTable.toggleRowSelection(row);
const selectedRows = this.$refs.projectTable.selection;
const isSelected = selectedRows.some((item) => item.id === row.id);
if (isSelected) {
// 如果是选中状态,添加到已选项目中
if (!this.selectedProjectIds.includes(row.id)) {
this.selectedProjectIds.push(row.id);
this.selectedProjects.push(row);
}
} else {
// 如果是取消选中,从已选项目中移除
this.selectedProjectIds = this.selectedProjectIds.filter(
(id) => id !== row.id
);
this.selectedProjects = this.selectedProjects.filter(
(item) => item.id !== row.id
);
}
},
removeSelectedProject(project) {
// 从选择列表中移除项目
this.selectedProjects = this.selectedProjects.filter(
(item) => item.id !== project.id
);
this.selectedProjectIds = this.selectedProjectIds.filter(
(id) => id !== project.id
);
// 如果项目在当前页面,取消其选择状态
if (this.$refs.projectTable) {
const projectInCurrentPage = this.projectList.find(
(item) => item.id == project.id
);
if (projectInCurrentPage) {
this.$refs.projectTable.toggleRowSelection(
projectInCurrentPage,
false
);
}
}
},
handleProjectPagination() {
this.getProjectList();
},
// 恢复选中状态
restoreSelection() {
if (!this.$refs.projectTable) return;
this.$refs.projectTable.clearSelection();
if (!this.selectedProjectIds.length) return;
this.projectList.forEach((row) => {
if (this.selectedProjectIds.includes(row.id)) {
this.$refs.projectTable.toggleRowSelection(row, true);
}
});
},
// 提交生成手册
submitHandbook() {
if (this.selectedProjects.length === 0) {
this.$message.warning("请至少选择一个项目");
return;
}
const data = {};
if (this.coverForm.imageUrl) data.coverImg = this.coverForm.imageUrl;
if (this.coverForm.title) data.name = this.coverForm.title;
if (this.coverForm.subtitle1) data.subtitle1 = this.coverForm.subtitle1;
if (this.coverForm.subtitle2) data.subtitle2 = this.coverForm.subtitle2;
if (this.endForm.imageUrl) data.tailingImg = this.endForm.imageUrl;
if (this.endForm.dwname) data.dwname = this.endForm.dwname;
if (this.endForm.date) data.date = this.endForm.date;
if (this.endForm.phone) data.phone = this.endForm.phone;
if (this.endForm.lxname) data.lxname = this.endForm.lxname;
if (this.endForm.address) data.address = this.endForm.address;
if (this.selectedProjects && this.selectedProjects.length > 0) {
data.xmId = this.selectedProjects
.map((project) => project.id)
.join(",");
}
if (this.editingHandbook) {
data.id = this.editingHandbook.id;
updateHandbook(data)
.then((res) => {
this.$message.success("手册更新成功");
this.addDialogVisible = false;
this.getList();
// 重置编辑状态
this.editingHandbook = null;
})
.catch(() => {
this.$message.error("手册更新失败");
});
} else {
// 新增模式
addHandbook(data)
.then((res) => {
this.$message.success("手册生成成功");
this.addDialogVisible = false;
this.getList();
})
.catch(() => {
this.$message.error("手册生成失败");
});
}
},
// 处理单个项目选择事件
handleSelect(selection, row) {
// 检查是选中还是取消选中
const isSelected = selection.some((item) => item.id === row.id);
if (isSelected) {
// 如果是选中,添加到已选列表中
if (!this.selectedProjectIds.includes(row.id)) {
this.selectedProjectIds.push(row.id);
this.selectedProjects.push(row);
}
} else {
// 如果是取消选中,从已选列表中移除
this.selectedProjectIds = this.selectedProjectIds.filter(
(id) => id !== row.id
);
this.selectedProjects = this.selectedProjects.filter(
(item) => item.id !== row.id
);
}
},
// 处理全选/取消全选事件
handleSelectAll(selection) {
// 获取当前页面所有项目ID
const currentPageIds = this.projectList.map((item) => item.id);
// 检查是全选还是取消全选
if (selection.length === 0) {
// 取消全选 - 从已选列表中移除当前页所有项目
this.selectedProjectIds = this.selectedProjectIds.filter(
(id) => !currentPageIds.includes(id)
);
this.selectedProjects = this.selectedProjects.filter(
(project) => !currentPageIds.includes(project.id)
);
} else {
// 全选 - 将当前页所有项目添加到已选列表
// 先移除当前页已有的选择,避免重复
const projectIdsNotInCurrentPage = this.selectedProjectIds.filter(
(id) => !currentPageIds.includes(id)
);
const projectsNotInCurrentPage = this.selectedProjects.filter(
(project) => !currentPageIds.includes(project.id)
);
// 合并不在当前页的选择和当前页所有项目
this.selectedProjectIds = [
...projectIdsNotInCurrentPage,
...currentPageIds,
];
this.selectedProjects = [
...projectsNotInCurrentPage,
...this.projectList,
];
}
},
// 编辑按钮操作
handleEdit(row) {
// 获取手册详情
this.loading = true;
getHandbookDetail(row.id)
.then((res) => {
const detail = res.data;
this.coverForm = {
title: detail.name,
subtitle1: detail.subtitle1,
subtitle2: detail.subtitle2,
imageUrl: detail.coverImg,
};
this.endForm = {
imageUrl: detail.tailingImg || "",
dwname: detail.dwname || "",
lxname: detail.lxname || "",
phone: detail.phone || "",
address: detail.address || "",
date: detail.date || "",
};
// 先清空选中状态
this.selectedProjectIds = [];
this.selectedProjects = [];
if (detail.xmId) {
const projectIds = detail.xmId.split(",");
this.selectedProjectIds = projectIds.map((id) => Number(id));
// 设置已选择的项目
if (detail.projectName && Array.isArray(detail.projectName)) {
this.selectedProjects = detail.projectName;
}
this.projectParams.pageNum = 1;
this.getProjectList();
}
this.loading = false;
this.addDialogVisible = true;
this.activeStep = 1;
this.editingHandbook = detail;
})
.catch(() => {
this.$message.error("获取手册详情失败");
this.loading = false;
});
},
// 删除按钮操作
handleDelete(row) {
this.$confirm("是否确认删除该手册?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(async () => {
this.loading = true;
const idList = [row.id];
await deleteHandbook(idList).then(() => {
this.$message.success("删除成功");
this.getList();
});
this.loading = false;
})
.catch(() => {});
},
},
};
</script>
<style scoped lang="scss">
/* */
.headerbox,
.tablebox {
background-color: #fff;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
border: 1px solid #eee;
margin: 0.5rem;
.el-input {
flex: 1;
max-width: 100%;
}
}
.headerbox {
margin-bottom: 15px;
}
/* */
.tablebtntwo {
width: 100%;
display: flex;
justify-content: left;
margin: 10px 0 20px;
}
.tablebox ::v-deep .el-table {
border-radius: 4px;
overflow: hidden;
.el-table__header-wrapper th {
background-color: #f5f7fa;
color: #606266;
font-weight: 600;
padding: 12px 0;
}
// .el-table__row {
// // transition: all 0.2s;
// // &:hover {
// // background-color: #ecf5ff;
// // }
// }
.el-button--text {
padding: 0 5px;
font-weight: 500;
// transition: all 0.3s;
// &:hover {
// transform: scale(1.05);
// }
}
}
/* PDF */
.previewbox {
height: calc(100% - 50px);
z-index: 1500;
display: flex;
flex-direction: column;
padding: 20px;
overflow: hidden;
animation: fadeIn 0.3s ease;
}
.preview-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
background-color: #ffffff;
border-radius: 8px 8px 0 0;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
flex-shrink: 0;
}
.preview-title {
font-size: 18px;
font-weight: 600;
color: #303133;
display: flex;
align-items: center;
i {
margin-right: 10px;
color: #409eff;
font-size: 20px;
}
}
.preview-controls {
display: flex;
align-items: center;
gap: 15px;
}
.page-counter {
background-color: #ecf5ff;
padding: 6px 12px;
border-radius: 4px;
color: #409eff;
font-size: 14px;
font-weight: 500;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
min-width: 60px;
text-align: center;
}
.navigation-buttons {
display: flex;
gap: 10px;
.el-button {
padding: 7px 15px;
font-weight: 500;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
// transition: all 0.2s ease;
// &:hover:not([disabled]) {
// transform: translateY(-2px);
// box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
// }
&[disabled] {
opacity: 0.6;
cursor: not-allowed;
}
}
}
.preview-content {
flex: 1;
overflow: auto;
background-color: #f5f7fa;
border-radius: 0 0 8px 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
display: flex;
justify-content: center;
position: relative;
width: 100%;
scrollbar-width: none;
span {
width: 100%;
height: 100%;
}
::v-deep canvas {
max-width: 100% !important;
height: auto !important;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
border-radius: 2px;
background-color: white;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* */
.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__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);
}
::v-deep {
.is-process {
color: #c0c4cc !important;
font-weight: normal !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;
}
}
.el-dialog {
border-radius: 4px;
overflow: hidden;
}
.el-button--primary {
background-color: #1890ff;
border-color: #1890ff;
}
}
/* */
.form-label {
width: 70px;
text-align: right;
padding-right: 10px;
line-height: 32px;
color: #333;
font-size: 14px;
}
/* */
.cover-form {
width: 100%;
max-width: 1200px;
}
.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%;
}
/* */
.project-top {
border: 1px solid #1890ff;
padding: 15px 15px 0px 15px;
border-radius: 4px;
margin-bottom: 10px;
}
.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,
.search-date {
width: 30%;
transition: all 0.3s;
margin-right: 30px;
::v-deep .el-input {
flex: 1 !important;
max-width: 100% !important;
}
::v-deep .el-input__inner {
width: 100% !important;
}
&:hover {
box-shadow: 0 0 0 1px #409eff;
}
}
.search-btn {
margin-right: 8px;
}
.project-table {
border-radius: 4px;
overflow: hidden;
margin-bottom: 20px;
::v-deep .el-table {
max-height: 400px;
overflow-y: auto;
.el-table__body-wrapper {
overflow-y: auto;
}
.el-table__row {
cursor: pointer;
&: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;
max-height: 300px;
display: flex;
flex-direction: column;
}
.selected-header {
font-size: 15px;
font-weight: 500;
color: #333;
margin-bottom: 15px;
}
.selected-list {
display: flex;
flex-direction: column;
gap: 12px;
max-height: 100px;
overflow-y: auto;
padding-right: 10px;
flex: 1;
/* */
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
&::-webkit-scrollbar-thumb {
background: #c0c4cc;
border-radius: 4px;
}
&::-webkit-scrollbar-thumb:hover {
background: #909399;
}
}
.selected-item {
display: flex;
align-items: center;
padding: 8px 15px;
background-color: #f8f8f8;
border-radius: 4px;
position: relative;
transition: all 0.2s;
&:hover {
background-color: #f0f0f0;
.remove-btn {
opacity: 1;
}
}
}
.dot-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #409eff;
margin-right: 10px;
}
.project-name {
flex: 1;
color: #333;
}
.remove-btn {
opacity: 0.5;
transition: all 0.2s;
color: #909399;
padding: 2px;
margin-left: 8px;
&:hover {
color: #f56c6c;
opacity: 1;
transform: scale(1.1);
}
}
/* */
.step-content {
padding: 10px 10%;
min-height: 400px;
}
::v-deep .el-dialog__body {
padding: 20px 15px !important;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
padding: 10px;
box-sizing: border-box;
overflow: hidden;
}
.headerbox {
background-color: #fff;
border-radius: 0.5rem;
padding: 1rem 1rem 0rem 1rem;
margin-bottom: 0.5rem;
border: 1px solid #eee;
}
.table-container {
flex: 1;
display: flex;
flex-direction: column;
background-color: #fff;
border-radius: 0.5rem;
padding: 1rem;
border: 1px solid #eee;
overflow: hidden;
}
.table-header {
margin-bottom: 1rem;
width: 99.7%;
display: flex;
justify-content: space-between;
}
.table-wrapper {
flex: 1;
min-height: 0;
overflow: hidden;
}
.el-table {
height: 100% !important;
}
/* */
.table-container ::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
display: none;
}
/* Firefox */
.table-container {
scrollbar-width: none;
}
</style>