招标解析

This commit is contained in:
cwchen 2025-11-05 09:47:20 +08:00
parent 90fea54cef
commit 8deab5d92c
5 changed files with 414 additions and 20 deletions

View File

@ -8,7 +8,7 @@ VUE_APP_ENV = 'development'
# 智能投标系统/开发环境 # 智能投标系统/开发环境
VUE_APP_BASE_API = '/dev-api' VUE_APP_BASE_API = '/dev-api'
VUE_APP_ONLYOFFICE_URL = 'http://192.168.0.14:19840/' VUE_APP_ONLYOFFICE_URL = 'http://192.168.0.14:19840'
# 路由懒加载 # 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true VUE_CLI_BABEL_TRANSPILE_MODULES = true

View File

@ -0,0 +1,292 @@
<template>
<!-- 小型弹窗用于完成删除保存等操作 -->
<el-dialog class="l-dialog" :class="lDialog" :title="title" :visible.sync="dialogVisible" :showClose="true"
:closeOnClickModal="false" @close="handleClose" :append-to-body="true">
<div>
<el-form :model="form" :rules="rules" ref="ruleForm" label-width="110px">
<el-form-item label="项目名称" prop="toolName">
<el-input class="form-item" v-model="form.toolName" clearable show-word-limit placeholder="请输入项目名称"
maxlength="64"></el-input>
</el-form-item>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<el-button type="primary" class="confirm-btn"
@click="submitForm('ruleForm')">确认</el-button>
<el-button class="cancel-btn" @click="handleClose">取消</el-button>
</span>
</el-dialog>
</template>
<script>
import _ from 'lodash'
import UploadFile from '@/views/common/UploadFile.vue'
import FileOrImageDisplay from '@/views/common/FileOrImageDisplay.vue';
//
const defaultParams = {
fileUploadRule: {
fileUploadType: 'tools',
fields_json: '',
suffix: 'tools_database'
},
};
export default {
name: "AnalysisForm",
components: {
UploadFile,
FileOrImageDisplay
},
props: ["width", "rowData", "title", "isAdd"],
data() {
return {
lDialog: this.width > 500 ? "w700" : "w500",
dialogVisible: true,
defaultParams,
form: {
id: null,
toolName: '',
},
rules: {
toolName: [
{ required: true, message: '工器具名称不能为空', trigger: 'blur' }
],
},
};
},
watch: {
isAdd: {
handler(newVal) {
if (newVal === 'edit' || newVal === 'detail') {
this.initFormData();
}
},
immediate: true,
},
},
methods: {
/** 初始化表单数据 */
async initFormData() {
if (!this.rowData) return;
const files = await this.getDetail();
//
this.form = {
toolId: this.rowData.toolId,
};
},
async getDetail() {
try {
const res = await getDetailDataAPI({ toolId: this.rowData.toolId, enterpriseId: this.rowData.enterpriseId });
if (res && res.code === 200) {
return this.getFileList(res.data);
}
return [];
} catch (error) {
console.error(error);
return [];
}
},
getFileList(detailData){
const list = detailData && Array.isArray(detailData.resourceFileVoList)
? detailData.resourceFileVoList
: [];
return list.map(item => {
return {
name: item.fileName,
filePath: item.filePath,
lsFilePath: item.lsFilePath,
fileType: item.fileType
};
});
},
//
handleFileChange(file) {
console.log(file);
this.form.fileList = file;
},
//
handleDelFile(file) {
console.log(file);
const delPath = file?.response?.fileRes?.filePath || file?.filePath || null;
if (delPath) {
this.form.delFileList.push(delPath);
}
},
/*关闭弹窗 */
handleClose() {
this.dialogVisible = false;
this.$emit("closeDialog");
},
/**确认弹窗 */
sureBtnClick() {
this.dialogVisible = false;
this.$emit("closeDialog");
},
/**重置表单*/
reset() {
this.form = {
id: null,
pid: null,
dataTypeName: '',
remark: '',
};
this.resetForm("ruleForm");
},
handleReuslt(res) {
this.$modal.msgSuccess(res.msg);
this.reset();
this.$emit('handleQuery');
this.handleClose();
},
validate(formName) {
return new Promise((resolve, reject) => {
this.$refs[formName].validate((valid) => {
if (valid) {
resolve(this.form) //
} else {
reject(new Error('数据未填写完整'))
}
})
})
},
/**验证 */
async submitForm(formName) {
try {
const data = await this.validate(formName);
//
let formData = {
...data,
allFiles: [
...data.fileList.map(file => JSON.parse(JSON.stringify(file))),
],
delFiles: [
...data.delFileList
]
}
let allFiles = formData.allFiles.map(file => {
return file?.response?.fileRes ? {
...file.response.fileRes,
} : null;
}).filter(item => item !== null);
formData.files = allFiles;
delete formData.fileList;
delete formData.delFileList;
delete formData.allFiles;
//
this.loading = this.$loading({
lock: true,
text: "数据提交中,请稍候...",
background: 'rgba(0,0,0,0.5)',
target: this.$el.querySelector('.el-dialog') || document.body
})
console.log('所有表单校验通过,完整数据:', formData)
const res = await this.saveData(formData)
if (res.code === 200) {
this.handleReuslt(res);
} else {
this.$modal.msgError(res.msg);
}
} catch (error) {
} finally {
this.loading.close();
}
},
//
async saveData(formData) {
return new Promise((resolve, reject) => {
if (this.isAdd === 'add') { //
addDataAPI(formData).then(res => {
resolve(res)
}).catch(error => {
reject(error)
})
} else { //
editDataAPI(formData).then(res => {
resolve(res)
}).catch(error => {
reject(error)
})
}
})
},
}
};
</script>
<style lang="scss" scoped>
.w700 ::v-deep .el-dialog {
width: 700px;
font-family: Source Han Sans CN, Source Han Sans CN;
}
.w500 ::v-deep .el-dialog {
width: 500px;
font-family: Source Han Sans CN, Source Han Sans CN;
}
.w500 ::v-deep .el-dialog__header,
.w700 ::v-deep .el-dialog__header {
.el-dialog__title {
font-size: 16px;
}
}
.yxq .el-range-separator {
margin-right: 7px !important;
}
.el-date-editor--daterange.el-input__inner {
width: 260px;
}
.form-item {
width: 100%;
}
.select-style {
display: flex;
justify-content: space-between;
}
.confirm-btn {
width: 98px;
height: 36px;
background: #1F72EA;
box-shadow: 0px 4px 8px 0px rgba(51, 135, 255, 0.5);
border-radius: 4px 4px 4px 4px;
color: #fff;
border: none;
font-size: 14px;
transition: all 0.3s;
&:hover {
background: #4A8BFF;
box-shadow: 0px 6px 12px 0px rgba(51, 135, 255, 0.6);
}
}
.cancel-btn {
width: 98px;
height: 36px;
background: #E5E5E5;
box-shadow: 0px 4px 8px 0px rgba(76, 76, 76, 0.2);
border-radius: 4px 4px 4px 4px;
color: #333;
border: none;
font-size: 14px;
transition: all 0.3s;
&:hover {
background: #d0d0d0;
box-shadow: 0px 6px 12px 0px rgba(76, 76, 76, 0.3);
}
}
::v-deep .el-dialog__footer {
text-align: center;
}
</style>

View File

@ -34,6 +34,9 @@
:allow-download="true" @close="showViewer = false" @loaded="onViewerLoaded" @error="onViewerError" :allow-download="true" @close="showViewer = false" @loaded="onViewerLoaded" @error="onViewerError"
@download-success="onDownloadSuccess" /> @download-success="onDownloadSuccess" />
</el-dialog> </el-dialog>
<!-- 新建项目 -->
<AnalysisForm v-if="showAnalysisForm" :title="title" :isAdd="isAdd" :row="row"
@closeDialog="showAnalysisForm = false" :width="600"/>
</el-card> </el-card>
</template> </template>
@ -42,11 +45,13 @@ import TableModel from '@/components/TableModel2'
import { columnsList, formLabel } from './config' import { columnsList, formLabel } from './config'
import { listAPI, delDataAPI } from '@/api/analysis/analysis' import { listAPI, delDataAPI } from '@/api/analysis/analysis'
import OnlyOfficeViewer from '@/views/common/OnlyOfficeViewer.vue' import OnlyOfficeViewer from '@/views/common/OnlyOfficeViewer.vue'
import AnalysisForm from './components/AnalysisForm.vue'
export default { export default {
name: 'Tool', name: 'Tool',
components: { components: {
TableModel, TableModel,
OnlyOfficeViewer, OnlyOfficeViewer,
AnalysisForm
}, },
data() { data() {
return { return {
@ -55,7 +60,11 @@ export default {
listAPI, listAPI,
showViewer: false, showViewer: false,
documentId: '716d9f3d89434c56bc49296dbbccc226', documentId: '716d9f3d89434c56bc49296dbbccc226',
documentName: 'technicalSolutionDatabase/2025/11/03/716d9f3d89434c56bc49296dbbccc226.docx' documentName: 'technicalSolutionDatabase/2025/11/03/716d9f3d89434c56bc49296dbbccc226.docx',
showAnalysisForm: false,
title: '',
isAdd: '',
row: {},
} }
}, },
@ -75,15 +84,14 @@ export default {
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.title = "新增工器具"; this.title = "新建项目";
this.isAdd = 'add'; this.isAdd = 'add';
this.row = { enterpriseId: this.enterpriseId }; this.showAnalysisForm = true;
this.isflag = true;
}, },
/** 修改操作 */ /** 修改操作 */
handleUpdate(row) { handleUpdate(row) {
this.title = "修改工器具"; this.title = "修改项目";
this.isAdd = 'edit'; this.isAdd = 'edit';
this.row = row; this.row = row;
this.isflag = true; this.isflag = true;

View File

@ -39,8 +39,8 @@
</div> </div>
<!-- 编辑器容器 --> <!-- 编辑器容器 -->
<div v-show="!loading && !error" ref="editorContainer" class="editor-container" <div v-if="!loading && !error" ref="editorContainer" class="editor-container"
:class="{ 'fullscreen': isFullscreen }" :style="{ height: containerHeight }"></div> :class="{ 'fullscreen': isFullscreen }" :style="{ height: containerHeight, width: '100%' }"></div>
<!-- 移动端提示 --> <!-- 移动端提示 -->
<div v-if="isMobile && !loading && !error" class="mobile-tip"> <div v-if="isMobile && !loading && !error" class="mobile-tip">
@ -124,11 +124,16 @@ export default {
return '100vh'; return '100vh';
} }
// 48px // 48px
if (this.height.includes('vh')) {
// vh
const vhValue = parseFloat(this.height);
return `calc(${vhValue}vh - 48px)`;
}
const heightValue = parseInt(this.height); const heightValue = parseInt(this.height);
if (isNaN(heightValue)) { if (isNaN(heightValue)) {
return 'calc(100% - 48px)'; return 'calc(100% - 48px)';
} }
return `${heightValue - 48}px`; return `${Math.max(heightValue - 48, 200)}px`; // 200px
} }
}, },
@ -165,6 +170,21 @@ export default {
// //
this.loadingText = '正在获取文档配置...'; this.loadingText = '正在获取文档配置...';
const config = await this.getEditorConfig(); const config = await this.getEditorConfig();
console.log('OnlyOffice 配置:', config);
//
if (!config || typeof config !== 'object') {
throw new Error('获取的配置格式不正确');
}
//
if (!config.document || !config.document.url) {
throw new Error('配置中缺少文档URL');
}
if (!config.documentType) {
console.warn('配置中缺少 documentType将尝试自动检测');
}
// //
if (!window.DocsAPI) { if (!window.DocsAPI) {
@ -172,13 +192,72 @@ export default {
} }
this.loadingText = '正在初始化编辑器...'; this.loadingText = '正在初始化编辑器...';
this.editor = new window.DocsAPI.DocEditor(
this.$refs.editorContainer,
config
);
this.loading = false; //
this.$emit('loaded', this.editor); const container = this.$refs.editorContainer;
if (container) {
//
container.style.display = 'block';
container.style.width = '100%';
// tickDOM
await this.$nextTick();
//
const rect = container.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) {
console.warn('容器尺寸为0等待尺寸调整...', rect);
//
await new Promise(resolve => setTimeout(resolve, 500));
}
}
//
try {
this.editor = new window.DocsAPI.DocEditor(
this.$refs.editorContainer,
config
);
//
if (this.editor && this.editor.events) {
//
this.editor.events.on('onDocumentReady', () => {
console.log('OnlyOffice 文档已准备就绪');
this.loading = false;
});
this.editor.events.on('onAppReady', () => {
console.log('OnlyOffice 应用已准备就绪');
//
setTimeout(() => {
if (this.loading) {
this.loading = false;
}
}, 1000);
});
this.editor.events.on('onError', (error) => {
console.error('OnlyOffice 错误:', error);
this.handleError(`编辑器错误: ${error?.data || error?.message || '未知错误'}`);
});
}
//
setTimeout(() => {
if (this.loading) {
this.loading = false;
console.warn('编辑器初始化超时,但可能仍在加载中');
}
}, 30000); // 30
//
this.loading = false;
this.$emit('loaded', this.editor);
} catch (editorError) {
console.error('创建编辑器实例失败:', editorError);
throw new Error(`创建编辑器失败: ${editorError.message}`);
}
} catch (error) { } catch (error) {
console.error('初始化文档查看器失败:', error); console.error('初始化文档查看器失败:', error);
const errorMsg = error?.message || error?.response?.data?.msg || '加载文档失败,请重试'; const errorMsg = error?.message || error?.response?.data?.msg || '加载文档失败,请重试';
@ -608,6 +687,17 @@ export default {
position: relative; position: relative;
transition: all 0.3s ease; transition: all 0.3s ease;
background: #f5f5f5; background: #f5f5f5;
min-height: 200px;
display: block !important;
/* 确保容器始终显示 */
/* 确保 OnlyOffice iframe 正确显示 */
::v-deep iframe {
width: 100% !important;
height: 100% !important;
border: none;
display: block;
}
} }
.editor-container.fullscreen { .editor-container.fullscreen {

View File

@ -72,9 +72,9 @@ export default {
dialogVisible: true, dialogVisible: true,
defaultParams, defaultParams,
form: { form: {
id: null, toolId: null,
enterpriseId: this.rowData.enterpriseId, enterpriseId: this.rowData.enterpriseId,
technicalSolutionName: '', toolName: '',
model: '', model: '',
unit: '', unit: '',
technicalParameters: '', technicalParameters: '',
@ -188,10 +188,14 @@ export default {
/**重置表单*/ /**重置表单*/
reset() { reset() {
this.form = { this.form = {
id: null, toolName: '',
pid: null, model: '',
dataTypeName: '', unit: '',
technicalParameters: '',
mainFunction: '',
remark: '', remark: '',
fileList: [],
delFileList: []
}; };
this.resetForm("ruleForm"); this.resetForm("ruleForm");
}, },