usePlanView.js
4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
* 计划书查看 Composable
*
* @description 封装计划书查看逻辑,支持:
* - 单文件直接预览
* - 多文件显示选择弹框
* - 预览成功后标记为已查看
* - 传入 proposal 数据自动处理状态和文件
*
* @example
* const { viewProposal } = usePlanView()
*
* // 方式1:传入完整的 proposal 对象(从消息详情 API 获取)
* viewProposal({
* id: 123,
* order_status: '7',
* proposal_files: [
* { file_name: '计划书.pdf', file_url: 'xxx', id: 1 }
* ]
* })
*
* // 方式2:传入已转换的 item(从计划书列表获取)
* viewProposal(planItem)
*
* @author Claude Code
* @version 1.0.0
*/
import { useFileOperation } from './useFileOperation'
import { viewAPI } from '@/api/plan'
import { ORDER_STATUS, mapOrderStatus, getStatusText } from '@/config/constants/orderStatus'
import Taro from '@tarojs/taro'
/**
* 计划书查看 Hook
*
* @returns {Object} 包含 viewProposal 方法的对象
*/
export function usePlanView() {
const { viewFile } = useFileOperation()
/**
* 查看计划书
*
* @param {Object} proposal - 计划书对象(支持两种格式)
* @param {number} proposal.id - 计划书 ID(必需)
* @param {string} proposal.order_status - 订单状态(API 格式:'3'|'5'|'7'|'9')
* @param {Array} proposal.proposal_files - 文件列表(API 格式)
* @param {string} proposal.status - 订单状态(前端格式,兼容列表数据)
* @param {Array} proposal.proposalFiles - 文件列表(兼容列表数据)
* @param {Object} callbacks - 回调函数
* @param {Function} callbacks.onViewSuccess - 查看成功后回调,参数为 proposalId
* @param {Function} callbacks.beforeView - 查看前回调,返回 false 可取消查看
* @returns {Promise<void>}
*/
const viewProposal = async (proposal, callbacks = {}) => {
const { beforeView, onViewSuccess } = callbacks
// 1. 状态检查 - 解析两种可能的状态字段
const status = proposal.status || mapOrderStatus(proposal.order_status)
if (status === ORDER_STATUS.PENDING || status === ORDER_STATUS.PROCESSING) {
Taro.showToast({
title: '计划书尚未生成,请稍后',
icon: 'none'
})
return
}
// 2. 解析文件列表 - 支持两种可能的字段名
const proposalFiles = proposal.proposal_files || proposal.proposalFiles || []
if (!proposalFiles || proposalFiles.length === 0) {
Taro.showToast({
title: '暂无可查看的计划书',
icon: 'none'
})
return
}
// 3. 执行查看前回调
if (beforeView) {
const shouldContinue = await beforeView(proposal)
if (shouldContinue === false) return
}
/**
* 处理单个文件的查看
*
* @param {Object} file - 文件对象
* @param {string} file.file_url - 文件 URL
* @param {string} file.file_name - 文件名称
*/
const handleFileView = async (file) => {
try {
const previewSuccess = await viewFile({
downloadUrl: file.file_url,
fileName: file.file_name
})
if (!previewSuccess) return
// 4. 预览成功后标记为已查看
if (status !== 'viewed' && proposal.id) {
const viewRes = await viewAPI({ i: proposal.id })
if (viewRes.code === 1) {
Taro.showToast({
title: '已标记为查看',
icon: 'success',
duration: 1000
})
// 触发成功回调
if (onViewSuccess) {
onViewSuccess(proposal.id)
}
}
}
} catch (error) {
console.error('查看计划书文件失败:', error)
}
}
// 5. 单文件直接查看
if (proposalFiles.length === 1) {
await handleFileView(proposalFiles[0])
return
}
// 6. 多文件显示选择弹框
const fileList = proposalFiles.map((file, index) => ({
text: file.file_name || `计划书 ${index + 1}`,
file: file
}))
Taro.showActionSheet({
itemList: fileList.map(f => f.text),
success: async (res) => {
const selectedIndex = res.tapIndex
if (selectedIndex !== undefined && selectedIndex >= 0) {
const selectedFile = fileList[selectedIndex].file
await handleFileView(selectedFile)
}
}
})
}
return {
viewProposal,
mapOrderStatus,
getStatusText
}
}