| | |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç份" prop="province" show-overflow-tooltip width="120" /> |
| | | <el-table-column label="客æ·åç§°" prop="customerName" show-overflow-tooltip width="230" /> |
| | | <el-table-column label="åæºæ¥æº" prop="businessSource" show-overflow-tooltip width="150" /> |
| | | <el-table-column label="å®¢æ·æè¿°" prop="description" show-overflow-tooltip min-width="200" /> |
| | | <el-table-column label="å½å
¥äºº" prop="entryPerson" show-overflow-tooltip width="120" /> |
| | | <el-table-column label="æ´æ°æ¥æ" prop="updateTime" width="120"> |
| | | <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"> |
| | | <template #default="{ row }"> |
| | | {{ formatDate(row.updateTime) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" fixed="right" width="130" align="center"> |
| | | <el-table-column label="æä½" fixed="right" width="220" align="center"> |
| | | <template #default="{ row }"> |
| | | <el-button |
| | | link |
| | |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="handleAddOperation(row)" |
| | | > |
| | | æ·»å æè¿° |
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="handleDetail(row)" |
| | | > |
| | | 详æ
|
| | | </el-button> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="handleAttachment(row)" |
| | | > |
| | | éä»¶ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å»ºåæº' : operationType === 'edit' ? 'ç¼è¾åæº' : 'åæºè¯¦æ
'" |
| | | :title="operationType === 'add' ? 'æ°å»ºåæº' : operationType === 'edit' ? 'ç¼è¾åæº' : operationType === 'addOperation' ? 'æ·»å åæº' : 'åæºè¯¦æ
'" |
| | | width="600px" |
| | | @close="closeDialog" |
| | | > |
| | |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ç份" prop="province"> |
| | | <el-select v-model="form.province" filterable placeholder="è¯·éæ©ç份" style="width: 100%" :disabled="operationType === 'detail'"> |
| | | <el-select v-model="form.province" filterable placeholder="è¯·éæ©ç份" style="width: 100%" :disabled="operationType === 'detail' || operationType === 'addOperation'"> |
| | | <el-option |
| | | v-for="item in provinceOptions" |
| | | :key="item.value" |
| | |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="客æ·åç§°" prop="customerName"> |
| | | <el-select v-model="form.customerName" placeholder="è¯·éæ©" clearable :disabled="operationType === 'detail'"> |
| | | <el-select v-model="form.customerName" placeholder="è¯·éæ©" clearable :disabled="operationType === 'detail' || operationType === 'addOperation'"> |
| | | <el-option v-for="item in customerOption" :key="item.customerName" :label="item.customerName" :value="item.customerName"> |
| | | {{ |
| | | item.customerName + "ââ" + item.taxpayerIdentificationNumber |
| | |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="åæºæ¥æº" prop="businessSource"> |
| | | <el-input v-model="form.businessSource" placeholder="请è¾å
¥åæºæ¥æº" :disabled="operationType === 'detail'" /> |
| | | <el-input v-model="form.businessSource" placeholder="请è¾å
¥åæºæ¥æº" :disabled="operationType === 'detail' || operationType === 'addOperation'" /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="å®¢æ·æè¿°" prop="description"> |
| | | <el-form-item label="å®¢æ·æè¿°" prop="description" v-if="operationType !== 'detail'"> |
| | | <el-input |
| | | v-model="form.description" |
| | | type="textarea" |
| | |
| | | placeholder="请è¾å
¥å®¢æ·æè¿°" |
| | | maxlength="500" |
| | | show-word-limit |
| | | :disabled="operationType === 'detail'" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äºº" prop="entryPerson"> |
| | | <el-select v-model="form.entryPerson" placeholder="è¯·éæ©" clearable @change="changs" :disabled="operationType === 'detail'"> |
| | | <el-select v-model="form.entryPerson" placeholder="è¯·éæ©" clearable @change="changs" :disabled="operationType === 'detail' || operationType === 'addOperation'"> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥æ¥æ" prop="entryDateStart"> |
| | | <el-date-picker style="width: 100%" v-model="form.entryDateStart" value-format="YYYY-MM-DD" format="YYYY-MM-DD" |
| | | type="date" placeholder="è¯·éæ©" clearable :disabled="operationType === 'detail'" /> |
| | | <el-form-item label="å½å
¥æ¥æ" prop="entryDate"> |
| | | <el-date-picker style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" |
| | | type="date" placeholder="è¯·éæ©" clearable :disabled="operationType === 'detail' || operationType === 'addOperation'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- éä»¶ä¸ä¼ ï¼é详æ
模å¼ä¸æ¾ç¤ºï¼ --> |
| | | <el-row :gutter="30" v-if="operationType !== 'detail'"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="éä»¶ææï¼"> |
| | | <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload |
| | | :headers="upload.headers" :data="upload.data" :before-upload="handleBeforeUpload" :on-error="handleUploadError" |
| | | :on-success="handleUploadSuccess" :on-remove="handleRemove"> |
| | | <el-button type="primary">ä¸ä¼ </el-button> |
| | | <template #tip> |
| | | <div class="el-upload__tip"> |
| | | æä»¶æ ¼å¼æ¯æ |
| | | docï¼docxï¼xlsï¼xlsxï¼pptï¼pptxï¼pdfï¼txtï¼xmlï¼jpgï¼jpegï¼pngï¼gifï¼bmpï¼rarï¼zipï¼7z |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <!-- åæ´è®°å½æ¶é´çº¿ï¼ä»
å¨è¯¦æ
模å¼ä¸æ¾ç¤ºï¼ --> |
| | | <div v-if="operationType === 'detail'" class="change-history-section"> |
| | | <el-divider content-position="left">åæ´è®°å½</el-divider> |
| | | <el-timeline> |
| | | <el-timeline-item |
| | | v-for="record in changeHistory" |
| | | :key="record.id" |
| | | :timestamp="record.timestamp" |
| | | :type="record.type === 'current' ? 'primary' : record.type === 'update' ? 'success' : 'info'" |
| | | :hollow="record.type === 'current'" |
| | | placement="top" |
| | | > |
| | | <el-card shadow="hover" class="timeline-card"> |
| | | <template #header> |
| | | <div class="card-header"> |
| | | <span class="action-type">{{ record.action }}</span> |
| | | <span class="operator">æä½äººï¼{{ record.operator }}</span> |
| | | </div> |
| | | </template> |
| | | <div class="change-content"> |
| | | <div class="status-change" v-if="record.status"> |
| | | <span class="label">ç¶æï¼</span> |
| | | <el-tag :type="record.type === 'current' ? 'primary' : 'info'" size="small"> |
| | | {{ getStatusLabel(record.status) }} |
| | | </el-tag> |
| | | </div> |
| | | <div class="description-change" v-if="record.description"> |
| | | <span class="label">å®¢æ·æè¿°ï¼</span> |
| | | <span class="description-text">{{ record.description }}</span> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </el-timeline-item> |
| | | </el-timeline> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- éä»¶åè¡¨å¯¹è¯æ¡ --> |
| | | <FileList ref="fileListRef" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import pagination from '@/components/PIMTable/Pagination.vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import dayjs from 'dayjs' |
| | | import { getToken } from '@/utils/auth' |
| | | import { |
| | | opportunityListPage, |
| | | addOpportunity, |
| | | updateOpportunity, |
| | | delOpportunity |
| | | delOpportunity, |
| | | addDescription |
| | | } from '@/api/salesManagement/opportunityManagement.js' |
| | | import { userListNoPage } from '@/api/system/user.js' |
| | | import { customerList } from '@/api/salesManagement/salesLedger.js' |
| | | import {customerList, getSalesLedgerWithProducts} from '@/api/salesManagement/salesLedger.js' |
| | | import FileList from './fileList.vue' |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const userStore = useUserStore() |
| | |
| | | const formRef = ref() |
| | | const form = reactive({ |
| | | id: undefined, |
| | | status: 'new', |
| | | status: undefined, |
| | | province: '', |
| | | customerName: '', |
| | | businessSource: '', |
| | | description: '', |
| | | entryPerson: userStore.nickName, |
| | | entryDateStart: dayjs().format('YYYY-MM-DD') |
| | | entryDate: dayjs().format('YYYY-MM-DD') |
| | | }) |
| | | |
| | | // åæ´è®°å½æ°æ®ï¼æ¨¡ææ°æ®ï¼ |
| | | const changeHistory = ref([]) |
| | | |
| | | // æä»¶å表 |
| | | const fileList = ref([]) |
| | | |
| | | // FileListç»ä»¶å¼ç¨ |
| | | const fileListRef = ref(null) |
| | | |
| | | // ä¸ä¼ é
ç½® |
| | | const upload = reactive({ |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/file/upload", |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | // ä¸ä¼ åæ° |
| | | data: { type: 9 } |
| | | }) |
| | | |
| | | // è·åç¶ææ ç¾ |
| | | const getStatusLabel = (statusValue) => { |
| | | const status = statusOptions.find(item => item.value === statusValue) |
| | | return status ? status.label : statusValue |
| | | } |
| | | |
| | | // 表åéªè¯è§å |
| | | const rules = reactive({ |
| | |
| | | entryPerson: [ |
| | | { required: true, message: 'è¯·éæ©å½å
¥äºº', trigger: 'change' } |
| | | ], |
| | | entryDateStart: [ |
| | | entryDate: [ |
| | | { required: true, message: 'è¯·éæ©å½å
¥æ¥æ', trigger: 'change' } |
| | | ] |
| | | }) |
| | | |
| | | // ç¶æé项 |
| | | const statusOptions = [ |
| | | { value: 'new', label: 'æ°å»º' }, |
| | | { value: 'tracking', label: '项ç®è·è¸ª' }, |
| | | { value: 'contract', label: 'ååç¾çº¦' }, |
| | | { value: 'delivery', label: '项ç®äº¤ä»' }, |
| | | { value: 'acceptance', label: '项ç®éªæ¶' } |
| | | { value: 'æ°å»º', label: 'æ°å»º' }, |
| | | { value: '项ç®è·è¸ª', label: '项ç®è·è¸ª' }, |
| | | { value: 'ååç¾çº¦', label: 'ååç¾çº¦' }, |
| | | { value: '项ç®äº¤ä»', label: '项ç®äº¤ä»' }, |
| | | { value: '项ç®éªæ¶', label: '项ç®éªæ¶' } |
| | | ] |
| | | |
| | | // ç份é项ï¼ç¤ºä¾ï¼ |
| | | const provinceOptions = [ |
| | | { value: 'beijing', label: 'å京å¸' }, |
| | | { value: 'tianjin', label: '天津å¸' }, |
| | | { value: 'hebei', label: 'æ²³åç' }, |
| | | { value: 'shanxi', label: '山西ç' }, |
| | | { value: 'neimenggu', label: 'å
èå¤èªæ²»åº' }, |
| | | { value: 'liaoning', label: 'è¾½å®ç' }, |
| | | { value: 'jilin', label: 'åæç' }, |
| | | { value: 'heilongjiang', label: 'é»é¾æ±ç' }, |
| | | { value: 'shanghai', label: '䏿µ·å¸' }, |
| | | { value: 'jiangsu', label: 'æ±èç' }, |
| | | { value: 'zhejiang', label: 'æµæ±ç' }, |
| | | { value: 'anhui', label: 'å®å¾½ç' }, |
| | | { value: 'fujian', label: 'ç¦å»ºç' }, |
| | | { value: 'jiangxi', label: 'æ±è¥¿ç' }, |
| | | { value: 'shandong', label: 'å±±ä¸ç' }, |
| | | { value: 'henan', label: 'æ²³åç' }, |
| | | { value: 'hubei', label: 'æ¹åç' }, |
| | | { value: 'hunan', label: 'æ¹åç' }, |
| | | { value: 'guangdong', label: '广ä¸ç' }, |
| | | { value: 'guangxi', label: '广西壮æèªæ²»åº' }, |
| | | { value: 'hainan', label: 'æµ·åç' }, |
| | | { value: 'chongqing', label: 'éåºå¸' }, |
| | | { value: 'sichuan', label: 'åå·ç' }, |
| | | { value: 'guizhou', label: 'è´µå·ç' }, |
| | | { value: 'yunnan', label: 'äºåç' }, |
| | | { value: 'xizang', label: '西èèªæ²»åº' }, |
| | | { value: 'shaanxi', label: 'é西ç' }, |
| | | { value: 'gansu', label: 'çèç' }, |
| | | { value: 'qinghai', label: 'éæµ·ç' }, |
| | | { value: 'ningxia', label: 'å®å¤åæèªæ²»åº' }, |
| | | { value: 'xinjiang', label: 'æ°çç»´å¾å°èªæ²»åº' }, |
| | | { value: 'taiwan', label: 'å°æ¹¾ç' }, |
| | | { value: 'xianggang', label: '馿¸¯ç¹å«è¡æ¿åº' }, |
| | | { value: 'aomen', 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: '馿¸¯ç¹å«è¡æ¿åº' }, |
| | | { value: 'æ¾³é¨ç¹å«è¡æ¿åº', label: 'æ¾³é¨ç¹å«è¡æ¿åº' } |
| | | ] |
| | | |
| | | // è·åç¶ææ ç¾ç±»å |
| | | const getStatusTagType = (status) => { |
| | | const typeMap = { |
| | | 'new': 'info', |
| | | 'tracking': 'primary', |
| | | 'contract': 'warning', |
| | | 'delivery': 'success', |
| | | 'acceptance': 'success' |
| | | 'æ°å»º': 'info', |
| | | '项ç®è·è¸ª': 'primary', |
| | | 'ååç¾çº¦': 'warning', |
| | | '项ç®äº¤ä»': 'success', |
| | | '项ç®éªæ¶': 'success' |
| | | } |
| | | return typeMap[status] || 'info' |
| | | } |
| | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const textMap = { |
| | | 'new': 'æ°å»º', |
| | | 'tracking': '项ç®è·è¸ª', |
| | | 'contract': 'ååç¾çº¦', |
| | | 'delivery': '项ç®äº¤ä»', |
| | | 'acceptance': '项ç®éªæ¶' |
| | | 'æ°å»º': 'æ°å»º', |
| | | '项ç®è·è¸ª': '项ç®è·è¸ª', |
| | | 'ååç¾çº¦': 'ååç¾çº¦', |
| | | '项ç®äº¤ä»': '项ç®äº¤ä»', |
| | | '项ç®éªæ¶': '项ç®éªæ¶' |
| | | } |
| | | return textMap[status] || 'æªç¥' |
| | | } |
| | |
| | | dialogFormVisible.value = true |
| | | } |
| | | |
| | | // æ·»å æä½ |
| | | const handleAddOperation = async (row) => { |
| | | operationType.value = 'addOperation' |
| | | |
| | | // å è½½ç¨æ·å表å客æ·å表 |
| | | let userLists = await userListNoPage() |
| | | userList.value = userLists.data |
| | | customerList().then((res) => { |
| | | customerOption.value = res |
| | | }) |
| | | |
| | | // 使ç¨å½åè¡æ°æ®ä½ä¸ºåºç¡ï¼ä½åªè½ä¿®æ¹ç¶æåå®¢æ·æè¿° |
| | | Object.assign(form, row, { |
| | | // ä¿çåå§åæºIDï¼ç¨äºå
³èæä½è®°å½ |
| | | status: row.status, |
| | | description: '', // æ¸
ç©ºå®¢æ·æè¿°ï¼å
è®¸éæ°å¡«å |
| | | entryPerson: userStore.nickName, // 设置å½å
¥äººä¸ºå½åè´¦å· |
| | | entryDate: dayjs().format('YYYY-MM-DD') // 设置å½å
¥æ¶é´ä¸ºå½å¤© |
| | | }) |
| | | dialogFormVisible.value = true |
| | | } |
| | | |
| | | // æ¥ç详æ
|
| | | const handleDetail = async (row) => { |
| | | operationType.value = 'detail' |
| | |
| | | Object.assign(form, row, { |
| | | entryDateStart: row.updateTime || row.entryDateStart |
| | | }) |
| | | |
| | | // çææ¨¡æåæ´è®°å½ |
| | | generateChangeHistory(row) |
| | | dialogFormVisible.value = true |
| | | } |
| | | |
| | | // çæåæ´è®°å½ |
| | | const generateChangeHistory = (row) => { |
| | | // 使ç¨businessDescriptionæ°ç»æ°æ®çæåæ´è®°å½ |
| | | const history = [] |
| | | |
| | | if (row.businessDescription && Array.isArray(row.businessDescription)) { |
| | | row.businessDescription.forEach((item, index) => { |
| | | history.push({ |
| | | id: item.id || index, |
| | | timestamp: item.entryDate || item.updateTime || item.createTime, |
| | | operator: item.entryPerson || 'ç³»ç»', |
| | | status: item.status, |
| | | description: item.description, |
| | | type: index === 0 ? 'current' : 'info', |
| | | action: index === 0 ? 'å½åç¶æ' : 'åå²è®°å½' |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | changeHistory.value = history |
| | | } |
| | | |
| | | // ç¼è¾åæº |
| | |
| | | customerOption.value = res |
| | | }) |
| | | |
| | | // 使ç¨updateTimeä½ä¸ºå½å
¥æ¶é´åæ¾ |
| | | // 使ç¨å½åè´¦å·åå½å¤©æ¥æä½ä¸ºé»è®¤å¼ |
| | | Object.assign(form, row, { |
| | | entryDateStart: row.updateTime || row.entryDateStart |
| | | entryPerson: userStore.nickName, // 设置å½å
¥äººä¸ºå½åè´¦å· |
| | | entryDate: dayjs().format('YYYY-MM-DD') // 设置å½å
¥æ¶é´ä¸ºå½å¤© |
| | | }) |
| | | dialogFormVisible.value = true |
| | | } |
| | |
| | | const submitForm = () => { |
| | | formRef.value.validate(valid => { |
| | | if (valid) { |
| | | const api = operationType.value === 'add' ? addOpportunity : updateOpportunity |
| | | // æ¶ééä»¶æä»¶ç临æ¶ID |
| | | let tempFileIds = [] |
| | | if (fileList.value !== null && fileList.value.length > 0) { |
| | | tempFileIds = fileList.value.map(item => item.tempId) |
| | | } |
| | | |
| | | api(form).then(res => { |
| | | let api |
| | | let successMessage |
| | | let submitData |
| | | |
| | | if (operationType.value === 'add') { |
| | | api = addOpportunity |
| | | successMessage = 'æ°å»ºæå' |
| | | submitData = { |
| | | ...form, |
| | | tempFileIds: tempFileIds, |
| | | type: 9 // åæºç®¡ççç±»åæ è¯ |
| | | } |
| | | } else if (operationType.value === 'addOperation') { |
| | | api = addDescription |
| | | successMessage = 'æ·»å æä½æå' |
| | | // æ·»å æä½æ¶ä¼ éç¶æãæè¿°ãå½å
¥äººãå½å
¥æ¥æãéä»¶ååæºID |
| | | submitData = { |
| | | status: form.status, |
| | | description: form.description, |
| | | entryPerson: form.entryPerson, |
| | | entryDate: form.entryDate, |
| | | tempFileIds: tempFileIds, |
| | | type: 9, // åæºç®¡ççç±»åæ è¯ |
| | | businessOpportunityId: form.id // ä¼ éåæºID |
| | | } |
| | | } else { |
| | | api = updateOpportunity |
| | | successMessage = 'ä¿®æ¹æå' |
| | | submitData = { |
| | | ...form, |
| | | tempFileIds: tempFileIds, |
| | | type: 9 // åæºç®¡ççç±»åæ è¯ |
| | | } |
| | | } |
| | | |
| | | api(submitData).then(res => { |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess(operationType.value === 'add' ? 'æ°å»ºæå' : 'ä¿®æ¹æå') |
| | | proxy.$modal.msgSuccess(successMessage) |
| | | closeDialog() |
| | | getList() |
| | | } else { |
| | |
| | | const resetForm = () => { |
| | | Object.assign(form, { |
| | | id: undefined, |
| | | status: 'new', |
| | | status: 'æ°å»º', |
| | | province: '', |
| | | customerName: '', |
| | | businessSource: '', |
| | | description: '', |
| | | entryPerson: userStore.nickName, |
| | | entryDateStart: dayjs().format('YYYY-MM-DD') |
| | | entryDate: dayjs().format('YYYY-MM-DD') |
| | | }) |
| | | |
| | | if (formRef.value) { |
| | |
| | | const closeDialog = () => { |
| | | dialogFormVisible.value = false |
| | | resetForm() |
| | | } |
| | | |
| | | // ä¸ä¼ åæ ¡æ£ |
| | | function handleBeforeUpload(file) { |
| | | // æ ¡æ£æä»¶å¤§å° |
| | | // if (file.size > 1024 * 1024 * 10) { |
| | | // proxy.$modal.msgError("ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿10MB!"); |
| | | // return false; |
| | | // } |
| | | proxy.$modal.loading("æ£å¨ä¸ä¼ æä»¶ï¼è¯·ç¨å..."); |
| | | return true; |
| | | } |
| | | |
| | | // ä¸ä¼ 失败 |
| | | function handleUploadError(err) { |
| | | proxy.$modal.msgError("ä¸ä¼ æä»¶å¤±è´¥"); |
| | | proxy.$modal.closeLoading(); |
| | | } |
| | | |
| | | // ä¸ä¼ æååè° |
| | | function handleUploadSuccess(res, file, uploadFiles) { |
| | | proxy.$modal.closeLoading(); |
| | | if (res.code === 200) { |
| | | file.tempId = res.data.tempId; |
| | | proxy.$modal.msgSuccess("ä¸ä¼ æå"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg); |
| | | proxy.$refs.fileUpload.handleRemove(file); |
| | | } |
| | | } |
| | | |
| | | // ç§»é¤æä»¶ |
| | | function handleRemove(file) { |
| | | // è¿éå¯ä»¥æ·»å å 餿件çé»è¾ |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | } |
| | | |
| | | // æ¥çéä»¶ |
| | | function handleAttachment(row) { |
| | | fileListRef.value.open(row.businessCommonFiles) |
| | | } |
| | | |
| | | onMounted(() => { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* åæ´è®°å½æ¶é´çº¿æ ·å¼ */ |
| | | .change-history-section { |
| | | margin-top: 20px; |
| | | |
| | | .el-divider { |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .timeline-card { |
| | | margin: 8px 0; |
| | | border-radius: 8px; |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 8px 0; |
| | | |
| | | .action-type { |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | |
| | | .operator { |
| | | font-size: 12px; |
| | | color: #666; |
| | | } |
| | | } |
| | | |
| | | .change-content { |
| | | .status-change, .description-change { |
| | | margin-bottom: 8px; |
| | | |
| | | .label { |
| | | font-weight: 500; |
| | | color: #666; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .description-text { |
| | | color: #333; |
| | | line-height: 1.5; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* æ¶é´çº¿æ ·å¼ä¼å */ |
| | | :deep(.el-timeline) { |
| | | padding-left: 0; |
| | | |
| | | .el-timeline-item { |
| | | .el-timeline-item__node { |
| | | background-color: #409eff; |
| | | |
| | | &.el-timeline-item__node--primary { |
| | | background-color: #409eff; |
| | | } |
| | | |
| | | &.el-timeline-item__node--success { |
| | | background-color: #67c23a; |
| | | } |
| | | |
| | | &.el-timeline-item__node--info { |
| | | background-color: #909399; |
| | | } |
| | | |
| | | &.el-timeline-item__node--hollow { |
| | | background-color: transparent; |
| | | border-color: #409eff; |
| | | } |
| | | } |
| | | |
| | | .el-timeline-item__timestamp { |
| | | color: #666; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |