feat(wecom): 集成企业微信JSSDK并重构客户信息获取逻辑
refactor(admin): 优化文件上传处理及表单字段管理 fix(user): 修复企微SDK初始化及客户ID获取问题
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@vicons/ionicons5": "^0.13.0",
|
||||
"@wecom/jssdk": "^2.3.4",
|
||||
"axios": "^1.13.6",
|
||||
"dev": "^0.1.3",
|
||||
"naive-ui": "^2.44.1",
|
||||
|
||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -11,6 +11,9 @@ importers:
|
||||
'@vicons/ionicons5':
|
||||
specifier: ^0.13.0
|
||||
version: 0.13.0
|
||||
'@wecom/jssdk':
|
||||
specifier: ^2.3.4
|
||||
version: 2.3.4
|
||||
axios:
|
||||
specifier: ^1.13.6
|
||||
version: 1.13.6
|
||||
@@ -650,6 +653,9 @@ packages:
|
||||
vue:
|
||||
optional: true
|
||||
|
||||
'@wecom/jssdk@2.3.4':
|
||||
resolution: {integrity: sha512-oLfuvwMBZCRRMowVi/JkKx/dLNGHCmmUbQfCYG7XGmHYbgkQJlAlack4jKBk+NVG4G0S24fIrAF+XwQuXXxgAw==}
|
||||
|
||||
acorn@8.16.0:
|
||||
resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
@@ -1890,6 +1896,8 @@ snapshots:
|
||||
typescript: 5.9.3
|
||||
vue: 3.5.30(typescript@5.9.3)
|
||||
|
||||
'@wecom/jssdk@2.3.4': {}
|
||||
|
||||
acorn@8.16.0: {}
|
||||
|
||||
alien-signals@3.1.2: {}
|
||||
|
||||
@@ -101,9 +101,9 @@
|
||||
</n-card>
|
||||
</main>
|
||||
|
||||
<!-- 详情抽屉 - 视觉重构 -->
|
||||
<!-- 详情抽屉 -->
|
||||
<n-drawer v-model:show="showDrawer" :width="650" placement="right" resizable>
|
||||
<n-drawer-content title="原始提报资料详情" closable class="modern-drawer">
|
||||
<n-drawer-content title="原始提报资料详情与分配" closable class="modern-drawer">
|
||||
<div class="drawer-body" v-if="showDrawer && editingRow.wecom_id">
|
||||
<n-space vertical :size="24">
|
||||
<!-- 分配任务卡片 -->
|
||||
@@ -136,14 +136,8 @@
|
||||
</div>
|
||||
<n-form label-placement="left" label-width="90" size="small" :model="editingRow">
|
||||
<n-grid :x-gap="20" :cols="2">
|
||||
<n-grid-item v-for="field in [
|
||||
{label:'主管', key:'analyst_supervisor'},
|
||||
{label:'部门', key:'analyst_department'},
|
||||
{label:'分析师', key:'analyst_name'},
|
||||
{label:'家长姓名', key:'parent_name'},
|
||||
{label:'家长电话', key:'parent_phone'},
|
||||
{label:'身份证', key:'parent_id_card'},
|
||||
]" :key="field.key">
|
||||
<!-- 修复了之前的 v-for 报错,将数组抽离为了 baseInfoFields -->
|
||||
<n-grid-item v-for="field in baseInfoFields" :key="field.key">
|
||||
<n-form-item :label="field.label">
|
||||
<n-input v-model:value="editingRow[field.key]" />
|
||||
</n-form-item>
|
||||
@@ -162,27 +156,43 @@
|
||||
</n-form>
|
||||
</div>
|
||||
|
||||
<!-- 附件区 -->
|
||||
<!-- 附件/素材区 -->
|
||||
<div class="file-grid">
|
||||
<!-- 1. 附件文档 -->
|
||||
<div class="file-item">
|
||||
<div class="file-label"><n-icon><FileTrayOutline /></n-icon> 附件文档</div>
|
||||
<n-upload
|
||||
v-model:file-list="editingRow.attachmentFileList"
|
||||
:max="1"
|
||||
:custom-request="({ file, onFinish, onError, onProgress }) => handleCustomUpload({ file, onFinish, onError, onProgress }, 'attachmentFileList')"
|
||||
:custom-request="handleCustomUpload"
|
||||
>
|
||||
<n-button dashed block>上传新附件</n-button>
|
||||
<n-button dashed block>更换附件文档</n-button>
|
||||
</n-upload>
|
||||
</div>
|
||||
|
||||
<!-- 2. 电子签名 -->
|
||||
<div class="file-item">
|
||||
<div class="file-label"><n-icon><ImagesOutline /></n-icon> 付款截图</div>
|
||||
<div class="file-label"><n-icon><CreateOutline /></n-icon> 电子签名</div>
|
||||
<n-upload
|
||||
v-model:file-list="editingRow.signatureFileList"
|
||||
list-type="image-card"
|
||||
:max="1"
|
||||
@preview="handlePreview"
|
||||
:custom-request="handleCustomUpload"
|
||||
>
|
||||
点击上传
|
||||
</n-upload>
|
||||
</div>
|
||||
|
||||
<!-- 3. 付款截图 -->
|
||||
<div class="file-item payment-item">
|
||||
<div class="file-label"><n-icon><ImagesOutline /></n-icon> 付款截图凭证 (多选)</div>
|
||||
<n-upload
|
||||
v-model:file-list="editingRow.paymentFileList"
|
||||
list-type="image-card"
|
||||
multiple
|
||||
@preview="handlePreview"
|
||||
:custom-request="({ file, onFinish, onError, onProgress }) => handleCustomUpload({ file, onFinish, onError, onProgress }, 'paymentFileList')"
|
||||
:custom-request="handleCustomUpload"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -208,21 +218,17 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/**
|
||||
* Script 部分保持原样,无需修改逻辑
|
||||
* 这里省略重复的逻辑代码以减少篇幅,请直接沿用你原文件中的 script 内容
|
||||
*/
|
||||
import { ref, h, reactive, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import {
|
||||
useMessage, zhCN, dateZhCN, NConfigProvider, NCard, NDataTable, NButton, NIcon, NInput,
|
||||
NDrawer, NDrawerContent, NSpace, NForm, NFormItem, NGrid, NGridItem, NDatePicker, NSelect,
|
||||
NTag, NUpload, NModal, NText, NBadge
|
||||
NTag, NUpload, NModal, NBadge
|
||||
} from 'naive-ui'
|
||||
|
||||
import {
|
||||
SearchOutline, LogOutOutline, DownloadOutline, PersonOutline, FileTrayOutline,
|
||||
ImagesOutline, BrushOutline, ReaderOutline, EyeOutline
|
||||
ImagesOutline, BrushOutline, ReaderOutline, EyeOutline, CreateOutline
|
||||
} from '@vicons/ionicons5'
|
||||
import http from '@/utils/http'
|
||||
|
||||
@@ -231,6 +237,16 @@ const message = useMessage()
|
||||
const loading = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
|
||||
// 基础信息表单配置(解决模板中 v-for 太长和语法报错的问题)
|
||||
const baseInfoFields =[
|
||||
{ label: '主管', key: 'analyst_supervisor' },
|
||||
{ label: '部门', key: 'analyst_department' },
|
||||
{ label: '分析师', key: 'analyst_name' },
|
||||
{ label: '家长姓名', key: 'parent_name' },
|
||||
{ label: '家长电话', key: 'parent_phone' },
|
||||
{ label: '身份证', key: 'parent_id_card' }
|
||||
]
|
||||
|
||||
const searchParams = reactive({
|
||||
wecom_id: '',
|
||||
parentInfo: '',
|
||||
@@ -262,6 +278,9 @@ const pagination = reactive({
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 核心逻辑:数据请求与文件对象标准化
|
||||
*/
|
||||
const fetchData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
@@ -278,18 +297,22 @@ const fetchData = async () => {
|
||||
query.append('start_date', startDate)
|
||||
query.append('end_date', endDate)
|
||||
}
|
||||
|
||||
const res = await http.get(`/v1/customer/list?${query.toString()}`)
|
||||
if (res && res.success) {
|
||||
displayData.value = res.data.map(item => {
|
||||
// 列表回显处理:为了让 n-upload 正常显示缩略图,仍然必须组装包含 url 字段的对象
|
||||
const p_names = Array.isArray(item.payment_object_names) ? item.payment_object_names :[]
|
||||
const p_urls = item.payment_image_url ||[]
|
||||
const paymentFileList = p_urls.map((url, i) => ({
|
||||
id: p_names[i] || `pay_${i}`,
|
||||
name: `付款截图_${i + 1}.png`,
|
||||
status: 'finished',
|
||||
url: url,
|
||||
object_name: p_names[i]
|
||||
url: url, // 映射到组件的 url 以展示缩略图
|
||||
object_name: p_names[i] // 保留真实的 object_name
|
||||
}))
|
||||
|
||||
// 处理签名
|
||||
const signatureFileList = item.signature_image_url ?[{
|
||||
id: item.signature_object_name || 'sig',
|
||||
name: '电子签名.png',
|
||||
@@ -297,6 +320,8 @@ const fetchData = async () => {
|
||||
url: item.signature_image_url,
|
||||
object_name: item.signature_object_name
|
||||
}] :[]
|
||||
|
||||
// 处理附件文档
|
||||
const attachmentFileList = item.attachment_file_url ?[{
|
||||
id: item.attachment_object_name || 'att',
|
||||
name: '原始附件文档',
|
||||
@@ -304,6 +329,7 @@ const fetchData = async () => {
|
||||
url: item.attachment_file_url,
|
||||
object_name: item.attachment_object_name
|
||||
}] :[]
|
||||
|
||||
return {
|
||||
...item,
|
||||
transaction_amount: item.transaction_amount || '0',
|
||||
@@ -318,54 +344,85 @@ const fetchData = async () => {
|
||||
pagination.itemCount = res.pagination?.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
console.error('Fetch error:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleCustomUpload = async ({ file, onFinish, onError, onProgress }, type) => {
|
||||
/**
|
||||
* 核心上传逻辑:基于引用的响应式更新 (已适配最新接口格式)
|
||||
*/
|
||||
const handleCustomUpload = async ({ file, onFinish, onError, onProgress }) => {
|
||||
try {
|
||||
const uploadData = new FormData()
|
||||
uploadData.append('file', file.file)
|
||||
|
||||
const response = await http.post('/v1/material/upload', uploadData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
onUploadProgress: (p) => onProgress({ percent: Math.ceil((p.loaded / p.total) * 100) })
|
||||
})
|
||||
if (response && response.success) {
|
||||
file.rawResponse = response
|
||||
file.url = response.url
|
||||
|
||||
// 提取接口返回的真实数据对象
|
||||
const resData = response.data
|
||||
console.log(24536,resData)
|
||||
// 判断是否成功获取到了关键字段 object_name
|
||||
if ( resData && resData.object_name) {
|
||||
|
||||
// 1. 核心业务字段赋值:供后续 submitAssignment 提取上传
|
||||
file.name = resData.object_name
|
||||
|
||||
// 2. 组件渲染依赖字段映射:Naive UI 组件强依赖 url 属性显示图片预览,所以把 preview_url 给它
|
||||
file.url = resData.preview_url
|
||||
|
||||
// 3. 存储其余接口返回数据:备用
|
||||
file.download_url = resData.download_url
|
||||
file.upload_time = resData.upload_time
|
||||
|
||||
// 更新组件内部状态为完成
|
||||
file.status = 'finished'
|
||||
|
||||
message.success('上传成功')
|
||||
onFinish()
|
||||
} else {
|
||||
message.error(response.message || '上传失败,接口返回数据格式异常')
|
||||
onError()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Upload error:', error)
|
||||
message.error('网络错误,上传失败')
|
||||
onError()
|
||||
}
|
||||
}
|
||||
|
||||
const getObjectName = (fileItem) => {
|
||||
if (fileItem.rawResponse) return fileItem.rawResponse.data?.object_name || fileItem.rawResponse.object_name || null
|
||||
return fileItem.object_name || null
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交分配任务 (包含文件标识符提取)
|
||||
*/
|
||||
const submitAssignment = async (row) => {
|
||||
if (!row.assignee_name || !row.assignee_phone) {
|
||||
message.warning('请填写指导师姓名和电话')
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查上传状态
|
||||
const allFiles = [...row.paymentFileList, ...row.signatureFileList, ...row.attachmentFileList]
|
||||
if (allFiles.some(f => f.status === 'uploading')) {
|
||||
message.warning('文件正在上传中,请稍后提交')
|
||||
return false
|
||||
}
|
||||
|
||||
row.isSubmitting = true
|
||||
try {
|
||||
const payment_object_names = row.paymentFileList.map(getObjectName).filter(Boolean)
|
||||
const signature_object_name = row.signatureFileList.length > 0 ? getObjectName(row.signatureFileList[0]) : ''
|
||||
const attachment_object_name = row.attachmentFileList.length > 0 ? getObjectName(row.attachmentFileList[0]) : ''
|
||||
// 从当前数组提取最新的 object_name
|
||||
const payment_object_names = row.paymentFileList.map(f => f.name || f?.object_name || f.name).filter(Boolean)
|
||||
const signature_object_name = row.signatureFileList[0]?.name || row.signatureFileList[0]?.object_name || row.signatureFileList[0]?.name
|
||||
const attachment_object_name = row.attachmentFileList[0]?.name || row.attachmentFileList[0]?.object_name || row.attachmentFileList[0]?.name
|
||||
|
||||
const payload = {
|
||||
wecom_id: String(row.wecom_id),
|
||||
payment_object_names: payment_object_names,
|
||||
signature_object_name: signature_object_name,
|
||||
attachment_object_name: attachment_object_name,
|
||||
payment_object_names,
|
||||
signature_object_name,
|
||||
attachment_object_name,
|
||||
analyst_supervisor: row.analyst_supervisor,
|
||||
analyst_department: row.analyst_department,
|
||||
analyst_name: row.analyst_name,
|
||||
@@ -378,14 +435,18 @@ const submitAssignment = async (row) => {
|
||||
assignee_name: row.assignee_name,
|
||||
assignee_phone: row.assignee_phone
|
||||
}
|
||||
console.log(24531221126,row)
|
||||
console.log('提交的数据:', payload)
|
||||
|
||||
const res = await http.post('/v1/material/submit', payload)
|
||||
if (res && (res.success || res.code === 200)) {
|
||||
message.success('分配成功')
|
||||
message.success('分配并同步成功')
|
||||
row.status = 'processed'
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} catch (error) {
|
||||
console.error('Submit error:', error)
|
||||
return false
|
||||
} finally {
|
||||
row.isSubmitting = false
|
||||
@@ -397,12 +458,14 @@ const editingRow = ref({})
|
||||
const showPreview = ref(false)
|
||||
const previewImageUrl = ref('')
|
||||
|
||||
/**
|
||||
* 打开详情并执行深拷贝隔离
|
||||
*/
|
||||
const openDetails = (row) => {
|
||||
const rowCopy = JSON.parse(JSON.stringify(row))
|
||||
if (!rowCopy.transaction_date) {
|
||||
rowCopy.transaction_date = null
|
||||
editingRow.value = JSON.parse(JSON.stringify(row))
|
||||
if (!editingRow.value.transaction_date) {
|
||||
editingRow.value.transaction_date = null
|
||||
}
|
||||
editingRow.value = rowCopy
|
||||
showDrawer.value = true
|
||||
}
|
||||
|
||||
@@ -416,6 +479,9 @@ const handleDrawerSubmit = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格列配置
|
||||
*/
|
||||
const columns =[
|
||||
{ title: '分析师', key: 'analyst_name', width: 100, fixed: 'left' },
|
||||
{ title: '家长姓名', key: 'parent_name', width: 100 },
|
||||
@@ -485,6 +551,7 @@ const columns =[
|
||||
}
|
||||
]
|
||||
|
||||
// 预览依然取 url,因为 handleCustomUpload 已将接口真实的 preview_url 映射给了 url
|
||||
const handlePreview = (file) => {
|
||||
previewImageUrl.value = file.url || (file.file && URL.createObjectURL(file.file))
|
||||
showPreview.value = true
|
||||
@@ -668,6 +735,7 @@ const logout = () => {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* 文件网格布局 */
|
||||
.file-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
@@ -679,6 +747,13 @@ const logout = () => {
|
||||
padding: 16px;
|
||||
border-radius: 12px;
|
||||
border: 1px dashed #cbd5e1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 付款截图独占一行 */
|
||||
.payment-item {
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
.file-label {
|
||||
@@ -688,6 +763,7 @@ const logout = () => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.drawer-footer {
|
||||
@@ -713,6 +789,10 @@ const logout = () => {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.payment-item {
|
||||
grid-column: span 1;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
@@ -186,17 +186,26 @@ import {
|
||||
NForm, NFormItem, NInput, NInputNumber, NDatePicker, NUpload, NUploadDragger,
|
||||
NButton, NIcon, NText, NP
|
||||
} from 'naive-ui'
|
||||
|
||||
import {
|
||||
AnalyticsOutline, LogOutOutline, IdCardOutline, DocumentAttachOutline,
|
||||
ImagesOutline, BrushOutline, CloudUploadOutline, CameraOutline,
|
||||
CreateOutline, CloseOutline, CheckmarkCircleOutline
|
||||
} from '@vicons/ionicons5'
|
||||
|
||||
import http from '@/utils/http'
|
||||
import * as ww from '@wecom/jssdk'
|
||||
|
||||
const message = useMessage()
|
||||
const router = useRouter()
|
||||
const formRef = ref(null)
|
||||
|
||||
// 【修复 1】添加 isWWReady 响应式变量的声明
|
||||
const isWWReady = ref(false)
|
||||
|
||||
// 【修复 2 & 3】使用 let 声明 wecomId,并且不在顶层作用域立即调用 API
|
||||
let wecomId = ''
|
||||
|
||||
/**
|
||||
* 主题定制:优化圆角和品牌色
|
||||
* 主题定制
|
||||
*/
|
||||
const themeOverrides = {
|
||||
common: {
|
||||
@@ -207,15 +216,64 @@ const themeOverrides = {
|
||||
}
|
||||
}
|
||||
|
||||
const message = useMessage()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const formRef = ref(null)
|
||||
/**
|
||||
* 初始化企业微信 JSSDK
|
||||
*/
|
||||
async function getConfigSignature(url) {
|
||||
const response = await fetch('https://superdata.nycjy.cn/api/v1/wecom/agent-config-signature', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ url })
|
||||
})
|
||||
const ConfigSignature = await response.json()
|
||||
console.log('基础签名响应:', ConfigSignature)
|
||||
if (ConfigSignature.code === 200 && ConfigSignature.data) {
|
||||
return {
|
||||
timestamp: ConfigSignature.data.timestamp,
|
||||
nonceStr: ConfigSignature.data.nonceStr,
|
||||
signature: ConfigSignature.data.corpSignature
|
||||
}
|
||||
}
|
||||
throw new Error('基础签名获取失败')
|
||||
}
|
||||
|
||||
// 保持原逻辑:获取 wecom_id
|
||||
const wecomId = route.query.wecom_id || 'wmcr-ECwAAzKclEfIKNcVgOdxD-TcqLg'
|
||||
async function getAgentConfigSignature(url) {
|
||||
const response = await fetch('https://superdata.nycjy.cn/api/v1/wecom/agent-config-signature', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ url })
|
||||
})
|
||||
const AgentConfigSignature = await response.json()
|
||||
console.log('应用签名响应:', AgentConfigSignature)
|
||||
if (AgentConfigSignature.code === 200 && AgentConfigSignature.data) {
|
||||
return {
|
||||
timestamp: AgentConfigSignature.data.timestamp,
|
||||
nonceStr: AgentConfigSignature.data.nonceStr,
|
||||
signature: AgentConfigSignature.data.signature
|
||||
}
|
||||
}
|
||||
throw new Error('应用签名获取失败')
|
||||
}
|
||||
const initSDK = async () => {
|
||||
try {
|
||||
await ww.register({
|
||||
corpId: 'wwf72acc5a681dca93',
|
||||
agentId: 1000135,
|
||||
jsApiList: ['getCurExternalContact'],
|
||||
getAgentConfigSignature,
|
||||
getConfigSignature
|
||||
})
|
||||
isWWReady.value = true
|
||||
console.log('企微JSSDK初始化成功')
|
||||
} catch (e) {
|
||||
console.error('SDK初始化失败', e)
|
||||
message.error('企业微信SDK初始化失败,请检查配置或环境')
|
||||
}
|
||||
}
|
||||
|
||||
// 保持原逻辑:响应式表单数据
|
||||
/**
|
||||
* 响应式表单数据
|
||||
*/
|
||||
const formData = reactive({
|
||||
analystSupervisor: '',
|
||||
analystDepartment: '',
|
||||
@@ -232,12 +290,16 @@ const formData = reactive({
|
||||
signatureFileList: []
|
||||
})
|
||||
|
||||
// 保持原逻辑:文件预览列表
|
||||
/**
|
||||
* 文件预览列表
|
||||
*/
|
||||
const documentFileListLast = ref([])
|
||||
const paymentFileListLast = ref([])
|
||||
const signatureFileListLast = ref([])
|
||||
|
||||
// 保持原逻辑:校验规则
|
||||
/**
|
||||
* 表单校验规则
|
||||
*/
|
||||
const rules = {
|
||||
analystSupervisor: { required: true, message: '请输入主管姓名', trigger: 'blur' },
|
||||
parentName: { required: true, message: '请输入家长姓名', trigger: 'blur' },
|
||||
@@ -245,7 +307,7 @@ const rules = {
|
||||
}
|
||||
|
||||
/**
|
||||
* 保持原逻辑:格式化日期
|
||||
* 格式化日期
|
||||
*/
|
||||
const formatDate = (timestamp) => {
|
||||
if (!timestamp) return null;
|
||||
@@ -257,7 +319,7 @@ const formatDate = (timestamp) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 保持原逻辑:通用文件上传逻辑
|
||||
* 通用文件上传逻辑
|
||||
*/
|
||||
const handleCustomUpload = async ({ file, onFinish, onError, onProgress }, type) => {
|
||||
try {
|
||||
@@ -294,60 +356,84 @@ const handleCustomUpload = async ({ file, onFinish, onError, onProgress }, type)
|
||||
}
|
||||
|
||||
/**
|
||||
* 保持原逻辑:初始化数据回显
|
||||
* 初始化数据回显
|
||||
*/
|
||||
const initData = async () => {
|
||||
try {
|
||||
const res = await http.get('/v1/customer/get_customers_info', { wecom_id: wecomId })
|
||||
// 【修复 3】确保在 SDK ready 后再调用 API
|
||||
if (isWWReady.value) {
|
||||
const contactRes = await ww.getCurExternalContact()
|
||||
wecomId = contactRes?.userId || ''
|
||||
|
||||
formData.analystName = res.analystName
|
||||
formData.parentName = res.customerName
|
||||
formData.parentPhone = res.customerPhone
|
||||
formData.analystNotes = res.notes
|
||||
formData.analystSupervisor = res.analystDepartmentLeader?.[0] || ''
|
||||
formData.analystDepartment = res.analystDepartmentName?.[0] || ''
|
||||
if (res.dealAmount) formData.transactionAmount = Number(res.dealAmount)
|
||||
if (res.dealDate) formData.transactionDate = new Date(res.dealDate).getTime()
|
||||
if (!wecomId) {
|
||||
message.warning('未获取到当前客户ID,请确认在企微侧边栏打开');
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.proofOfPayment && res.proofOfPayment_urls) {
|
||||
const paymentFiles = res.proofOfPayment.map((objName, index) => ({
|
||||
id: objName,
|
||||
name: `凭证-${index + 1}`,
|
||||
status: 'finished',
|
||||
url: res.proofOfPayment_urls[index],
|
||||
rawResponse: {
|
||||
data: {
|
||||
object_name: objName,
|
||||
url: res.proofOfPayment_urls[index],
|
||||
},
|
||||
success: true
|
||||
}
|
||||
}))
|
||||
formData.paymentFileList = paymentFiles
|
||||
paymentFileListLast.value = paymentFiles
|
||||
console.log('当前客户 wecom_id:', wecomId);
|
||||
const res = await http.get('/v1/customer/get_customers_info', { wecom_id: wecomId })
|
||||
|
||||
formData.analystName = res.analystName
|
||||
formData.parentName = res.customerName
|
||||
formData.parentPhone = res.customerPhone
|
||||
formData.analystNotes = res.notes
|
||||
formData.analystSupervisor = res.analystDepartmentLeader?.[0] || ''
|
||||
formData.analystDepartment = res.analystDepartmentName?.[0] || ''
|
||||
if (res.dealAmount) formData.transactionAmount = Number(res.dealAmount)
|
||||
if (res.dealDate) formData.transactionDate = new Date(res.dealDate).getTime()
|
||||
|
||||
if (res.proofOfPayment && res.proofOfPayment_urls) {
|
||||
const paymentFiles = res.proofOfPayment.map((objName, index) => ({
|
||||
id: objName,
|
||||
name: `凭证-${index + 1}`,
|
||||
status: 'finished',
|
||||
url: res.proofOfPayment_urls[index],
|
||||
rawResponse: {
|
||||
data: {
|
||||
object_name: objName,
|
||||
url: res.proofOfPayment_urls[index],
|
||||
},
|
||||
success: true
|
||||
}
|
||||
}))
|
||||
formData.paymentFileList = paymentFiles
|
||||
paymentFileListLast.value = paymentFiles
|
||||
}
|
||||
message.success('客户数据加载成功')
|
||||
}
|
||||
message.success('数据加载成功')
|
||||
} catch (error) {
|
||||
console.error('加载错误:', error)
|
||||
message.error('客户信息加载失败')
|
||||
console.error('加载客户数据错误:', error)
|
||||
message.error('客户信息加载失败,请刷新重试')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initData()
|
||||
/**
|
||||
* 生命周期钩子:组件挂载后执行初始化
|
||||
*/
|
||||
onMounted(async () => {
|
||||
await initSDK() // 等待 SDK 初始化完成
|
||||
initData() // 然后再去获取业务数据
|
||||
})
|
||||
|
||||
/**
|
||||
* 文件预览
|
||||
*/
|
||||
const handlePreview = (file) => {
|
||||
const url = file.url || file.thumbnailUrl
|
||||
if (url) window.open(url)
|
||||
}
|
||||
|
||||
/**
|
||||
* 保持原逻辑:更新提交逻辑
|
||||
* 提交表单
|
||||
*/
|
||||
const handleSubmit = () => {
|
||||
const handleSubmit = async () => {
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (!errors) {
|
||||
if (!wecomId) {
|
||||
message.error('未获取到客户ID,无法提交');
|
||||
return;
|
||||
}
|
||||
|
||||
const submitPayload = {
|
||||
wecom_id: wecomId,
|
||||
analyst_supervisor: formData.analystSupervisor,
|
||||
@@ -371,7 +457,7 @@ const handleSubmit = () => {
|
||||
message.error('提交失败,请联系管理员');
|
||||
}
|
||||
} else {
|
||||
message.error('请完善必填信息');
|
||||
message.error('请检查并完善必填信息');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user