2025-11-05 16:42:09 +08:00
|
|
|
|
<template>
|
2025-11-05 18:00:34 +08:00
|
|
|
|
<!-- 标段解析 -->
|
2025-11-05 16:42:09 +08:00
|
|
|
|
<div class="analysis-detail-container">
|
|
|
|
|
|
<div class="content-header">
|
|
|
|
|
|
<el-button class="reset-btn" @click="handleClose">返回</el-button>
|
|
|
|
|
|
<el-button class="upload-btn" @click="handleUpload('ruleForm')">提交解析</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="content-scrollable">
|
|
|
|
|
|
<el-card class="analysis-detail-card">
|
|
|
|
|
|
<template slot="header">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<img src="@/assets/enterpriseLibrary/basic-info.png" alt="项目信息">
|
|
|
|
|
|
<h3>项目信息</h3>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<div class="analysis-detail-content">
|
|
|
|
|
|
<!-- 两列布局的字段 -->
|
|
|
|
|
|
<el-row :gutter="24" class="detail-row">
|
|
|
|
|
|
<el-col :span="12" class="detail-col">
|
|
|
|
|
|
<div class="detail-field">
|
|
|
|
|
|
<div class="field-label">项目名称</div>
|
|
|
|
|
|
<div class="field-value">{{ detailData.proName || '--' }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12" class="detail-col">
|
|
|
|
|
|
<div class="detail-field">
|
|
|
|
|
|
<div class="field-label">项目编号</div>
|
|
|
|
|
|
<div class="field-value">{{ detailData.proCode || '--' }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
<el-row :gutter="24" class="detail-row">
|
|
|
|
|
|
<el-col :span="12" class="detail-col">
|
|
|
|
|
|
<div class="detail-field">
|
|
|
|
|
|
<div class="field-label">招标人</div>
|
2025-11-26 16:47:07 +08:00
|
|
|
|
<div class="field-value">{{ detailData.tenderer || '--' }}</div>
|
2025-11-05 16:42:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12" class="detail-col">
|
|
|
|
|
|
<div class="detail-field">
|
|
|
|
|
|
<div class="field-label">代理机构</div>
|
|
|
|
|
|
<div class="field-value">{{ detailData.agency || '--' }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
<el-row :gutter="24" class="detail-row">
|
|
|
|
|
|
<el-col :span="12" class="detail-col">
|
|
|
|
|
|
<div class="detail-field">
|
|
|
|
|
|
<div class="field-label">开标时间</div>
|
2025-11-26 16:47:07 +08:00
|
|
|
|
<div class="field-value">{{ detailData.bidOpeningTime || '--' }}</div>
|
2025-11-05 16:42:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12" class="detail-col">
|
|
|
|
|
|
<div class="detail-field">
|
|
|
|
|
|
<div class="field-label">开标方式</div>
|
2025-11-26 16:47:07 +08:00
|
|
|
|
<div class="field-value">{{ detailData.bidOpeningMethod || '--' }}</div>
|
2025-11-05 16:42:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 项目简介 - 占满宽度 -->
|
|
|
|
|
|
<div class="detail-field full-width">
|
|
|
|
|
|
<div class="field-label">项目简介</div>
|
2025-11-26 16:47:07 +08:00
|
|
|
|
<div class="field-value description-value">{{ detailData.proIntroduction || '--' }}</div>
|
2025-11-05 16:42:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-11-26 16:47:07 +08:00
|
|
|
|
<div class="detail-field full-width" v-for="item in detailData.compositions" :key="item.id">
|
|
|
|
|
|
<div class="field-label">{{ item.compositionFileName || '--' }}</div>
|
|
|
|
|
|
<div class="file-value" @click="viewFile(item)">{{ getFirstFileName(item) }}</div>
|
2025-11-05 16:42:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
<div class="table-container">
|
|
|
|
|
|
<el-row :gutter="12">
|
|
|
|
|
|
<el-col :span="17">
|
|
|
|
|
|
<TableModel :showSearch="false" :showOperation="false" :showRightTools="false"
|
2025-11-26 16:47:07 +08:00
|
|
|
|
ref="detailTableRef" :columnsList="detailColumnsList" :request-api="getBidListAPI"
|
2025-11-05 16:42:09 +08:00
|
|
|
|
:sendParams="sendParams" :handleColWidth="180" :isRadioShow="true"
|
2025-11-05 18:00:34 +08:00
|
|
|
|
@radio-change="handleRadioChange" :indexNumShow="false" :isShowtableCardStyle="false">
|
2025-11-05 16:42:09 +08:00
|
|
|
|
<template slot="tableTitle">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<img src="@/assets/enterpriseLibrary/basic-info.png" alt="标的信息">
|
|
|
|
|
|
<h3>标的信息</h3>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<template slot="handle" slot-scope="{ data }">
|
|
|
|
|
|
<el-button type="text" v-hasPermi="['enterpriseLibrary:analysis:edit']"
|
|
|
|
|
|
class="action-btn" style="#FE9400" @click="handleUpdate(data)">
|
|
|
|
|
|
修改
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</TableModel>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="7">
|
|
|
|
|
|
<el-card class="upload-container">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<img src="@/assets/enterpriseLibrary/basic-info.png" alt="附件上传">
|
|
|
|
|
|
<h3>附件上传</h3>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="upload-title">
|
|
|
|
|
|
<span>请先选择需要解析的标的,再上传标的及其相关附件附件进行解析</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<el-form :model="form" :rules="rules" ref="ruleForm" label-width="110px"
|
|
|
|
|
|
label-position="top">
|
|
|
|
|
|
<el-form-item v-for="(item, index) in uploadType" :key="index" :label="item"
|
|
|
|
|
|
:prop="`fileList${index + 1}`">
|
|
|
|
|
|
<UploadMoreFile :fileList="form[`fileList${index + 1}`]"
|
|
|
|
|
|
@file-change="handleFileChange" @del-file="handleDelFile"
|
|
|
|
|
|
:type="`fileList${index + 1}`" :uploadType="defaultParams.uploadType"
|
|
|
|
|
|
:maxFileTips="defaultParams.maxFileTips"
|
|
|
|
|
|
:fileUploadRule="defaultParams.fileUploadRule"
|
|
|
|
|
|
:limitUploadNum="defaultParams.limitUploadNum" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-11-26 16:47:07 +08:00
|
|
|
|
<ViewFile v-if="dialogVisible" :file="fileData" @closeDialog="handleCloseDialog" />
|
2025-11-05 16:42:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
import { decryptWithSM4 } from '@/utils/sm'
|
2025-11-26 16:47:07 +08:00
|
|
|
|
import { getProDetailAPI, getBidListAPI } from '@/api/analysis/analysis'
|
2025-11-05 16:42:09 +08:00
|
|
|
|
import { formLabel, detailColumnsList } from '../config'
|
|
|
|
|
|
import TableModel from '@/components/TableModel2'
|
|
|
|
|
|
import BidForm from './BidForm.vue'
|
|
|
|
|
|
import UploadMoreFile from '@/views/common/UploadMoreFile.vue'
|
2025-11-26 16:47:07 +08:00
|
|
|
|
import ViewFile from '@/views/common/ViewFile.vue';
|
2025-11-05 16:42:09 +08:00
|
|
|
|
// 默认参数
|
|
|
|
|
|
const defaultParams = {
|
|
|
|
|
|
fileUploadRule: {
|
|
|
|
|
|
fileUploadType: 'bidding',
|
|
|
|
|
|
fields_json: '',
|
|
|
|
|
|
suffix: 'analysis_database',
|
|
|
|
|
|
},
|
|
|
|
|
|
uploadType: 'pdf、doc、docx',
|
|
|
|
|
|
maxFileTips: '500MB',
|
|
|
|
|
|
limitUploadNum: 1,
|
|
|
|
|
|
}
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: 'AnalysisBidDetail',
|
|
|
|
|
|
components: {
|
|
|
|
|
|
TableModel,
|
|
|
|
|
|
BidForm,
|
2025-11-26 16:47:07 +08:00
|
|
|
|
UploadMoreFile,
|
|
|
|
|
|
ViewFile
|
2025-11-05 16:42:09 +08:00
|
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
formLabel,
|
|
|
|
|
|
detailColumnsList,
|
2025-11-26 16:47:07 +08:00
|
|
|
|
getBidListAPI,
|
2025-11-05 16:42:09 +08:00
|
|
|
|
proId: '',
|
|
|
|
|
|
detailData: {},
|
|
|
|
|
|
sendParams: {
|
2025-11-26 16:47:07 +08:00
|
|
|
|
proId: decryptWithSM4(this.$route.query.proId),
|
2025-11-05 16:42:09 +08:00
|
|
|
|
},
|
|
|
|
|
|
defaultParams,
|
|
|
|
|
|
selectedRow: {},
|
|
|
|
|
|
uploadType: ['标段文件', '标段文件2'],
|
|
|
|
|
|
form: {
|
|
|
|
|
|
delFileList: []
|
|
|
|
|
|
},
|
|
|
|
|
|
rules: {},
|
2025-11-26 16:47:07 +08:00
|
|
|
|
dialogVisible:false,
|
|
|
|
|
|
fileData:{}
|
|
|
|
|
|
|
2025-11-05 16:42:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
watch: {
|
|
|
|
|
|
uploadType: {
|
|
|
|
|
|
handler(newVal, oldVal) {
|
|
|
|
|
|
if (newVal && newVal.length > 0) {
|
|
|
|
|
|
// 立即清除验证
|
|
|
|
|
|
this.$refs.ruleForm && this.$refs.ruleForm.clearValidate()
|
|
|
|
|
|
if (oldVal && oldVal.length > 0) {
|
|
|
|
|
|
oldVal.forEach((item, index) => {
|
|
|
|
|
|
this.$delete(this.form, `fileList${index + 1}`)
|
|
|
|
|
|
this.$delete(this.rules, `fileList${index + 1}`)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
newVal.forEach((item, index) => {
|
|
|
|
|
|
this.$set(this.form, `fileList${index + 1}`, [])
|
|
|
|
|
|
this.$set(this.rules, `fileList${index + 1}`, [
|
|
|
|
|
|
{
|
|
|
|
|
|
required: true,
|
|
|
|
|
|
message: `请上传${item}`,
|
|
|
|
|
|
trigger: ['change'],
|
|
|
|
|
|
},
|
|
|
|
|
|
])
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
|
this.$refs.ruleForm &&
|
|
|
|
|
|
this.$refs.ruleForm.clearValidate()
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
immediate: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
created() {
|
|
|
|
|
|
this.proId = decryptWithSM4(this.$route.query.proId)
|
|
|
|
|
|
this.getDetail()
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
// 获取详情数据
|
|
|
|
|
|
async getDetail() {
|
|
|
|
|
|
try {
|
2025-11-26 16:47:07 +08:00
|
|
|
|
const res = await getProDetailAPI({ proId: this.proId, queryType: 2 })
|
|
|
|
|
|
console.log('res:', res);
|
2025-11-05 16:42:09 +08:00
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
|
this.detailData = res.data || {}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$message.error(res.msg || '获取详情失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取详情失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-11-26 16:47:07 +08:00
|
|
|
|
// 处理文件名
|
|
|
|
|
|
getFirstFileName(item) {
|
|
|
|
|
|
return item?.fileVoList?.[0]?.fileName || '--';
|
|
|
|
|
|
},
|
|
|
|
|
|
// 预览文件
|
|
|
|
|
|
viewFile(item) {
|
|
|
|
|
|
this.fileData = item.fileVoList[0]
|
|
|
|
|
|
console.log(this.fileData);
|
|
|
|
|
|
this.dialogVisible = true
|
|
|
|
|
|
},
|
|
|
|
|
|
handleCloseDialog() {
|
|
|
|
|
|
this.dialogVisible = false
|
|
|
|
|
|
this.fileData = {}
|
|
|
|
|
|
},
|
2025-11-05 16:42:09 +08:00
|
|
|
|
// 返回
|
|
|
|
|
|
handleClose() {
|
|
|
|
|
|
const obj = { path: "/analysis" }
|
|
|
|
|
|
this.$tab.closeOpenPage(obj)
|
|
|
|
|
|
},
|
|
|
|
|
|
// 处理单选框变化
|
|
|
|
|
|
handleRadioChange(row, index) {
|
|
|
|
|
|
this.selectedRow = row
|
|
|
|
|
|
console.log('选中的行数据:', row)
|
|
|
|
|
|
},
|
|
|
|
|
|
// 文件变化
|
|
|
|
|
|
handleFileChange(file, fileName) {
|
|
|
|
|
|
console.log(file)
|
|
|
|
|
|
this.form[fileName] = file
|
|
|
|
|
|
this.$refs.ruleForm && this.$refs.ruleForm.clearValidate([fileName])
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
// 文件删除时触发
|
|
|
|
|
|
handleDelFile(file) {
|
|
|
|
|
|
console.log(file)
|
|
|
|
|
|
const delPath =
|
|
|
|
|
|
file?.response?.fileRes?.filePath || file?.filePath || null
|
|
|
|
|
|
if (delPath) {
|
|
|
|
|
|
this.form.delFileList.push(delPath)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
validate(formName) {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
this.$refs[formName].validate((valid) => {
|
|
|
|
|
|
if (valid) {
|
|
|
|
|
|
resolve(this.form) // 校验成功返回表单数据
|
|
|
|
|
|
} else {
|
|
|
|
|
|
reject(new Error('数据未填写完整'))
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
/**验证 */
|
|
|
|
|
|
async handleUpload(formName) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (Object.keys(this.selectedRow).length === 0) {
|
|
|
|
|
|
this.$message.error('请选择要提交的标段')
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
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 {
|
|
|
|
|
|
if (this.loading) {
|
|
|
|
|
|
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 scoped lang="scss">
|
|
|
|
|
|
.analysis-detail-container {
|
|
|
|
|
|
padding: 24px;
|
|
|
|
|
|
background: linear-gradient(180deg, #F1F6FF 20%, #E5EFFF 100%);
|
|
|
|
|
|
height: calc(100vh - 84px);
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content-scrollable {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
|
padding-right: 6px; // 为滚动条留出空间
|
|
|
|
|
|
|
|
|
|
|
|
// 自定义滚动条样式
|
|
|
|
|
|
&::-webkit-scrollbar {
|
|
|
|
|
|
width: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&::-webkit-scrollbar-track {
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&::-webkit-scrollbar-thumb {
|
|
|
|
|
|
background: rgba(0, 0, 0, 0.2);
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: rgba(0, 0, 0, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.reset-btn {
|
|
|
|
|
|
width: 98px;
|
|
|
|
|
|
height: 36px;
|
|
|
|
|
|
background: #FFFFFF;
|
|
|
|
|
|
box-shadow: 0px 4px 8px 0px rgba(76, 76, 76, 0.2);
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: #f5f7fa;
|
|
|
|
|
|
color: #409EFF;
|
|
|
|
|
|
box-shadow: 0px 6px 12px 0px rgba(76, 76, 76, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.analysis-detail-card {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
box-shadow: 0px 4px 20px 0px rgba(31, 35, 55, 0.1);
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
margin-top: 5px;
|
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-card__header {
|
|
|
|
|
|
padding: 20px 24px;
|
|
|
|
|
|
border-bottom: 1px solid #EBEEF5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-card__body {
|
|
|
|
|
|
padding: 24px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.card-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
.header-icon {
|
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
|
color: #409EFF;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
h3 {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.analysis-detail-content {
|
|
|
|
|
|
.detail-row {
|
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
|
|
|
|
|
|
&:last-of-type {
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.detail-col {
|
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.detail-field {
|
|
|
|
|
|
.field-label {
|
|
|
|
|
|
color: #424242;
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.field-value {
|
|
|
|
|
|
background: #f5f7fa;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
min-height: 20px;
|
|
|
|
|
|
word-break: break-word;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.full-width {
|
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
|
|
|
|
|
|
.description-value {
|
|
|
|
|
|
min-height: 80px;
|
|
|
|
|
|
white-space: pre-wrap;
|
|
|
|
|
|
word-wrap: break-word;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.file-value {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
color: #1f72ea;
|
2025-11-26 16:47:07 +08:00
|
|
|
|
cursor: pointer;
|
2025-11-05 16:42:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.upload-container {
|
|
|
|
|
|
margin-top: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.upload-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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.upload-title {
|
|
|
|
|
|
span {
|
|
|
|
|
|
font-size: 14px !important;
|
|
|
|
|
|
color: red;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-26 16:47:07 +08:00
|
|
|
|
|
2025-11-05 16:42:09 +08:00
|
|
|
|
</style>
|