From 5afd9f97735894e558af58841d39e76da3c465f2 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 09 二月 2026 15:02:28 +0800
Subject: [PATCH] 公司 1.商机管理附件删除修改 2.商机管理添加新状态,并添加筛选条件 3.商机管理添加行业、信息化现状、主营业务收入等字段
---
src/views/salesManagement/opportunityManagement/index.vue | 315 +++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 250 insertions(+), 65 deletions(-)
diff --git a/src/views/salesManagement/opportunityManagement/index.vue b/src/views/salesManagement/opportunityManagement/index.vue
index 23cd728..888a9ac 100644
--- a/src/views/salesManagement/opportunityManagement/index.vue
+++ b/src/views/salesManagement/opportunityManagement/index.vue
@@ -2,16 +2,59 @@
<div class="app-container">
<!-- 鎼滅储鍖哄煙 -->
<div class="search_form">
- <el-form :model="searchForm" :inline="true" label-width="auto">
+ <el-form :model="searchForm" :inline="true">
<el-form-item label="瀹㈡埛鍚嶇О">
<el-input
v-model="searchForm.customerName"
placeholder="璇疯緭鍏ュ鎴峰悕绉�"
clearable
prefix-icon="Search"
- style="width: 200px"
+ style="width: 200px;"
@change="handleQuery"
/>
+ </el-form-item>
+ <el-form-item label="鍩庡競">
+ <el-input
+ v-model="searchForm.city"
+ placeholder="璇疯緭鍏ュ煄甯傚悕绉�"
+ clearable
+ prefix-icon="Search"
+ style="width: 200px"
+ @change="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="鐘舵��">
+ <el-select
+ v-model="searchForm.status"
+ placeholder="璇烽�夋嫨鐘舵��"
+ clearable
+ style="width: 160px"
+ @change="handleQuery"
+ >
+ <el-option
+ v-for="item in statusOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="褰曞叆浜�">
+ <el-select
+ v-model="searchForm.entryPerson"
+ placeholder="璇烽�夋嫨褰曞叆浜�"
+ clearable
+ filterable
+ style="width: 200px"
+ @change="handleQuery"
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.nickName"
+ />
+ </el-select>
</el-form-item>
<el-form-item label="褰曞叆鏃ユ湡锛�">
<el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
@@ -20,12 +63,10 @@
<el-form-item>
<el-button type="primary" @click="handleQuery">鎼滅储</el-button>
<el-button @click="resetQuery">閲嶇疆</el-button>
+ <el-button type="primary" @click="handleAdd">鏂板缓</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
</el-form-item>
</el-form>
- <div class="actions">
- <el-button type="primary" @click="handleAdd">鏂板缓</el-button>
- <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
- </div>
</div>
<!-- 琛ㄦ牸鍖哄煙 -->
<div class="table_list">
@@ -38,7 +79,7 @@
height="calc(100vh - 18.5em)"
stripe
>
- <el-table-column align="center" type="selection" width="55" />
+ <el-table-column align="center" type="selection" width="55" fixed="left"/>
<el-table-column align="center" label="搴忓彿" type="index" width="60" />
<el-table-column label="鐘舵��" prop="status" width="120">
<template #default="{ row }">
@@ -50,12 +91,13 @@
</el-tag>
</template>
</el-table-column>
- <el-table-column label="鐪佷唤" prop="province" show-overflow-tooltip width="120" />
+ <el-table-column label="鐪佷唤" prop="province" show-overflow-tooltip />
+ <el-table-column label="甯�" prop="city" show-overflow-tooltip/>
<el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" show-overflow-tooltip />
<el-table-column label="鍟嗘満鏉ユ簮" prop="businessSource" show-overflow-tooltip />
<!-- <el-table-column label="瀹㈡埛鎻忚堪" prop="description" show-overflow-tooltip min-width="200" /> -->
- <el-table-column label="褰曞叆浜�" prop="entryPerson" show-overflow-tooltip />
- <el-table-column label="鏇存柊鏃ユ湡" prop="updateTime">
+ <el-table-column label="褰曞叆浜�" prop="entryPerson" show-overflow-tooltip width="120" />
+ <el-table-column label="鏇存柊鏃ユ湡" prop="updateTime" width="120">
<template #default="{ row }">
{{ formatDate(row.updateTime) }}
</template>
@@ -113,7 +155,7 @@
<el-dialog
v-model="dialogFormVisible"
:title="operationType === 'add' ? '鏂板缓鍟嗘満' : operationType === 'edit' ? '缂栬緫鍟嗘満' : operationType === 'addOperation' ? '娣诲姞鍟嗘満' : '鍟嗘満璇︽儏'"
- width="600px"
+ width="1000px"
@close="closeDialog"
>
<el-form
@@ -135,12 +177,25 @@
</el-form-item>
<el-form-item label="鐪佷唤" prop="province">
- <el-select v-model="form.province" filterable placeholder="璇烽�夋嫨鐪佷唤" style="width: 100%" :disabled="operationType === 'detail' || operationType === 'addOperation'">
+ <el-select v-model="form.province" filterable placeholder="璇烽�夋嫨鐪佷唤"
+ @change="getCityListChange"
+ style="width: 100%" :disabled="operationType === 'detail' || operationType === 'addOperation'">
<el-option
v-for="item in provinceOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="甯�" prop="city">
+ <el-select v-model="form.city" filterable placeholder="璇烽�夋嫨甯�"
+ style="width: 100%" :disabled="operationType === 'detail' || operationType === 'addOperation'">
+ <el-option
+ v-for="item in cityOptions"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
/>
</el-select>
</el-form-item>
@@ -155,6 +210,40 @@
</el-select>
</el-form-item>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="琛屼笟">
+ <el-input v-model="form.industry" placeholder="璇疯緭鍏ヨ涓�" clearable :disabled="operationType === 'detail' || operationType === 'addOperation'" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓昏惀浜у搧">
+ <el-input v-model="form.mainProducts" placeholder="璇疯緭鍏ヤ富钀ヤ骇鍝�" clearable :disabled="operationType === 'detail' || operationType === 'addOperation'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="涓昏惀涓氬姟鏀跺叆">
+ <el-input v-model="form.mainBusinessRevenue" placeholder="璇疯緭鍏ヤ富钀ヤ笟鍔℃敹鍏�" clearable :disabled="operationType === 'detail' || operationType === 'addOperation'" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瀹㈡埛瑙勬ā">
+ <el-input v-model="form.customerScale" placeholder="璇疯緭鍏ュ鎴疯妯�" clearable :disabled="operationType === 'detail' || operationType === 'addOperation'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="24">
+ <el-form-item label="淇℃伅鍖栫幇鐘�">
+ <el-input v-model="form.informationState" placeholder="璇疯緭鍏ヤ俊鎭寲鐜扮姸" clearable :disabled="operationType === 'detail' || operationType === 'addOperation'" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
<el-form-item label="鍟嗘満鏉ユ簮" prop="businessSource">
<el-input v-model="form.businessSource" placeholder="璇疯緭鍏ュ晢鏈烘潵婧�" :disabled="operationType === 'detail' || operationType === 'addOperation'" />
</el-form-item>
@@ -165,7 +254,6 @@
type="textarea"
:rows="3"
placeholder="璇疯緭鍏ュ鎴锋弿杩�"
- maxlength="500"
show-word-limit
/>
</el-form-item>
@@ -205,6 +293,25 @@
</el-col>
</el-row>
</el-form>
+
+ <!-- 闄勪欢鏌ョ湅锛堜粎鍦ㄨ鎯呮ā寮忎笅鏄剧ず锛� -->
+ <div v-if="operationType === 'detail'" class="attachment-section">
+ <el-divider content-position="left">闄勪欢鏉愭枡</el-divider>
+ <div v-if="form.businessCommonFiles && form.businessCommonFiles.length > 0">
+ <el-table :data="form.businessCommonFiles" border stripe style="width: 100%">
+ <el-table-column label="闄勪欢鍚嶇О" prop="name" min-width="400" show-overflow-tooltip />
+ <el-table-column fixed="right" label="鎿嶄綔" width="150" align="center">
+ <template #default="scope">
+ <el-button link type="primary" size="small" @click="downloadAttachment(scope.row)">涓嬭浇</el-button>
+ <el-button link type="primary" size="small" @click="previewAttachment(scope.row)">棰勮</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ <div v-else style="text-align: center; padding: 20px; color: #999;">
+ 鏆傛棤闄勪欢
+ </div>
+ </div>
<!-- 鍙樻洿璁板綍鏃堕棿绾匡紙浠呭湪璇︽儏妯″紡涓嬫樉绀猴級 -->
<div v-if="operationType === 'detail'" class="change-history-section">
@@ -253,7 +360,9 @@
</el-dialog>
<!-- 闄勪欢鍒楄〃瀵硅瘽妗� -->
- <FileList ref="fileListRef" />
+ <FileList ref="fileListRef" @refresh="handleFileListRefresh" />
+ <!-- 鏂囦欢棰勮缁勪欢 -->
+ <filePreview ref="filePreviewRef" />
</div>
</template>
@@ -265,16 +374,17 @@
import useUserStore from '@/store/modules/user'
import dayjs from 'dayjs'
import { getToken } from '@/utils/auth'
-import {
- opportunityListPage,
- addOpportunity,
- updateOpportunity,
- delOpportunity,
- addDescription
+import {
+ opportunityListPage,
+ addOpportunity,
+ updateOpportunity,
+ delOpportunity,
+ addDescription, getProvinceList, getCityList
} from '@/api/salesManagement/opportunityManagement.js'
import { userListNoPage } from '@/api/system/user.js'
import {customerList, getSalesLedgerWithProducts} from '@/api/salesManagement/salesLedger.js'
import FileList from './fileList.vue'
+import filePreview from '@/components/filePreview/index.vue'
const { proxy } = getCurrentInstance()
const userStore = useUserStore()
@@ -296,6 +406,9 @@
// 鎼滅储琛ㄥ崟
const searchForm = reactive({
customerName: '',
+ city: '',
+ status: '',
+ entryPerson: '',
entryDate: [],
entryDateStart: '',
entryDateEnd: ''
@@ -309,7 +422,13 @@
id: undefined,
status: undefined,
province: '',
+ city: '',
customerName: '',
+ industry: '',
+ informationState: '',
+ mainBusinessRevenue: '',
+ customerScale: '',
+ mainProducts: '',
businessSource: '',
description: '',
entryPerson: userStore.nickName,
@@ -324,6 +443,8 @@
// FileList缁勪欢寮曠敤
const fileListRef = ref(null)
+const currentAttachmentRow = ref(null)
+const filePreviewRef = ref(null)
// 涓婁紶閰嶇疆
const upload = reactive({
@@ -362,47 +483,14 @@
{ value: '鏂板缓', label: '鏂板缓' },
{ value: '椤圭洰璺熻釜', label: '椤圭洰璺熻釜' },
{ value: '鍚堝悓绛剧害', label: '鍚堝悓绛剧害' },
+ { value: '澶囨鐢虫姤', label: '澶囨鐢虫姤' },
{ value: '椤圭洰浜や粯', label: '椤圭洰浜や粯' },
{ value: '椤圭洰楠屾敹', label: '椤圭洰楠屾敹' }
]
-// 鐪佷唤閫夐」锛堢ず渚嬶級
-const provinceOptions = [
- { value: '鍖椾含甯�', label: '鍖椾含甯�' },
- { value: '澶╂触甯�', label: '澶╂触甯�' },
- { value: '娌冲寳鐪�', label: '娌冲寳鐪�' },
- { value: '灞辫タ鐪�', label: '灞辫タ鐪�' },
- { value: '鍐呰挋鍙よ嚜娌诲尯', label: '鍐呰挋鍙よ嚜娌诲尯' },
- { value: '杈藉畞鐪�', label: '杈藉畞鐪�' },
- { value: '鍚夋灄鐪�', label: '鍚夋灄鐪�' },
- { value: '榛戦緳姹熺渷', label: '榛戦緳姹熺渷' },
- { value: '涓婃捣甯�', label: '涓婃捣甯�' },
- { value: '姹熻嫃鐪�', label: '姹熻嫃鐪�' },
- { value: '娴欐睙鐪�', label: '娴欐睙鐪�' },
- { value: '瀹夊窘鐪�', label: '瀹夊窘鐪�' },
- { value: '绂忓缓鐪�', label: '绂忓缓鐪�' },
- { value: '姹熻タ鐪�', label: '姹熻タ鐪�' },
- { value: '灞变笢鐪�', label: '灞变笢鐪�' },
- { value: '娌冲崡鐪�', label: '娌冲崡鐪�' },
- { value: '婀栧寳鐪�', label: '婀栧寳鐪�' },
- { value: '婀栧崡鐪�', label: '婀栧崡鐪�' },
- { value: '骞夸笢鐪�', label: '骞夸笢鐪�' },
- { value: '骞胯タ澹棌鑷不鍖�', label: '骞胯タ澹棌鑷不鍖�' },
- { value: '娴峰崡鐪�', label: '娴峰崡鐪�' },
- { value: '閲嶅簡甯�', label: '閲嶅簡甯�' },
- { value: '鍥涘窛鐪�', label: '鍥涘窛鐪�' },
- { value: '璐靛窞鐪�', label: '璐靛窞鐪�' },
- { value: '浜戝崡鐪�', label: '浜戝崡鐪�' },
- { value: '瑗胯棌鑷不鍖�', label: '瑗胯棌鑷不鍖�' },
- { value: '闄曡タ鐪�', label: '闄曡タ鐪�' },
- { value: '鐢樿們鐪�', label: '鐢樿們鐪�' },
- { value: '闈掓捣鐪�', label: '闈掓捣鐪�' },
- { value: '瀹佸鍥炴棌鑷不鍖�', label: '瀹佸鍥炴棌鑷不鍖�' },
- { value: '鏂扮枂缁村惥灏旇嚜娌诲尯', label: '鏂扮枂缁村惥灏旇嚜娌诲尯' },
- { value: '鍙版咕鐪�', label: '鍙版咕鐪�' },
- { value: '棣欐腐鐗瑰埆琛屾斂鍖�', label: '棣欐腐鐗瑰埆琛屾斂鍖�' },
- { value: '婢抽棬鐗瑰埆琛屾斂鍖�', label: '婢抽棬鐗瑰埆琛屾斂鍖�' }
-]
+// 鐪佷唤閫夐」
+const provinceOptions = ref([])
+const cityOptions = ref([])
// 鑾峰彇鐘舵�佹爣绛剧被鍨�
const getStatusTagType = (status) => {
@@ -410,7 +498,8 @@
'鏂板缓': 'info',
'椤圭洰璺熻釜': 'primary',
'鍚堝悓绛剧害': 'warning',
- '椤圭洰浜や粯': 'success',
+ '澶囨鐢虫姤': 'primary',
+ '椤圭洰浜や粯': 'success',
'椤圭洰楠屾敹': 'success'
}
return typeMap[status] || 'info'
@@ -422,7 +511,8 @@
'鏂板缓': '鏂板缓',
'椤圭洰璺熻釜': '椤圭洰璺熻釜',
'鍚堝悓绛剧害': '鍚堝悓绛剧害',
- '椤圭洰浜や粯': '椤圭洰浜や粯',
+ '澶囨鐢虫姤': '澶囨鐢虫姤',
+ '椤圭洰浜や粯': '椤圭洰浜や粯',
'椤圭洰楠屾敹': '椤圭洰楠屾敹'
}
return textMap[status] || '鏈煡'
@@ -444,6 +534,9 @@
const resetQuery = () => {
Object.assign(searchForm, {
customerName: '',
+ city: '',
+ status: '',
+ entryPerson: '',
entryDate: [],
entryDateStart: '',
entryDateEnd: ''
@@ -516,8 +609,16 @@
customerList().then((res) => {
customerOption.value = res
})
+ getProvinceList().then(res => {
+ provinceOptions.value = res.data
+ })
dialogFormVisible.value = true
+}
+const getCityListChange = (id) => {
+ getCityList({provinceId: id}).then(res => {
+ cityOptions.value = res.data
+ })
}
// 娣诲姞鎿嶄綔
@@ -596,8 +697,43 @@
customerOption.value = res
})
+ // 鍔犺浇鐪佷唤鍒楄〃
+ await getProvinceList().then(res => {
+ provinceOptions.value = res.data
+ })
+
+ // 濡傛灉鍚庣杩斿洖鐨勬槸name锛岄渶瑕佽浆鎹负id
+ let provinceId = row.province
+ let cityId = row.city
+
+ // 濡傛灉province鏄痭ame瀛楃涓诧紝鏌ユ壘瀵瑰簲鐨刬d
+ if (row.province && typeof row.province === 'string' && !/^\d+$/.test(row.province)) {
+ const provinceOption = provinceOptions.value.find(item => item.name === row.province)
+ if (provinceOption) {
+ provinceId = provinceOption.id
+ // 鍔犺浇瀵瑰簲鐨勫煄甯傚垪琛�
+ await getCityList({ provinceId: provinceId }).then(res => {
+ cityOptions.value = res.data
+ // 濡傛灉city鏄痭ame瀛楃涓诧紝鏌ユ壘瀵瑰簲鐨刬d
+ if (row.city && typeof row.city === 'string' && !/^\d+$/.test(row.city)) {
+ const cityOption = cityOptions.value.find(item => item.name === row.city)
+ if (cityOption) {
+ cityId = cityOption.id
+ }
+ }
+ })
+ }
+ } else if (row.province) {
+ // 濡傛灉province鏄痠d锛岀洿鎺ュ姞杞藉煄甯傚垪琛�
+ await getCityList({ id: row.province }).then(res => {
+ cityOptions.value = res.data
+ })
+ }
+
// 浣跨敤褰撳墠璐﹀彿鍜屽綋澶╂棩鏈熶綔涓洪粯璁ゅ��
Object.assign(form, row, {
+ province: provinceId, // 浣跨敤杞崲鍚庣殑id
+ city: cityId, // 浣跨敤杞崲鍚庣殑id
entryPerson: userStore.nickName, // 璁剧疆褰曞叆浜轰负褰撳墠璐﹀彿
entryDate: dayjs().format('YYYY-MM-DD') // 璁剧疆褰曞叆鏃堕棿涓哄綋澶�
})
@@ -619,6 +755,10 @@
tempFileIds = fileList.value.map(item => item.tempId)
}
+ // 灏嗙渷浠藉拰甯傜殑id杞崲涓簄ame
+ const provinceName = form.province ? provinceOptions.value.find(item => item.id === form.province)?.name || form.province : ''
+ const cityName = form.city ? cityOptions.value.find(item => item.id === form.city)?.name || form.city : ''
+
let api
let successMessage
let submitData
@@ -628,6 +768,8 @@
successMessage = '鏂板缓鎴愬姛'
submitData = {
...form,
+ province: provinceName, // 浼爊ame鑰屼笉鏄痠d
+ city: cityName, // 浼爊ame鑰屼笉鏄痠d
tempFileIds: tempFileIds,
type: 9 // 鍟嗘満绠$悊鐨勭被鍨嬫爣璇�
}
@@ -649,6 +791,8 @@
successMessage = '淇敼鎴愬姛'
submitData = {
...form,
+ province: provinceName, // 浼爊ame鑰屼笉鏄痠d
+ city: cityName, // 浼爊ame鑰屼笉鏄痠d
tempFileIds: tempFileIds,
type: 9 // 鍟嗘満绠$悊鐨勭被鍨嬫爣璇�
}
@@ -703,9 +847,15 @@
const resetForm = () => {
Object.assign(form, {
id: undefined,
- status: '鏂板缓',
+ status: '',
province: '',
+ city: '',
customerName: '',
+ industry: '',
+ informationState: '',
+ mainBusinessRevenue: '',
+ customerScale: '',
+ mainProducts: '',
businessSource: '',
description: '',
entryPerson: userStore.nickName,
@@ -760,10 +910,45 @@
// 鏌ョ湅闄勪欢
function handleAttachment(row) {
- fileListRef.value.open(row.businessCommonFiles)
+ currentAttachmentRow.value = row
+ fileListRef.value.open(row.businessCommonFiles, row.id)
}
-onMounted(() => {
+// 涓嬭浇闄勪欢锛堣鎯呴〉闈級
+function downloadAttachment(row) {
+ proxy.$download.name(row.url)
+}
+
+// 棰勮闄勪欢锛堣鎯呴〉闈級
+function previewAttachment(row) {
+ if (filePreviewRef.value) {
+ filePreviewRef.value.open(row.url)
+ } else {
+ // 濡傛灉娌℃湁棰勮缁勪欢锛岀洿鎺ユ墦寮�閾炬帴
+ window.open(row.url, '_blank')
+ }
+}
+
+// 闄勪欢鍒楄〃鍒锋柊
+function handleFileListRefresh(rowId) {
+ // 閲嶆柊鑾峰彇鍒楄〃鏁版嵁
+ getList()
+ // 绛夊緟鍒楄〃鏁版嵁鏇存柊鍚庯紝鎵惧埌瀵瑰簲鐨勮骞舵洿鏂伴檮浠跺垪琛�
+ setTimeout(() => {
+ if (currentAttachmentRow.value && tableData.value) {
+ const updatedRow = tableData.value.find(item => item.id === currentAttachmentRow.value.id)
+ if (updatedRow && updatedRow.businessCommonFiles) {
+ currentAttachmentRow.value = updatedRow
+ fileListRef.value.open(updatedRow.businessCommonFiles, updatedRow.id)
+ }
+ }
+ }, 300)
+}
+
+onMounted(async () => {
+ // 鍔犺浇鐢ㄦ埛鍒楄〃渚涙悳绱娇鐢�
+ const userLists = await userListNoPage()
+ userList.value = userLists.data
getList()
})
</script>
--
Gitblit v1.9.3