<template>
|
<div class="app-container">
|
<!-- 页面标题栏 -->
|
<div class="page-header">
|
<h2>企业门户</h2>
|
<div class="header-actions">
|
<el-button @click="handlePreview" :icon="View" type="info" plain>预览</el-button>
|
<el-button @click="toggleEdit" :icon="isEdit ? 'Close' : 'Edit'" :type="isEdit ? 'default' : 'primary'">
|
{{ isEdit ? '取消编辑' : '编辑' }}
|
</el-button>
|
</div>
|
</div>
|
|
<!-- 企业信息卡片 -->
|
<div class="enterprise-info-card" v-loading="loading">
|
<!-- 基本信息区域 -->
|
<div class="info-section">
|
<div class="section-header">
|
<h3>基本信息</h3>
|
</div>
|
<el-descriptions :column="2" border class="info-descriptions">
|
<el-descriptions-item label="公司名称">
|
<el-input v-if="isEdit" v-model="form.companyName" placeholder="请输入公司名称" clearable />
|
<span v-else class="content-text">{{ form.companyName || '-' }}</span>
|
</el-descriptions-item>
|
<el-descriptions-item label="联系人">
|
<el-input v-if="isEdit" v-model="form.contactPerson" placeholder="请输入联系人" clearable />
|
<span v-else class="content-text">{{ form.contactPerson || '-' }}</span>
|
</el-descriptions-item>
|
<el-descriptions-item label="联系电话">
|
<el-input v-if="isEdit" v-model="form.contactPhone" placeholder="请输入联系电话" clearable />
|
<span v-else class="content-text">{{ form.contactPhone || '-' }}</span>
|
</el-descriptions-item>
|
<el-descriptions-item label="公司地址">
|
<el-input v-if="isEdit" v-model="form.companyAddress" placeholder="请输入公司地址" clearable />
|
<span v-else class="content-text">{{ form.companyAddress || '-' }}</span>
|
</el-descriptions-item>
|
<el-descriptions-item label="公司网站">
|
<el-input v-if="isEdit" v-model="form.website" placeholder="请输入公司网站" clearable />
|
<a v-else-if="form.website" :href="form.website" target="_blank" class="link-text">{{ form.website }}</a>
|
<span v-else class="content-text">-</span>
|
</el-descriptions-item>
|
</el-descriptions>
|
</div>
|
|
<!-- Logo和二维码区域 -->
|
<div class="info-section">
|
<div class="section-header">
|
<h3>企业标识</h3>
|
</div>
|
<div class="logo-qr-container">
|
<!-- 公司Logo -->
|
<div class="upload-item">
|
<span class="upload-label">公司Logo</span>
|
<div class="upload-wrapper">
|
<el-upload
|
v-if="isEdit"
|
class="logo-uploader"
|
:show-file-list="false"
|
:before-upload="(file) => beforeLogoUpload(file, 'companyLogo')"
|
action="#">
|
<img v-if="form.companyLogo" :src="'/file/preview?url=' + form.companyLogo" class="uploaded-image" />
|
<div v-else class="upload-placeholder">
|
<el-icon class="upload-icon"><Plus /></el-icon>
|
<span class="upload-text">上传Logo</span>
|
</div>
|
</el-upload>
|
<img
|
v-else-if="form.companyLogo"
|
:src="'/file/preview?url=' + form.companyLogo"
|
class="display-image"
|
/>
|
<div v-else class="empty-placeholder">
|
<el-icon :size="40"><Picture /></el-icon>
|
<span>暂无Logo</span>
|
</div>
|
</div>
|
</div>
|
|
<!-- 二维码 -->
|
<div class="upload-item">
|
<span class="upload-label">二维码</span>
|
<div class="upload-wrapper">
|
<el-upload
|
v-if="isEdit"
|
class="qr-uploader"
|
:show-file-list="false"
|
:before-upload="(file) => beforeLogoUpload(file, 'qrCode')"
|
action="#">
|
<img v-if="form.qrCode" :src="'/file/preview?url=' + form.qrCode" class="uploaded-image" />
|
<div v-else class="upload-placeholder">
|
<el-icon class="upload-icon"><Plus /></el-icon>
|
<span class="upload-text">上传二维码</span>
|
</div>
|
</el-upload>
|
<img
|
v-else-if="form.qrCode"
|
:src="'/file/preview?url=' + form.qrCode"
|
class="display-image"
|
/>
|
<div v-else class="empty-placeholder">
|
<el-icon :size="40"><Picture /></el-icon>
|
<span>暂无二维码</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 公司简介 -->
|
<div class="info-section">
|
<div class="section-header">
|
<h3>公司简介</h3>
|
</div>
|
<div class="content-editor">
|
<el-input
|
v-if="isEdit"
|
v-model="form.companyIntro"
|
type="textarea"
|
:rows="6"
|
maxlength="2000"
|
show-word-limit
|
placeholder="请输入公司简介..."
|
/>
|
<div v-else class="content-display" v-html="form.companyIntro || '<span class=\'empty-text\'>暂无公司简介</span>'"></div>
|
</div>
|
</div>
|
|
<!-- 产品介绍 -->
|
<div class="info-section">
|
<div class="section-header">
|
<h3>产品介绍</h3>
|
</div>
|
<div class="content-editor">
|
<el-input
|
v-if="isEdit"
|
v-model="form.productIntro"
|
type="textarea"
|
:rows="6"
|
maxlength="2000"
|
show-word-limit
|
placeholder="请输入产品介绍..."
|
/>
|
<div v-else class="content-display" v-html="form.productIntro || '<span class=\'empty-text\'>暂无产品介绍</span>'"></div>
|
</div>
|
</div>
|
|
<!-- 设备介绍 -->
|
<div class="info-section">
|
<div class="section-header">
|
<h3>设备介绍</h3>
|
</div>
|
<div class="content-editor">
|
<el-input
|
v-if="isEdit"
|
v-model="form.equipmentIntro"
|
type="textarea"
|
:rows="6"
|
maxlength="2000"
|
show-word-limit
|
placeholder="请输入设备介绍..."
|
/>
|
<div v-else class="content-display" v-html="form.equipmentIntro || '<span class=\'empty-text\'>暂无设备介绍</span>'"></div>
|
</div>
|
</div>
|
|
<!-- 操作按钮 -->
|
<div v-if="isEdit" class="form-actions">
|
<el-button type="primary" @click="handleSave" :loading="saving" size="large">保存</el-button>
|
<el-button @click="handleCancel" size="large">取消</el-button>
|
</div>
|
</div>
|
|
<!-- 预览弹窗 -->
|
<el-dialog
|
v-model="previewVisible"
|
title="企业信息预览"
|
width="70%"
|
:destroy-on-close="true">
|
<div class="preview-content">
|
<div class="preview-header">
|
<img v-if="form.companyLogo" :src="'/file/preview?url=' + form.companyLogo" class="preview-logo" />
|
<div class="preview-title">
|
<h1>{{ form.companyName || '公司名称' }}</h1>
|
<p v-if="form.website">{{ form.website }}</p>
|
</div>
|
</div>
|
<el-divider />
|
<div class="preview-section">
|
<h4>联系方式</h4>
|
<p>联系人:{{ form.contactPerson || '-' }}</p>
|
<p>联系电话:{{ form.contactPhone || '-' }}</p>
|
<p>公司地址:{{ form.companyAddress || '-' }}</p>
|
</div>
|
<div class="preview-section">
|
<h4>公司简介</h4>
|
<div v-html="form.companyIntro || '暂无简介'"></div>
|
</div>
|
<div class="preview-section">
|
<h4>产品介绍</h4>
|
<div v-html="form.productIntro || '暂无介绍'"></div>
|
</div>
|
<div class="preview-section">
|
<h4>设备介绍</h4>
|
<div v-html="form.equipmentIntro || '暂无介绍'"></div>
|
</div>
|
<div v-if="form.qrCode" class="preview-section preview-qr">
|
<h4>扫码关注</h4>
|
<img :src="'/file/preview?url=' + form.qrCode" class="qr-image" />
|
</div>
|
</div>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted } from 'vue'
|
import { ElMessage } from 'element-plus'
|
import { Plus, Picture, View } from '@element-plus/icons-vue'
|
import { getEnterpriseInfo, saveEnterpriseInfo, uploadLogo, uploadQrCode } from '@/api/basicData/enterpriseInfo.js'
|
|
const { proxy } = getCurrentInstance()
|
|
const loading = ref(false)
|
const saving = ref(false)
|
const isEdit = ref(false)
|
const previewVisible = ref(false)
|
const uploadType = ref('')
|
|
const form = reactive({
|
id: null,
|
companyName: '',
|
companyLogo: '',
|
companyIntro: '',
|
productIntro: '',
|
equipmentIntro: '',
|
contactPerson: '',
|
contactPhone: '',
|
companyAddress: '',
|
website: '',
|
qrCode: ''
|
})
|
|
// 深拷贝原始数据,用于取消时恢复
|
let originalForm = {}
|
|
// 获取企业信息
|
const fetchInfo = () => {
|
loading.value = true
|
getEnterpriseInfo().then(res => {
|
if (res.code === 200 && res.data) {
|
Object.assign(form, res.data)
|
originalForm = JSON.parse(JSON.stringify(res.data))
|
}
|
}).finally(() => {
|
loading.value = false
|
})
|
}
|
|
// 切换编辑模式
|
const toggleEdit = () => {
|
if (isEdit.value) {
|
// 取消编辑,恢复原始数据
|
Object.assign(form, originalForm)
|
isEdit.value = false
|
} else {
|
// 进入编辑模式
|
originalForm = JSON.parse(JSON.stringify(form))
|
isEdit.value = true
|
}
|
}
|
|
// 预览
|
const handlePreview = () => {
|
previewVisible.value = true
|
}
|
|
// 文件上传前校验
|
const beforeLogoUpload = (file, type) => {
|
const isImage = file.type.startsWith('image/')
|
const isLt2M = file.size / 1024 / 1024 < 2
|
|
if (!isImage) {
|
ElMessage.error('只能上传图片文件!')
|
return false
|
}
|
if (!isLt2M) {
|
ElMessage.error('图片大小不能超过 2MB!')
|
return false
|
}
|
|
uploadType.value = type
|
uploadFileReq(file)
|
return false
|
}
|
|
// 上传文件请求
|
const uploadFileReq = (file) => {
|
const uploadFn = uploadType.value === 'companyLogo' ? uploadLogo : uploadQrCode
|
uploadFn(file).then(res => {
|
if (res.code === 200) {
|
const path = res.data.tempPath
|
if (uploadType.value === 'companyLogo') {
|
form.companyLogo = path
|
} else {
|
form.qrCode = path
|
}
|
ElMessage.success('上传成功')
|
} else {
|
ElMessage.error(res.msg || '上传失败')
|
}
|
}).catch(() => {
|
ElMessage.error('上传失败')
|
})
|
}
|
|
// 保存
|
const handleSave = () => {
|
saving.value = true
|
saveEnterpriseInfo(form).then(res => {
|
if (res.code === 200) {
|
ElMessage.success('保存成功')
|
isEdit.value = false
|
fetchInfo()
|
} else {
|
ElMessage.error(res.msg || '保存失败')
|
}
|
}).finally(() => {
|
saving.value = false
|
})
|
}
|
|
// 取消
|
const handleCancel = () => {
|
Object.assign(form, originalForm)
|
isEdit.value = false
|
}
|
|
onMounted(() => {
|
fetchInfo()
|
})
|
</script>
|
|
<style scoped lang="scss">
|
.page-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 16px 24px;
|
background: #fff;
|
border-radius: 8px;
|
margin-bottom: 16px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
h2 {
|
margin: 0;
|
font-size: 20px;
|
font-weight: 600;
|
color: #303133;
|
}
|
|
.header-actions {
|
display: flex;
|
gap: 10px;
|
}
|
}
|
|
.enterprise-info-card {
|
background: #fff;
|
padding: 24px;
|
border-radius: 8px;
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
}
|
|
.info-section {
|
margin-bottom: 32px;
|
|
&:last-of-type {
|
margin-bottom: 0;
|
}
|
|
.section-header {
|
margin-bottom: 16px;
|
|
h3 {
|
margin: 0;
|
font-size: 16px;
|
font-weight: 600;
|
color: #303133;
|
padding-bottom: 10px;
|
border-bottom: 2px solid #409eff;
|
display: inline-block;
|
position: relative;
|
|
&::after {
|
content: '';
|
position: absolute;
|
left: 0;
|
bottom: -2px;
|
width: 60px;
|
height: 2px;
|
background-color: #409eff;
|
}
|
}
|
}
|
}
|
|
.info-descriptions {
|
:deep(.el-descriptions__label) {
|
width: 120px;
|
background-color: #f5f7fa;
|
font-weight: 500;
|
color: #606266;
|
}
|
|
:deep(.el-descriptions__content) {
|
color: #303133;
|
}
|
}
|
|
.content-text {
|
color: #606266;
|
}
|
|
.link-text {
|
color: #409eff;
|
text-decoration: none;
|
|
&:hover {
|
text-decoration: underline;
|
}
|
}
|
|
.logo-qr-container {
|
display: flex;
|
gap: 40px;
|
}
|
|
.upload-item {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
|
.upload-label {
|
font-size: 14px;
|
color: #606266;
|
margin-bottom: 12px;
|
font-weight: 500;
|
}
|
|
.upload-wrapper {
|
width: 140px;
|
height: 140px;
|
}
|
}
|
|
/* el-upload 根节点是外层 div,真正触发区在内层 .el-upload,需让内层铺满外层虚线框 */
|
.logo-uploader,
|
.qr-uploader {
|
display: flex;
|
flex-direction: column;
|
box-sizing: border-box;
|
width: 140px;
|
height: 140px;
|
border: 1px dashed #d9d9d9;
|
border-radius: 8px;
|
cursor: pointer;
|
transition: all 0.3s;
|
overflow: hidden;
|
|
:deep(.el-upload) {
|
flex: 1;
|
min-height: 0;
|
width: 100%;
|
display: flex !important;
|
flex-direction: column;
|
align-items: stretch;
|
box-sizing: border-box;
|
border: none;
|
outline: none;
|
}
|
|
:deep(.uploaded-image),
|
:deep(.upload-placeholder) {
|
flex: 1 1 auto;
|
min-height: 0;
|
min-width: 0;
|
width: 100%;
|
}
|
|
&:hover {
|
border-color: #409eff;
|
}
|
|
:deep(.uploaded-image) {
|
object-fit: contain;
|
}
|
|
:deep(.upload-placeholder) {
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
align-items: center;
|
background: #fafafa;
|
color: #8c939d;
|
|
.upload-icon {
|
font-size: 32px;
|
margin-bottom: 8px;
|
}
|
|
.upload-text {
|
font-size: 12px;
|
}
|
}
|
}
|
|
.display-image {
|
width: 140px;
|
height: 140px;
|
object-fit: contain;
|
border-radius: 8px;
|
border: 1px solid #e4e7ed;
|
}
|
|
.empty-placeholder {
|
width: 140px;
|
height: 140px;
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
align-items: center;
|
background: #fafafa;
|
border-radius: 8px;
|
border: 1px dashed #e4e7ed;
|
color: #c0c4cc;
|
|
span {
|
margin-top: 8px;
|
font-size: 12px;
|
}
|
}
|
|
.content-editor {
|
:deep(.el-textarea__inner) {
|
border-radius: 6px;
|
font-size: 14px;
|
line-height: 1.8;
|
}
|
}
|
|
.content-display {
|
padding: 16px 20px;
|
background: #fafafa;
|
border-radius: 6px;
|
border: 1px solid #ebeef5;
|
line-height: 1.8;
|
color: #606266;
|
min-height: 120px;
|
white-space: pre-wrap;
|
|
:deep(.empty-text) {
|
color: #c0c4cc;
|
font-style: italic;
|
}
|
}
|
|
.form-actions {
|
display: flex;
|
justify-content: center;
|
gap: 16px;
|
padding-top: 24px;
|
margin-top: 16px;
|
border-top: 1px solid #ebeef5;
|
}
|
|
/* 预览弹窗样式 */
|
.preview-content {
|
.preview-header {
|
display: flex;
|
align-items: center;
|
gap: 20px;
|
padding: 20px;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
border-radius: 8px;
|
color: #fff;
|
margin-bottom: 20px;
|
|
.preview-logo {
|
width: 80px;
|
height: 80px;
|
object-fit: contain;
|
background: #fff;
|
border-radius: 8px;
|
padding: 8px;
|
}
|
|
.preview-title {
|
h1 {
|
margin: 0 0 8px 0;
|
font-size: 28px;
|
font-weight: 600;
|
}
|
|
p {
|
margin: 0;
|
opacity: 0.9;
|
font-size: 14px;
|
}
|
}
|
}
|
|
.preview-section {
|
margin-bottom: 24px;
|
|
h4 {
|
font-size: 16px;
|
font-weight: 600;
|
color: #303133;
|
margin: 0 0 12px 0;
|
padding-bottom: 8px;
|
border-bottom: 1px solid #ebeef5;
|
}
|
|
p {
|
margin: 8px 0;
|
color: #606266;
|
line-height: 1.6;
|
}
|
|
:deep(div) {
|
line-height: 1.8;
|
color: #606266;
|
white-space: pre-wrap;
|
}
|
}
|
|
.preview-qr {
|
text-align: center;
|
|
.qr-image {
|
width: 150px;
|
height: 150px;
|
margin-top: 12px;
|
border-radius: 8px;
|
border: 1px solid #ebeef5;
|
}
|
}
|
}
|
|
:deep(.el-divider) {
|
margin: 16px 0;
|
}
|
</style>
|