feat: 个人用户拜访编辑新增照片查看/删除/上传功能
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import { useThemeStore } from '@/stores/theme'
|
||||
import { customersApi } from '@/api/customers'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getManagerColor as mgrColorFn, getMgrTextColor, loadManagerColors } from '@/utils/managerColor'
|
||||
import { compressImage } from '@/utils/image'
|
||||
import api from '@/api/index'
|
||||
|
||||
const auth = useAuthStore()
|
||||
@@ -31,11 +32,49 @@ const indivEditVisible = ref(false)
|
||||
const indivEditType = ref('')
|
||||
const indivEditForm = ref<any>({})
|
||||
const indivEditSaving = ref(false)
|
||||
const indivPhotoUrls = ref<Record<string, string>>({})
|
||||
|
||||
function openIndivEdit(type: string, row: any) {
|
||||
async function openIndivEdit(type: string, row: any) {
|
||||
indivEditType.value = type
|
||||
indivEditForm.value = { ...row }
|
||||
indivEditVisible.value = true
|
||||
// Load photo URLs for visit editing
|
||||
if (type === 'visit' && row.photos?.length) {
|
||||
for (const key of row.photos) {
|
||||
if (!indivPhotoUrls.value[key]) {
|
||||
try {
|
||||
const urlRes = await api.get('/upload/download-url', { params: { object_key: key } })
|
||||
indivPhotoUrls.value[key] = urlRes.data.download_url
|
||||
} catch (_) { indivPhotoUrls.value[key] = '' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handleIndivPhotoUpload(event: Event) {
|
||||
const target = event.target as HTMLInputElement
|
||||
if (!target.files?.length) return
|
||||
const form = indivEditForm.value
|
||||
if (!form.photos) form.photos = []
|
||||
if (form.photos.length >= 9) { ElMessage.warning('最多9张照片'); return }
|
||||
for (const file of Array.from(target.files)) {
|
||||
if (form.photos.length >= 9) break
|
||||
try {
|
||||
const compressed = await compressImage(file, { maxPixels: 1920, quality: 0.8 })
|
||||
const presignRes = await api.get('/upload/presigned-url', { params: { filename: compressed.name, content_type: compressed.type || 'image/jpeg' } })
|
||||
await api.put(presignRes.data.upload_url, compressed, { headers: { 'Content-Type': compressed.type || 'image/jpeg' } })
|
||||
form.photos.push(presignRes.data.object_key)
|
||||
indivPhotoUrls.value[presignRes.data.object_key] = URL.createObjectURL(compressed)
|
||||
} catch (_) { ElMessage.error('上传失败') }
|
||||
}
|
||||
target.value = ''
|
||||
}
|
||||
|
||||
function removeIndivPhoto(idx: number) {
|
||||
const form = indivEditForm.value
|
||||
const key = form.photos[idx]
|
||||
delete indivPhotoUrls.value[key]
|
||||
form.photos.splice(idx, 1)
|
||||
}
|
||||
|
||||
async function handleIndivEditSave() {
|
||||
@@ -53,6 +92,7 @@ async function handleIndivEditSave() {
|
||||
time_range: f.time_range || '',
|
||||
visit_date: f.visit_date,
|
||||
manager_id: f.manager_id,
|
||||
photos: f.photos || [],
|
||||
})
|
||||
} else if (type === 'plan') {
|
||||
await api.put(`/work-plans/${f.id}`, { plan_content: f.plan_content, status: f.status, plan_date: f.plan_date, manager_id: f.manager_id })
|
||||
@@ -710,6 +750,22 @@ async function handleImport() {
|
||||
<el-form-item label="相关人员"><el-input v-model="indivEditForm.companion_names_str" placeholder="多个姓名用、分隔" /></el-form-item>
|
||||
<el-form-item label="沟通内容"><el-input v-model="indivEditForm.communication_content" type="textarea" :rows="4" /></el-form-item>
|
||||
<el-form-item label="客户需求"><el-input v-model="indivEditForm.customer_demand" type="textarea" :rows="2" /></el-form-item>
|
||||
<el-form-item v-if="indivEditForm.photos?.length" label="照片">
|
||||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||||
<div v-for="(key, idx) in indivEditForm.photos" :key="key" style="position:relative">
|
||||
<img :src="indivPhotoUrls[key]" style="width:80px;height:80px;object-fit:cover;border:1px solid var(--warm-border)" v-if="indivPhotoUrls[key]" />
|
||||
<span v-else style="width:80px;height:80px;display:flex;align-items:center;justify-content:center;background:var(--paper);border:1px solid var(--warm-border);font-size:12px;color:var(--warm-gray)">加载中</span>
|
||||
<button type="button" style="position:absolute;top:-6px;right:-6px;background:var(--vermilion);color:#fff;border:none;width:18px;height:18px;cursor:pointer;font-size:12px;line-height:1" @click="removeIndivPhoto(idx)">×</button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="添加照片">
|
||||
<label style="cursor:pointer;display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border:1px dashed var(--warm-border);color:var(--warm-gray);font-size:13px">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>
|
||||
上传照片(最多9张)
|
||||
<input type="file" accept="image/*" multiple style="display:none" @change="handleIndivPhotoUpload" />
|
||||
</label>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-else-if="indivEditType === 'plan'">
|
||||
<el-form-item label="客户经理">
|
||||
|
||||
Reference in New Issue
Block a user