| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |