1轮修复
This commit is contained in:
@@ -7,13 +7,13 @@
|
||||
<button class="workcase-btn" @tap="showUserSelector">
|
||||
<text class="btn-text">{{userInfo.username || '切换'}}</text>
|
||||
</button>
|
||||
<button class="workcase-btn" @tap="goToChatRoomList">
|
||||
<!-- <button class="workcase-btn" @tap="showOperationSelect('chat')">
|
||||
<text class="btn-text">聊天室</text>
|
||||
</button>
|
||||
<button class="workcase-btn" @tap="goToWorkList">
|
||||
<button class="workcase-btn" @tap="showOperationSelect('workcase')">
|
||||
<image class="btn-icon" src="/static/imgs/case.svg" />
|
||||
<text class="btn-text">工单</text>
|
||||
</button>
|
||||
</button> -->
|
||||
</view>
|
||||
</view>
|
||||
<!-- 欢迎区域(机器人+浮动标签) -->
|
||||
@@ -41,7 +41,8 @@
|
||||
</view>
|
||||
|
||||
<!-- 聊天消息区域 -->
|
||||
<scroll-view class="chat-messages" scroll-y="true" :scroll-top="scrollTop" scroll-with-animation="true" :class="{ started: messages.length > 0 }">
|
||||
<scroll-view class="chat-messages" scroll-y="true" :scroll-top="scrollTop" scroll-with-animation="true"
|
||||
:class="{ started: messages.length > 0 }">
|
||||
<!-- AI初始消息 -->
|
||||
<view class="ai-initial-msg" v-if="messages.length === 0">
|
||||
<text class="ai-msg-text">您好,我是泰豪小电智能客服。请描述您的问题,我会尽力协助。</text>
|
||||
@@ -59,7 +60,8 @@
|
||||
</view>
|
||||
<!-- 用户消息的文件列表(在气泡外面) -->
|
||||
<view v-if="item.files && item.files.length > 0" class="message-files">
|
||||
<view v-for="fileId in item.files" :key="fileId" class="message-file-item" @tap="previewFile(fileId)">
|
||||
<view v-for="fileId in item.files" :key="fileId" class="message-file-item"
|
||||
@tap="previewFile(fileId)">
|
||||
<view v-if="isImageFileById(fileId)" class="file-thumb image">
|
||||
<image :src="getFileDownloadUrl(fileId)" mode="aspectFill" class="file-img" />
|
||||
</view>
|
||||
@@ -86,69 +88,74 @@
|
||||
<view class="typing-dot"></view>
|
||||
<view class="typing-dot"></view>
|
||||
</view>
|
||||
<rich-text v-else :nodes="renderMarkdown(item.content)" class="message-rich-text"></rich-text>
|
||||
<rich-text v-else :nodes="renderMarkdown(item.content)"
|
||||
class="message-rich-text"></rich-text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="message-time">{{item.time}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- 底部操作区域 -->
|
||||
<view class="bottom-area">
|
||||
<!-- 快捷按钮横向滚动 -->
|
||||
<scroll-view class="quick-scroll" scroll-x="true">
|
||||
<view class="quick-list">
|
||||
<view class="quick-btn has-icon" @tap="contactHuman">
|
||||
<text class="quick-icon">☎</text>
|
||||
<text class="quick-text">联系人工</text>
|
||||
</view>
|
||||
<view class="quick-btn has-icon" @tap="showCreator">
|
||||
<text class="quick-icon">⊕</text>
|
||||
<text class="quick-text">创建工单</text>
|
||||
</view>
|
||||
<view class="quick-divider"></view>
|
||||
<view class="quick-btn" @tap="handleQuickQuestion('查询质保状态')">
|
||||
<text class="quick-text">查询质保状态</text>
|
||||
</view>
|
||||
<view class="quick-btn" @tap="handleQuickQuestion('发动机无法启动')">
|
||||
<text class="quick-text">发动机无法启动</text>
|
||||
</view>
|
||||
<!-- 快捷按钮横向滚动 -->
|
||||
<scroll-view class="quick-scroll" scroll-x="true" show-scrollbar="false">
|
||||
<view class="quick-inner">
|
||||
<view class="quick-btn has-icon" @tap="showOperationSelect('chat')">
|
||||
<text class="quick-icon">☎</text>
|
||||
<text class="quick-text">联系人工</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="quick-btn has-icon" @tap="showOperationSelect('workcase')">
|
||||
<text class="quick-icon">⊕</text>
|
||||
<text class="quick-text">创建工单</text>
|
||||
</view>
|
||||
<view class="quick-divider"></view>
|
||||
<view class="quick-btn" @tap="handleQuickQuestion('查询质保状态')">
|
||||
<text class="quick-text">查询质保状态</text>
|
||||
</view>
|
||||
<view class="quick-btn" @tap="handleQuickQuestion('发动机无法启动')">
|
||||
<text class="quick-text">发动机无法启动</text>
|
||||
</view>
|
||||
<view class="quick-btn" @tap="handleQuickQuestion('申请上门维修')">
|
||||
<text class="quick-text">申请上门维修服务</text>
|
||||
</view>
|
||||
<view class="quick-btn" @tap="handleQuickQuestion('查询维修进度')">
|
||||
<text class="quick-text">查询维修进度</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 输入区域 -->
|
||||
<view class="chat-input-wrap">
|
||||
<!-- 已上传文件预览 -->
|
||||
<view v-if="uploadedFiles.length > 0" class="uploaded-files">
|
||||
<view v-for="(file, index) in uploadedFiles" :key="file.id || index" class="uploaded-file-item">
|
||||
<view v-if="isImageFile(file)" class="file-preview-image">
|
||||
<image :src="getFilePreviewUrl(file)" mode="aspectFill" class="preview-img" />
|
||||
</view>
|
||||
<view v-else class="file-preview-doc">
|
||||
<text class="doc-icon">📄</text>
|
||||
</view>
|
||||
<text class="file-name">{{file.name || '文件'}}</text>
|
||||
<view class="remove-file-btn" @tap="removeUploadedFile(index)">
|
||||
<text class="remove-icon">✕</text>
|
||||
</view>
|
||||
<!-- 输入区域 -->
|
||||
<view class="chat-input-wrap">
|
||||
<!-- 已上传文件预览 -->
|
||||
<view v-if="uploadedFiles.length > 0" class="uploaded-files">
|
||||
<view v-for="(file, index) in uploadedFiles" :key="file.id || index" class="uploaded-file-item">
|
||||
<view v-if="isImageFile(file)" class="file-preview-image">
|
||||
<image :src="getFilePreviewUrl(file)" mode="aspectFill" class="preview-img" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- 输入框 -->
|
||||
<view class="input-row">
|
||||
<view class="upload-btn" :class="{ uploading: isUploading }" @tap="showUploadOptions">
|
||||
<text v-if="isUploading" class="upload-icon">⏳</text>
|
||||
<text v-else class="upload-icon">📎</text>
|
||||
<view v-else class="file-preview-doc">
|
||||
<text class="doc-icon">📄</text>
|
||||
</view>
|
||||
<input class="chat-input" v-model="inputText" placeholder="输入问题 来问问我~" @confirm="sendMessage" />
|
||||
<view class="send-btn" :class="{ active: inputText.trim() || uploadedFiles.length > 0 }" @tap="sendMessage">
|
||||
<text class="send-icon">➤</text>
|
||||
<text class="file-name">{{file.name || '文件'}}</text>
|
||||
<view class="remove-file-btn" @tap="removeUploadedFile(index)">
|
||||
<text class="remove-icon">✕</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 输入框 -->
|
||||
<view class="input-row">
|
||||
<view class="upload-btn" :class="{ uploading: isUploading }" @tap="showUploadOptions">
|
||||
<text v-if="isUploading" class="upload-icon">⏳</text>
|
||||
<text v-else class="upload-icon">📎</text>
|
||||
</view>
|
||||
<input class="chat-input" v-model="inputText" placeholder="输入问题 来问问我~" @confirm="sendMessage" />
|
||||
<view class="send-btn" :class="{ active: inputText.trim() || uploadedFiles.length > 0 }"
|
||||
@tap="sendMessage">
|
||||
<text class="send-icon">➤</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 设备代码输入弹窗 -->
|
||||
<view class="device-code-modal" v-if="showDeviceCodeDialog">
|
||||
<view class="modal-mask" @tap="cancelDeviceCodeInput"></view>
|
||||
@@ -157,13 +164,8 @@
|
||||
<text class="modal-title">请输入设备代码</text>
|
||||
</view>
|
||||
<view class="modal-body">
|
||||
<input
|
||||
class="device-code-input"
|
||||
v-model="deviceCodeInput"
|
||||
placeholder="请输入设备代码"
|
||||
focus
|
||||
@confirm="confirmDeviceCodeInput"
|
||||
/>
|
||||
<input class="device-code-input" v-model="deviceCodeInput" placeholder="请输入设备代码" focus
|
||||
@confirm="confirmDeviceCodeInput" />
|
||||
</view>
|
||||
<view class="modal-footer">
|
||||
<button class="modal-btn cancel" @tap="cancelDeviceCodeInput">
|
||||
@@ -176,6 +178,28 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作选择弹窗 -->
|
||||
<view class="operation-select-modal" v-if="showOperationSelectDialog">
|
||||
<view class="modal-mask" @tap="cancelOperationSelect"></view>
|
||||
<view class="modal-content">
|
||||
<view class="modal-header">
|
||||
<text class="modal-title">{{ operationSelectTitle }}</text>
|
||||
</view>
|
||||
<view class="modal-body">
|
||||
<view class="operation-select-list">
|
||||
<view class="operation-select-item" @tap="handleOperationSelect('existing')">
|
||||
<text class="select-icon">📋</text>
|
||||
<text class="select-text">进入已有{{ operationSelectType === 'chat' ? '聊天室' : '工单' }}</text>
|
||||
</view>
|
||||
<view class="operation-select-item" @tap="handleOperationSelect('new')">
|
||||
<text class="select-icon">➕</text>
|
||||
<text class="select-text">创建新{{ operationSelectType === 'chat' ? '聊天室' : '工单' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 手机号授权弹窗 -->
|
||||
<view class="phone-auth-modal" v-if="showPhoneAuthModal">
|
||||
<view class="modal-mask"></view>
|
||||
@@ -237,11 +261,11 @@
|
||||
import { AGENT_ID } from '@/config'
|
||||
// 前端消息展示类型
|
||||
interface ChatMessageItem {
|
||||
type: 'user' | 'bot'
|
||||
content: string
|
||||
time: string
|
||||
actions?: string[] | null
|
||||
files?: string[] // 文件ID数组
|
||||
type : 'user' | 'bot'
|
||||
content : string
|
||||
time : string
|
||||
actions ?: string[] | null
|
||||
files ?: string[] // 文件ID数组
|
||||
}
|
||||
const agentId = AGENT_ID
|
||||
// 响应式数据
|
||||
@@ -268,7 +292,7 @@
|
||||
userId: ''
|
||||
})
|
||||
const userType = ref(false)
|
||||
|
||||
|
||||
// 是否显示手机号授权弹窗
|
||||
const showPhoneAuthModal = ref(false)
|
||||
// 临时保存的微信登录code
|
||||
@@ -283,6 +307,12 @@
|
||||
const deviceCodeInput = ref<string>('') // 弹窗中的设备代码输入
|
||||
const pendingAction = ref<'workcase' | 'human' | ''>('') // 待执行的操作类型
|
||||
|
||||
// 操作选择弹窗相关
|
||||
const showOperationSelectDialog = ref<boolean>(false) // 是否显示操作选择弹窗
|
||||
const operationSelectType = ref<'chat' | 'workcase'>('chat') // 选择类型:chat=聊天室, workcase=工单
|
||||
const operationSelectTitle = ref<string>('') // 弹窗标题
|
||||
const pendingOperation = ref<'existing' | 'new' | ''>('') // 待执行的操作:existing=进入已有, new=创建新的
|
||||
|
||||
// 初始化用户信息
|
||||
async function initUserInfo() {
|
||||
try {
|
||||
@@ -290,7 +320,7 @@
|
||||
const cachedWechatId = uni.getStorageSync('wechatId')
|
||||
const cachedUserInfo = uni.getStorageSync('userInfo')
|
||||
const cachedToken = uni.getStorageSync('token')
|
||||
|
||||
|
||||
if (cachedWechatId && cachedUserInfo && cachedToken) {
|
||||
// 有完整缓存,直接使用
|
||||
const parsedUserInfo = typeof cachedUserInfo === 'string' ? JSON.parse(cachedUserInfo) : cachedUserInfo
|
||||
@@ -300,14 +330,14 @@
|
||||
phone: parsedUserInfo.phone || '',
|
||||
userId: parsedUserInfo.userId || ''
|
||||
}
|
||||
|
||||
|
||||
// 判断用户类型
|
||||
if (parsedUserInfo.status === 'guest') {
|
||||
userType.value = false
|
||||
} else {
|
||||
userType.value = true
|
||||
}
|
||||
|
||||
|
||||
console.log('使用缓存的用户信息:', userInfo.value)
|
||||
return
|
||||
}
|
||||
@@ -324,7 +354,7 @@
|
||||
// 自动登录
|
||||
async function autoLogin() {
|
||||
uni.showLoading({ title: '初始化中...' })
|
||||
|
||||
|
||||
try {
|
||||
// 使用 wx.login 获取 code
|
||||
uni.login({
|
||||
@@ -332,10 +362,10 @@
|
||||
success: async (loginRes) => {
|
||||
console.log('微信登录成功,code:', loginRes.code)
|
||||
uni.hideLoading()
|
||||
|
||||
|
||||
// 保存code,等待手机号授权后使用
|
||||
tempWechatCode.value = loginRes.code
|
||||
|
||||
|
||||
// 显示手机号授权弹窗
|
||||
showPhoneAuthModal.value = true
|
||||
},
|
||||
@@ -345,7 +375,7 @@
|
||||
uni.showToast({ title: '登录失败,请重试', icon: 'none' })
|
||||
}
|
||||
})
|
||||
} catch (error: any) {
|
||||
} catch (error : any) {
|
||||
console.error('自动登录失败:', error)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
@@ -362,7 +392,7 @@
|
||||
uni.removeStorageSync('userInfo')
|
||||
uni.removeStorageSync('loginDomain')
|
||||
uni.removeStorageSync('wechatId')
|
||||
|
||||
|
||||
uni.showLoading({ title: '登录中...' })
|
||||
try {
|
||||
const res = await guestAPI.identify({
|
||||
@@ -379,7 +409,7 @@
|
||||
userInfo.value.userId = loginDomain.user?.userId || ''
|
||||
console.log('identify成功:', loginDomain)
|
||||
uni.showToast({ title: '登录成功', icon: 'success' })
|
||||
if(loginDomain.user.status == 'guest') {
|
||||
if (loginDomain.user.status == 'guest') {
|
||||
userType.value = false
|
||||
} else {
|
||||
userType.value = true
|
||||
@@ -394,12 +424,12 @@
|
||||
}
|
||||
|
||||
// 获取手机号回调(保留用于正式环境)
|
||||
async function onGetPhoneNumber(e: any) {
|
||||
async function onGetPhoneNumber(e : any) {
|
||||
console.log('获取手机号回调:', e)
|
||||
|
||||
|
||||
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
||||
console.error('获取手机号失败:', e.detail)
|
||||
|
||||
|
||||
// 如果是权限问题,提示用户
|
||||
if (e.detail.errno === 102) {
|
||||
uni.showModal({
|
||||
@@ -418,20 +448,20 @@
|
||||
|
||||
// 关闭弹窗
|
||||
showPhoneAuthModal.value = false
|
||||
|
||||
|
||||
uni.showLoading({ title: '登录中...' })
|
||||
|
||||
try {
|
||||
const code = tempWechatCode.value
|
||||
const wechatId = code.substring(0, 20) // 使用部分code作为临时ID
|
||||
|
||||
|
||||
// 获取手机号授权返回的数据
|
||||
const phoneCode = e.detail.code // 手机号授权code(推荐使用)
|
||||
const encryptedData = e.detail.encryptedData // 加密数据
|
||||
const iv = e.detail.iv // 解密向量
|
||||
|
||||
|
||||
console.log('手机号授权数据:', { code, phoneCode, encryptedData: encryptedData?.substring(0, 50) + '...', iv })
|
||||
|
||||
|
||||
// 调用 identify 接口
|
||||
// 后端可以选择使用 phoneCode 或 encryptedData+iv 来解密手机号
|
||||
const identifyRes = await guestAPI.identify({
|
||||
@@ -442,18 +472,18 @@
|
||||
iv: iv, // 解密向量(旧版API)
|
||||
loginType: 'wechat_miniprogram'
|
||||
})
|
||||
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
|
||||
if (identifyRes.success && identifyRes.data) {
|
||||
const loginDomain = identifyRes.data
|
||||
|
||||
|
||||
// 保存登录信息
|
||||
uni.setStorageSync('token', loginDomain.token || '')
|
||||
uni.setStorageSync('userInfo', JSON.stringify(loginDomain.user))
|
||||
uni.setStorageSync('loginDomain', JSON.stringify(loginDomain))
|
||||
uni.setStorageSync('wechatId', wechatId)
|
||||
|
||||
|
||||
// 更新用户信息
|
||||
userInfo.value = {
|
||||
wechatId: wechatId,
|
||||
@@ -461,14 +491,14 @@
|
||||
phone: loginDomain.user?.phone || '',
|
||||
userId: loginDomain.user?.userId || ''
|
||||
}
|
||||
|
||||
|
||||
// 判断用户类型
|
||||
if (loginDomain.user?.status === 'guest') {
|
||||
userType.value = false
|
||||
} else {
|
||||
userType.value = true
|
||||
}
|
||||
|
||||
|
||||
console.log('手机号授权登录成功:', userInfo.value)
|
||||
uni.showToast({ title: '登录成功', icon: 'success' })
|
||||
} else {
|
||||
@@ -479,7 +509,7 @@
|
||||
// 登录失败,重新显示授权弹窗
|
||||
showPhoneAuthModal.value = true
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error : any) {
|
||||
console.error('手机号授权登录失败:', error)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
@@ -492,7 +522,7 @@
|
||||
}
|
||||
|
||||
// 选择模拟用户(测试用)
|
||||
async function selectMockUser(phone: string, name: string, wechatId: string) {
|
||||
async function selectMockUser(phone : string, name : string, wechatId : string) {
|
||||
showPhoneAuthModal.value = false
|
||||
uni.showLoading({ title: '登录中...' })
|
||||
|
||||
@@ -505,18 +535,18 @@
|
||||
mockMode: true,
|
||||
loginType: 'wechat_miniprogram'
|
||||
})
|
||||
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
|
||||
if (identifyRes.success && identifyRes.data) {
|
||||
const loginDomain = identifyRes.data
|
||||
|
||||
|
||||
// 保存登录信息
|
||||
uni.setStorageSync('token', loginDomain.token || '')
|
||||
uni.setStorageSync('userInfo', JSON.stringify(loginDomain.user))
|
||||
uni.setStorageSync('loginDomain', JSON.stringify(loginDomain))
|
||||
uni.setStorageSync('wechatId', wechatId)
|
||||
|
||||
|
||||
// 更新用户信息
|
||||
userInfo.value = {
|
||||
wechatId: wechatId,
|
||||
@@ -524,14 +554,14 @@
|
||||
phone: phone,
|
||||
userId: loginDomain.user?.userId || ''
|
||||
}
|
||||
|
||||
|
||||
// 判断用户类型
|
||||
if (loginDomain.user?.status === 'guest') {
|
||||
userType.value = false
|
||||
} else {
|
||||
userType.value = true
|
||||
}
|
||||
|
||||
|
||||
console.log('模拟登录成功:', userInfo.value)
|
||||
uni.showToast({ title: `${name} 登录成功`, icon: 'success' })
|
||||
} else {
|
||||
@@ -541,7 +571,7 @@
|
||||
})
|
||||
showPhoneAuthModal.value = true
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error : any) {
|
||||
console.error('模拟登录失败:', error)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
@@ -570,7 +600,7 @@
|
||||
// 获取窗口信息
|
||||
const windowInfo = uni.getWindowInfo()
|
||||
statusBarHeight.value = windowInfo.statusBarHeight || 0
|
||||
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 获取胶囊按钮信息(仅小程序),计算header位置
|
||||
try {
|
||||
@@ -602,7 +632,7 @@
|
||||
})
|
||||
|
||||
// 添加用户消息(包含文件)
|
||||
const userMessage: ChatMessageItem = {
|
||||
const userMessage : ChatMessageItem = {
|
||||
type: 'user',
|
||||
content: text,
|
||||
time: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
|
||||
@@ -640,7 +670,7 @@
|
||||
}
|
||||
|
||||
// 准备流式对话(包含文件)
|
||||
const prepareData: ChatPrepareData = {
|
||||
const prepareData : ChatPrepareData = {
|
||||
chatId: chatId.value,
|
||||
query: query,
|
||||
agentId: agentId,
|
||||
@@ -776,7 +806,7 @@
|
||||
}
|
||||
|
||||
// 检查并获取设备代码
|
||||
function checkDeviceCode(action: 'workcase' | 'human') {
|
||||
function checkDeviceCode(action : 'workcase' | 'human') {
|
||||
if (!deviceCode.value) {
|
||||
// 如果没有设备代码,显示输入弹窗
|
||||
pendingAction.value = action
|
||||
@@ -881,7 +911,7 @@
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error : any) {
|
||||
uni.hideLoading()
|
||||
console.error('创建聊天室失败:', error)
|
||||
uni.showToast({
|
||||
@@ -891,6 +921,47 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 显示操作选择弹窗
|
||||
function showOperationSelect(type : 'chat' | 'workcase') {
|
||||
operationSelectType.value = type
|
||||
operationSelectTitle.value = type === 'chat' ? '选择聊天室操作' : '选择工单操作'
|
||||
showOperationSelectDialog.value = true
|
||||
}
|
||||
|
||||
// 处理操作选择
|
||||
function handleOperationSelect(operation : 'existing' | 'new') {
|
||||
showOperationSelectDialog.value = false
|
||||
pendingOperation.value = operation
|
||||
|
||||
if (operation === 'existing') {
|
||||
// 进入已有
|
||||
if (operationSelectType.value === 'chat') {
|
||||
// 进入已有聊天室
|
||||
goToChatRoomList()
|
||||
} else {
|
||||
// 进入已有工单
|
||||
goToWorkList()
|
||||
}
|
||||
} else {
|
||||
// 创建新的
|
||||
if (operationSelectType.value === 'chat') {
|
||||
// 创建新聊天室(联系人工)
|
||||
contactHuman()
|
||||
} else {
|
||||
// 创建新工单
|
||||
showCreator()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 取消操作选择
|
||||
function cancelOperationSelect() {
|
||||
showOperationSelectDialog.value = false
|
||||
operationSelectType.value = 'chat'
|
||||
operationSelectTitle.value = ''
|
||||
pendingOperation.value = ''
|
||||
}
|
||||
|
||||
// 直接跳转到工单详情页的 create 模式(复用 workcaseDetail 页面)
|
||||
async function showCreator() {
|
||||
// 检查设备代码
|
||||
@@ -1023,7 +1094,7 @@
|
||||
sourceType: ['album'],
|
||||
success: (res) => {
|
||||
if (res.tempFilePaths && res.tempFilePaths.length > 0) {
|
||||
res.tempFilePaths.forEach((filePath: string) => {
|
||||
res.tempFilePaths.forEach((filePath : string) => {
|
||||
uploadSingleFile(filePath)
|
||||
})
|
||||
}
|
||||
@@ -1039,15 +1110,15 @@
|
||||
count: 5,
|
||||
type: 'file',
|
||||
extension: ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'txt'],
|
||||
success: (res: any) => {
|
||||
success: (res : any) => {
|
||||
console.log('选择文件成功:', res)
|
||||
if (res.tempFiles && res.tempFiles.length > 0) {
|
||||
res.tempFiles.forEach((file: any) => {
|
||||
res.tempFiles.forEach((file : any) => {
|
||||
uploadSingleFile(file.path)
|
||||
})
|
||||
}
|
||||
},
|
||||
fail: (err: any) => {
|
||||
fail: (err : any) => {
|
||||
console.error('选择文件失败:', err)
|
||||
uni.showToast({
|
||||
title: '选择文件失败',
|
||||
@@ -1065,15 +1136,15 @@
|
||||
uni.chooseFile({
|
||||
count: 5,
|
||||
extension: ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.txt'],
|
||||
success: (res: any) => {
|
||||
success: (res : any) => {
|
||||
console.log('选择文件成功:', res)
|
||||
if (res.tempFilePaths && res.tempFilePaths.length > 0) {
|
||||
res.tempFilePaths.forEach((filePath: string) => {
|
||||
res.tempFilePaths.forEach((filePath : string) => {
|
||||
uploadSingleFile(filePath)
|
||||
})
|
||||
}
|
||||
},
|
||||
fail: (err: any) => {
|
||||
fail: (err : any) => {
|
||||
console.error('选择文件失败:', err)
|
||||
uni.showToast({
|
||||
title: '选择文件失败',
|
||||
@@ -1091,7 +1162,7 @@
|
||||
}
|
||||
|
||||
// 上传单个文件
|
||||
async function uploadSingleFile(filePath: string) {
|
||||
async function uploadSingleFile(filePath : string) {
|
||||
console.log('开始上传文件:', filePath)
|
||||
|
||||
if (!agentId) {
|
||||
@@ -1112,7 +1183,7 @@
|
||||
} else {
|
||||
uni.showToast({ title: result.message || '上传失败', icon: 'none' })
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error : any) {
|
||||
console.error('文件上传失败:', error)
|
||||
uni.showToast({ title: '上传失败: ' + (error.message || '未知错误'), icon: 'none' })
|
||||
} finally {
|
||||
@@ -1122,27 +1193,27 @@
|
||||
}
|
||||
|
||||
// 移除已上传的文件
|
||||
function removeUploadedFile(index: number) {
|
||||
function removeUploadedFile(index : number) {
|
||||
uploadedFiles.value.splice(index, 1)
|
||||
}
|
||||
|
||||
// 判断是否为图片文件
|
||||
function isImageFile(file: DifyFileInfo): boolean {
|
||||
function isImageFile(file : DifyFileInfo) : boolean {
|
||||
return file.type === 'image' || file.mime_type?.startsWith('image/') || false
|
||||
}
|
||||
|
||||
// 获取文件预览URL
|
||||
function getFilePreviewUrl(file: DifyFileInfo): string {
|
||||
function getFilePreviewUrl(file : DifyFileInfo) : string {
|
||||
return file.preview_url || file.source_url || file.url || ''
|
||||
}
|
||||
|
||||
// 获取文件下载URL(通过文件ID)
|
||||
function getFileDownloadUrl(fileId: string): string {
|
||||
function getFileDownloadUrl(fileId : string) : string {
|
||||
return fileAPI.getDownloadUrl(fileId)
|
||||
}
|
||||
|
||||
// 判断文件ID对应的文件是否为图片
|
||||
function isImageFileById(fileId: string): boolean {
|
||||
function isImageFileById(fileId : string) : boolean {
|
||||
// 从缓存中查找文件信息
|
||||
const file = fileInfoCache.value.get(fileId)
|
||||
if (file) {
|
||||
@@ -1157,13 +1228,13 @@
|
||||
}
|
||||
|
||||
// 获取文件名(从缓存)
|
||||
function getFileName(fileId: string): string {
|
||||
function getFileName(fileId : string) : string {
|
||||
const file = fileInfoCache.value.get(fileId)
|
||||
return file?.name || fileId.substring(0, 8) + '...'
|
||||
}
|
||||
|
||||
// 文件预览
|
||||
function previewFile(fileId: string) {
|
||||
function previewFile(fileId : string) {
|
||||
const url = getFileDownloadUrl(fileId)
|
||||
// 如果是图片,使用图片预览
|
||||
if (isImageFileById(fileId)) {
|
||||
@@ -1191,7 +1262,6 @@
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Reference in New Issue
Block a user