修复缺陷

pull/853/head
wersd 2025-06-18 22:54:39 +08:00
parent 3ee254dce0
commit 1bd61a1464
11 changed files with 198 additions and 43 deletions

View File

@ -4,7 +4,7 @@ NODE_ENV=production
VITE_DEV=false
# 请求路径
VITE_BASE_URL='http://localhost:48080'
VITE_BASE_URL='http://www.sujieguanli.top:88'
# 文件上传类型server - 后端上传, client - 前端直连上传仅支持S3服务
VITE_UPLOAD_TYPE=client

View File

@ -12,6 +12,7 @@ export interface StationSiteVO {
locationLat: number // 定位纬度
locationName: string // 定位名称
estimatedPiles: number // 可建充电桩数
parkingSpace: number //总车位数
siteType: number // 场地类型
siteStatus: number // 场地状态
ownerUserId: number // 责任人编号

View File

@ -11,7 +11,8 @@ const props = defineProps({
fullscreen: propTypes.bool.def(true),
width: propTypes.oneOfType([String, Number]).def('60%'),
scroll: propTypes.bool.def(false), // maxHeight
maxHeight: propTypes.oneOfType([String, Number]).def('400px')
maxHeight: propTypes.oneOfType([String, Number]).def('400px') ,
closeOnClickModal: propTypes.bool.def(true)
})
const getBindValue = computed(() => {
@ -60,7 +61,7 @@ const dialogStyle = computed(() => {
<template>
<ElDialog
v-bind="getBindValue"
:close-on-click-modal="true"
:close-on-click-modal="props.closeOnClickModal"
:fullscreen="isFullscreen"
:width="width"
destroy-on-close

View File

@ -95,7 +95,7 @@ const editorConfig = computed((): IEditorConfig => {
// 100
maxNumberOfFiles: 10,
// ['image/*'] []
allowedFileTypes: ['image/*'],
allowedFileTypes: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp', 'image/*'],
// http header
headers: {

View File

@ -1,5 +1,5 @@
<template>
<Dialog v-model="dialogVisible" :title="dialogTitle">
<Dialog v-model="dialogVisible" :title="dialogTitle" :closeOnClickModal="false">
<el-form
ref="formRef"
v-loading="formLoading"

View File

@ -47,7 +47,7 @@
placement="top"
>
<span>{{ bizLabel }}</span>{{ item.creatorName }}
<span v-if="queryParams.bizId !== undefined && Array.isArray(item.customer) && item.customer.length > 0 && item.customer[0].name" style="margin-left: 8px;">
<span v-if="queryParams.bizId === undefined && Array.isArray(item.customer) && item.customer.length > 0 && item.customer[0].name" style="margin-left: 8px;">
客户名称{{ item.customer[0].name }}
</span>

View File

@ -1,6 +1,6 @@
<!-- 跟进记录的添加表单 -->
<template>
<Dialog v-model="dialogVisible" :title="`添加${bizLabel}记录`" width="70%">
<Dialog v-model="dialogVisible" :title="`添加${bizLabel}记录`" width="70%" :closeOnClickModal="false">
<el-form
ref="formRef"
v-loading="formLoading"
@ -23,7 +23,7 @@
</el-col>
<el-col :span="12" v-if="formData.bizType == BizTypeEnum.CRM_CUSTOMER">
<el-form-item label="选择联系人" prop="contactIds">
<el-select v-model="formData.contactIds" filterable placeholder="请选择联系人">
<el-select v-model="contactId" filterable placeholder="请选择联系人" @change="val => console.log('contactIds changed:', val)">
<el-option v-for="item in contactOptions" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
@ -58,6 +58,7 @@ defineOptions({ name: 'FollowUpRecordForm' })
const { t } = useI18n() //
const message = useMessage() //
const contactId = ref()
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
@ -86,7 +87,7 @@ const formData = ref<FollowUpFormData>({
fileUrls: [],
businesses: [],
contacts: [],
contactIds: []
contactIds: [],
})
const formRef = ref() // Ref
@ -124,7 +125,11 @@ watch(
//
const res = await ContactApi.getContactPageByCustomer({ customerId: val, pageSize: 100 })
contactOptions.value = res.list || []
//
if (formType.value === 'update' && contactOptions.value.length > 0) {
formData.value.contactIds = [contactOptions.value[0].id]
contactId.value = contactOptions.value[0].id
}
} else {
contactOptions.value = []
formData.value.contactIds = []
@ -142,11 +147,8 @@ const open = async (type: string, bizType: number, bizId: number, id?: number) =
formData.value.bizType = bizType
formData.value.bizId = bizId
formData.value.id = id || undefined // idundefined
if (formType.value === 'update') {
if (bizId === undefined || bizId === null) {
message.warning(t('记录ID不能为空'))
return
}
if (id === undefined || id === null) {
message.warning(t('记录ID不能为空'))
return
@ -171,10 +173,12 @@ const submitForm = async () => {
formLoading.value = true
try {
// contactIds
let contactIds = formData.value.contactIds
let contactIds = Array.isArray(formData.value.contactIds) ? formData.value.contactIds : []
if (!Array.isArray(contactIds)) {
contactIds = contactIds !== undefined && contactIds !== null ? [contactIds] : []
contactIds = contactIds.length > 0 ? [contactIds[0]] : []
}
const data = {
...formData.value,
contactIds,
@ -212,7 +216,8 @@ const resetForm = () => {
fileUrls: [],
businesses: [],
contacts: [],
contactIds: []
contactIds: [],
contactId: undefined
}
}
</script>

View File

@ -40,8 +40,24 @@
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="可建充电桩数" prop="estimatedPiles" >
<el-input-number v-model="formData.estimatedPiles" :min="0" :max="255" :step="1"/>
<el-form-item label="可建充电枪数" prop="estimatedPiles" >
<el-input-number v-model="formData.estimatedPiles" :min="1" :max="255" :step="1"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="地图选点" prop="locationName">
<el-input v-model="formData.locationName" placeholder="请选择地图位置" readonly>
<template #append>
<el-button @click="openMapDialog"></el-button>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="总车位数" prop="parkingSpace" >
<el-input-number v-model="formData.parkingSpace" :min="0" :max="255" :step="1"/>
</el-form-item>
</el-col>
</el-row>
@ -65,17 +81,6 @@
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="地图选点" prop="locationName">
<el-input v-model="formData.locationName" placeholder="请选择地图位置" readonly>
<template #append>
<el-button @click="openMapDialog"></el-button>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-dialog v-model="mapDialogVisible" title="获取经纬度" width="800px" append-to-body>
<iframe
v-if="mapDialogVisible"
@ -158,8 +163,9 @@
v-model="ownerDialogVisible"
width="400px"
>
<el-input v-model="ownerSearchKeyword" placeholder="搜索业主方" style="margin-bottom: 10px;" clearable />
<el-table
:data="customerList"
:data="filteredOwnerList"
style="width: 100%"
@current-change="handleOwnerSelect"
@ -181,8 +187,9 @@
v-model="managementDialogVisible"
width="400px"
>
<el-input v-model="managementSearchKeyword" placeholder="搜索物管方" style="margin-bottom: 10px;" clearable />
<el-table
:data="customerList"
:data="filteredManagementList"
style="width: 100%"
@current-change="handleManagementSelect"
highlight-current-row
@ -223,6 +230,7 @@ const formData = ref({
locationLng: 0,
locationLat: 0,
estimatedPiles: 0,
parkingSpace: 0,
siteStatus: undefined,
siteType: undefined,
ownerUserId: 0,
@ -341,6 +349,7 @@ const resetForm = () => {
locationLng: 0,
locationLat: 0,
estimatedPiles: 0,
parkingSpace: 0,
siteStatus: undefined,
siteType: undefined,
ownerUserId: useUserStore().getUser.id,
@ -365,6 +374,21 @@ const resetForm = () => {
formRef.value?.resetFields()
}
const ownerSearchKeyword = ref('');
const managementSearchKeyword = ref('');
const filteredOwnerList = computed(() =>
ownerSearchKeyword.value
? customerList.value.filter(item => item.name?.includes(ownerSearchKeyword.value))
: customerList.value
);
const filteredManagementList = computed(() =>
managementSearchKeyword.value
? customerList.value.filter(item => item.name?.includes(managementSearchKeyword.value))
: customerList.value
);
/** 初始化 **/
const openMapDialog = () => {
// url

View File

@ -25,9 +25,12 @@
<el-descriptions-item label="地址:">
{{ stationSite.areaName || '-' }}{{ stationSite.detailAddress }}
</el-descriptions-item>
<el-descriptions-item label="可建充电数:">
<el-descriptions-item label="可建充电数:">
{{ stationSite.estimatedPiles ?? '-' }}
</el-descriptions-item>
<el-descriptions-item label="总车位数:">
{{ stationSite.parkingSpace ?? '-' }}
</el-descriptions-item>
<el-descriptions-item label="业主方:">
{{ stationSite.ownerName || '-' }}
</el-descriptions-item>

View File

@ -17,15 +17,93 @@
<el-tab-pane label="动态记录"> <!--v-hasPermi="['crm:station-site:update']" v-hasPermi="['crm:station-site:transfor']" v-if="checkPermi(['crm:follow-up-record:query'])" -->
<FollowUpList :biz-id="stationSite.id" :biz-type="BizTypeEnum.CRM_STATION_SITE" />
</el-tab-pane>
</el-tabs>
<!-- <el-tabs>
<el-tab-pane label="操作日志">
<OperateLogV2 :log-list="logList" />
</el-tab-pane>
<!-- 附件标签页 -->
<el-tab-pane label="附件">
<div>附件内容</div>
<div v-if="loading" class="loading-container">
<el-skeleton :rows="5" animated />
</div>
<div v-else class="attachment-container">
<!-- 图片展示部分 -->
<div class="section" v-if="stationSite.picUrls?.length">
<h3 class="section-title">图片</h3>
<div class="image-list">
<div
v-for="(url, index) in stationSite.picUrls"
:key="index"
class="image-item"
>
<el-image
:src="url"
:preview-src-list="stationSite.picUrls"
:initial-index="index"
fit="cover"
class="thumbnail"
>
<template #error>
<div class="image-error">
<span>加载失败</span>
</div>
</template>
</el-image>
</div>
</div>
</div>
<!-- 文件展示部分 -->
<div class="section" v-if="stationSite.fileUrls?.length">
<h3 class="section-title">文件</h3>
<div class="file-list">
<div
v-for="(url, index) in stationSite.fileUrls"
:key="index"
class="file-item"
>
<el-icon class="file-icon"><Document /></el-icon>
<div class="file-info">
<a
:href="url"
target="_blank"
class="file-name"
@click.prevent="downloadFile(url)"
>
{{ extractFileName(url) }}
</a>
<div class="file-actions">
<el-button
type="primary"
link
@click="downloadFile(url)"
>
下载
</el-button>
<el-button
type="info"
link
@click="previewFile(url)"
>
预览
</el-button>
</div>
</div>
</div>
</div>
</div>
<!-- 空状态显示 -->
<el-empty
v-if="!stationSite.picUrls?.length && !stationSite.fileUrls?.length"
description="暂无附件数据"
/>
</div>
</el-tab-pane>
</el-tabs> -->
<!-- <el-tabs>
<el-tab-pane label="操作日志">
<OperateLogV2 :log-list="logList" />
</el-tab-pane>-->
</el-tabs>
</el-col>
@ -47,7 +125,7 @@ import { checkPermi } from "@/utils/permission"; // 权限判断函数
import FollowUpList from '@/views/crm/followup/components/FollowUpList.vue'
import StationSiteForm from '../StationSiteForm.vue'
import CrmTransferForm from '@/views/crm/permission/components/TransferForm.vue'
import { ElMessage, ElLoading } from 'element-plus'
const route = useRoute()
const stationSiteId = ref<number>()
@ -94,6 +172,49 @@ const getStationSite = async () => {
}
}
// URL
const extractFileName = (url) => {
try {
const path = new URL(url).pathname
return decodeURIComponent(path.substring(path.lastIndexOf('/') + 1))
} catch {
return decodeURIComponent(url.substring(url.lastIndexOf('/') + 1))
}
}
//
const downloadFile = (url) => {
const loadingInstance = ElLoading.service({
lock: true,
text: '文件下载中...',
background: 'rgba(0, 0, 0, 0.7)'
})
try {
const link = document.createElement('a')
link.href = url
link.download = extractFileName(url)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
ElMessage.success('文件下载开始')
} catch (error) {
ElMessage.error('下载失败: ' + error.message)
} finally {
setTimeout(() => {
loadingInstance.close()
}, 500)
}
}
//
const previewFile = (url) => {
if (url.match(/\.(png|jpg|jpeg|gif|webp)$/i)) {
//
window.open(url, '_blank')
}
}
/** 客户转移 */
const transferFormRef = ref<InstanceType<typeof CrmTransferForm>>() // ref
const transfer = () => {
@ -102,7 +223,7 @@ const transfer = () => {
const close = () => {
delView(unref(currentRoute))
push({ name: 'CrmStaionSite' })
push({ name: 'CrmStationSite' })
}
/** 初始化 */

View File

@ -100,7 +100,7 @@
</template>
</el-table-column>
<el-table-column label="推荐人" align="center" prop="recommenderName" width="150px"/>
<el-table-column label="可建充电数" align="center" prop="estimatedPiles" width="150px"/>
<el-table-column label="可建充电数" align="center" prop="estimatedPiles" width="150px"/>
<el-table-column label="场地类型" align="center" prop="siteType" width="150px">
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_STATION_SITE_TYPE" :value="scope.row.siteType" width="150px"/>