聊天室url修正
This commit is contained in:
@@ -263,8 +263,8 @@ CREATE TABLE workcase.tb_workcase(
|
|||||||
type VARCHAR(50) NOT NULL, -- 故障类型
|
type VARCHAR(50) NOT NULL, -- 故障类型
|
||||||
device VARCHAR(50) DEFAULT NULL, -- 设备名称
|
device VARCHAR(50) DEFAULT NULL, -- 设备名称
|
||||||
device_code VARCHAR(50) DEFAULT NULL, -- 设备代码
|
device_code VARCHAR(50) DEFAULT NULL, -- 设备代码
|
||||||
device_name_plate VARCHAR(50) DEFAULT NULL, -- 设备名称牌
|
device_name_plate VARCHAR(50) NOT NULL, -- 设备名称牌
|
||||||
device_name_plate_img VARCHAR(50) NOT NULL, -- 设备名称牌图片
|
device_name_plate_img VARCHAR(50) DEFAULT NULL, -- 设备名称牌图片
|
||||||
address VARCHAR(1000) DEFAULT NULL, -- 现场地址
|
address VARCHAR(1000) DEFAULT NULL, -- 现场地址
|
||||||
description VARCHAR(1000) DEFAULT NULL, -- 故障描述
|
description VARCHAR(1000) DEFAULT NULL, -- 故障描述
|
||||||
imgs VARCHAR(50)[] DEFAULT '{}', -- 工单图片id
|
imgs VARCHAR(50)[] DEFAULT '{}', -- 工单图片id
|
||||||
|
|||||||
@@ -120,4 +120,6 @@ public class LoginParam implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String iv;
|
private String iv;
|
||||||
|
|
||||||
|
private Boolean mockMode;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ public class AesEncryptUtil {
|
|||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
AesEncryptUtil aesEncryptUtil = new AesEncryptUtil("MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=");
|
AesEncryptUtil aesEncryptUtil = new AesEncryptUtil("MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=");
|
||||||
String phone = "17857100376";
|
String phone = "15170037929";
|
||||||
|
|
||||||
// 测试加密(每次都不同,不能用于查询)
|
// 测试加密(每次都不同,不能用于查询)
|
||||||
String encryptedPhone1 = aesEncryptUtil.encryptPhone(phone);
|
String encryptedPhone1 = aesEncryptUtil.encryptPhone(phone);
|
||||||
|
|||||||
@@ -127,14 +127,44 @@ public class GuestController {
|
|||||||
|
|
||||||
// ========================= 微信小程序用户识别登录 =========================
|
// ========================= 微信小程序用户识别登录 =========================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模拟用户数据(用于测试,没有手机号校验appid时使用)
|
||||||
|
* 格式:手机号 -> [姓名, 微信ID, 角色]
|
||||||
|
*/
|
||||||
|
private static final java.util.Map<String, String[]> MOCK_USERS = new java.util.HashMap<String, String[]>() {{
|
||||||
|
put("17857100375", new String[]{"超级管理员", "17857100375", "admin"});
|
||||||
|
put("13870055185", new String[]{"魏瑶", "75719954", "engineer"});
|
||||||
|
put("15170466624", new String[]{"刘杰", "liujie1370984851", "engineer"});
|
||||||
|
put("15170037929", new String[]{"万家明", "WJM15170037929", "engineer"});
|
||||||
|
put("19100185270", new String[]{"戴斌", "BaiBin0714", "guest"});
|
||||||
|
put("15797790517", new String[]{"余其跃", "a540378218", "guest"});
|
||||||
|
put("15879126468", new String[]{"李小华", "wxid_vgmmzfdcwx9021", "guest"});
|
||||||
|
}};
|
||||||
|
|
||||||
@Operation(summary = "微信小程序用户识别登录")
|
@Operation(summary = "微信小程序用户识别登录")
|
||||||
@PostMapping("/identify")
|
@PostMapping("/identify")
|
||||||
public ResultDomain<LoginDomain> identifyUser(@RequestBody LoginParam loginParam, HttpServletRequest request) {
|
public ResultDomain<LoginDomain> identifyUser(@RequestBody LoginParam loginParam, HttpServletRequest request) {
|
||||||
logger.info("微信小程序登录请求: wechatId={}, code={}, phoneCode={}",
|
logger.info("微信小程序登录请求: wechatId={}, phone={}, mockMode={}",
|
||||||
loginParam.getWechatId(),
|
loginParam.getWechatId(),
|
||||||
loginParam.getCode() != null ? loginParam.getCode().substring(0, Math.min(10, loginParam.getCode().length())) + "..." : null,
|
loginParam.getPhone(),
|
||||||
loginParam.getPhoneCode() != null ? "有" : "无");
|
loginParam.getMockMode() != null ? loginParam.getMockMode() : false);
|
||||||
|
|
||||||
|
// ========== 模拟模式:直接使用传入的手机号匹配用户 ==========
|
||||||
|
if (Boolean.TRUE.equals(loginParam.getMockMode()) && loginParam.getPhone() != null) {
|
||||||
|
String phone = loginParam.getPhone().trim();
|
||||||
|
String[] mockUser = MOCK_USERS.get(phone);
|
||||||
|
|
||||||
|
if (mockUser != null) {
|
||||||
|
// 设置模拟用户信息
|
||||||
|
loginParam.setUsername(mockUser[0]);
|
||||||
|
loginParam.setWechatId(mockUser[1]);
|
||||||
|
logger.info("模拟登录: phone={}, name={}, wechatId={}, role={}",
|
||||||
|
phone, mockUser[0], mockUser[1], mockUser[2]);
|
||||||
|
} else {
|
||||||
|
return ResultDomain.failure("未找到该手机号对应的测试用户");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ========== 正常模式:通过微信API获取手机号 ==========
|
||||||
// 1. 处理微信登录code,获取openid
|
// 1. 处理微信登录code,获取openid
|
||||||
String openid = null;
|
String openid = null;
|
||||||
String sessionKey = null;
|
String sessionKey = null;
|
||||||
@@ -144,7 +174,6 @@ public class GuestController {
|
|||||||
openid = sessionResult.getData().getOpenid();
|
openid = sessionResult.getData().getOpenid();
|
||||||
sessionKey = sessionResult.getData().getSessionKey();
|
sessionKey = sessionResult.getData().getSessionKey();
|
||||||
logger.info("获取openid成功: {}", openid);
|
logger.info("获取openid成功: {}", openid);
|
||||||
// 使用openid作为wechatId
|
|
||||||
loginParam.setWechatId(openid);
|
loginParam.setWechatId(openid);
|
||||||
} else {
|
} else {
|
||||||
logger.warn("获取openid失败: {}", sessionResult.getMessage());
|
logger.warn("获取openid失败: {}", sessionResult.getMessage());
|
||||||
@@ -186,6 +215,7 @@ public class GuestController {
|
|||||||
if (phoneNumber != null) {
|
if (phoneNumber != null) {
|
||||||
loginParam.setPhone(phoneNumber);
|
loginParam.setPhone(phoneNumber);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 验证参数:必须有wechatId或phone
|
// 验证参数:必须有wechatId或phone
|
||||||
if ((loginParam.getWechatId() == null || loginParam.getWechatId().trim().isEmpty())
|
if ((loginParam.getWechatId() == null || loginParam.getWechatId().trim().isEmpty())
|
||||||
|
|||||||
@@ -87,6 +87,18 @@ public class WorkcaseController {
|
|||||||
return workcaseService.deleteWorkcase(workcase);
|
return workcaseService.deleteWorkcase(workcase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "撤销工单")
|
||||||
|
@PreAuthorize("hasAuthority('workcase:ticket:update')")
|
||||||
|
@PostMapping("/revoke/{workcaseId}")
|
||||||
|
public ResultDomain<TbWorkcaseProcessDTO> revokeWorkcase(@PathVariable(value = "workcaseId") String workcaseId) {
|
||||||
|
// 创建撤销处理过程
|
||||||
|
TbWorkcaseProcessDTO process = new TbWorkcaseProcessDTO();
|
||||||
|
process.setWorkcaseId(workcaseId);
|
||||||
|
process.setAction("repeal");
|
||||||
|
process.setMessage("用户撤销工单");
|
||||||
|
return workcaseService.createWorkcaseProcess(process);
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "获取工单详情")
|
@Operation(summary = "获取工单详情")
|
||||||
@PreAuthorize("hasAuthority('workcase:ticket:view')")
|
@PreAuthorize("hasAuthority('workcase:ticket:view')")
|
||||||
@GetMapping("/{workcaseId}")
|
@GetMapping("/{workcaseId}")
|
||||||
|
|||||||
@@ -376,6 +376,7 @@ public class VideoMeetingServiceImpl implements VideoMeetingService {
|
|||||||
meeting.setJwtToken(userJwtToken);
|
meeting.setJwtToken(userJwtToken);
|
||||||
meeting.setJitsiIframeUrl(jitsiIframeUrl); // 真正的Jitsi URL
|
meeting.setJitsiIframeUrl(jitsiIframeUrl); // 真正的Jitsi URL
|
||||||
meeting.setIframeUrl(meetingPageUrl); // 会议页面URL(用于router跳转)
|
meeting.setIframeUrl(meetingPageUrl); // 会议页面URL(用于router跳转)
|
||||||
|
meeting.setJitsiServerUrl(jitsiProperties.getServer().getUrl()); // 使用当前配置的服务器URL
|
||||||
|
|
||||||
logger.info("生成用户专属会议URL成功: meetingId={}, userId={}, status={}",
|
logger.info("生成用户专属会议URL成功: meetingId={}, userId={}, status={}",
|
||||||
meetingId, userId, meeting.getStatus());
|
meetingId, userId, meeting.getStatus());
|
||||||
|
|||||||
@@ -416,10 +416,38 @@ public class WorkcaseServiceImpl implements WorkcaseService {
|
|||||||
// 不影响工单完成流程,只记录错误日志
|
// 不影响工单完成流程,只记录错误日志
|
||||||
}
|
}
|
||||||
} else if (WorkcaseProcessAction.REPEAL.getName().equals(action)) {
|
} else if (WorkcaseProcessAction.REPEAL.getName().equals(action)) {
|
||||||
|
// 1. 更新工单状态为已撤销
|
||||||
TbWorkcaseDTO workcase = new TbWorkcaseDTO();
|
TbWorkcaseDTO workcase = new TbWorkcaseDTO();
|
||||||
workcase.setWorkcaseId(workcaseProcess.getWorkcaseId());
|
workcase.setWorkcaseId(workcaseProcess.getWorkcaseId());
|
||||||
workcase.setStatus("cancelled");
|
workcase.setStatus("cancelled");
|
||||||
workcaseMapper.updateWorkcase(workcase);
|
workcaseMapper.updateWorkcase(workcase);
|
||||||
|
|
||||||
|
// 2. 发送系统评分消息到聊天室
|
||||||
|
try {
|
||||||
|
TbWorkcaseDTO workcaseData = workcaseMapper.selectWorkcaseById(workcaseProcess.getWorkcaseId());
|
||||||
|
if (workcaseData != null && workcaseData.getRoomId() != null) {
|
||||||
|
// 创建系统评分消息
|
||||||
|
org.xyzh.api.workcase.dto.TbChatRoomMessageDTO commentMessage = new org.xyzh.api.workcase.dto.TbChatRoomMessageDTO();
|
||||||
|
commentMessage.setMessageId(IdUtil.generateUUID());
|
||||||
|
commentMessage.setOptsn(IdUtil.getOptsn());
|
||||||
|
commentMessage.setRoomId(workcaseData.getRoomId());
|
||||||
|
commentMessage.setSenderId("system");
|
||||||
|
commentMessage.setSenderType("system"); // 系统消息
|
||||||
|
commentMessage.setSenderName("系统");
|
||||||
|
commentMessage.setMessageType("comment"); // 评分消息
|
||||||
|
commentMessage.setContent("工单已撤销,请为本次服务评分");
|
||||||
|
commentMessage.setStatus("sent");
|
||||||
|
commentMessage.setCreator("system");
|
||||||
|
|
||||||
|
// 发送消息到聊天室
|
||||||
|
chatRoomService.sendMessage(commentMessage);
|
||||||
|
logger.info("工单撤销,已发送系统评分消息: workcaseId={}, roomId={}",
|
||||||
|
workcaseProcess.getWorkcaseId(), workcaseData.getRoomId());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("发送系统评分消息失败: workcaseId={}", workcaseProcess.getWorkcaseId(), e);
|
||||||
|
// 不影响工单撤销流程,只记录错误日志
|
||||||
|
}
|
||||||
}
|
}
|
||||||
workcaseProcess.setCreator(LoginUtil.getCurrentUserId());
|
workcaseProcess.setCreator(LoginUtil.getCurrentUserId());
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,15 @@ export const workcaseAPI = {
|
|||||||
return response.data
|
return response.data
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销工单
|
||||||
|
* @param workcaseId 工单ID
|
||||||
|
*/
|
||||||
|
async revokeWorkcase(workcaseId: string): Promise<ResultDomain<TbWorkcaseProcessDTO>> {
|
||||||
|
const response = await api.post<TbWorkcaseProcessDTO>(`${this.baseUrl}/revoke/${workcaseId}`)
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取工单详情
|
* 获取工单详情
|
||||||
* @param workcaseId 工单ID
|
* @param workcaseId 工单ID
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<AdminLayout title="工单管理" info="查看和处理客户服务工单">
|
<AdminLayout title="工单管理" info="查看和处理客户服务工单">
|
||||||
<template #action>
|
<!-- <template #action>
|
||||||
<el-button type="primary" @click="showCreateDialog = true">
|
<el-button type="primary" @click="showCreateDialog = true">
|
||||||
<el-icon><Plus /></el-icon>
|
<el-icon><Plus /></el-icon>
|
||||||
创建工单
|
创建工单
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template> -->
|
||||||
|
|
||||||
<div class="workcase-container">
|
<div class="workcase-container">
|
||||||
<!-- 筛选区域 -->
|
<!-- 筛选区域 -->
|
||||||
|
|||||||
@@ -471,7 +471,7 @@ const handleSendMessage = async (content: string, files: File[]) => {
|
|||||||
roomId: currentRoomId.value,
|
roomId: currentRoomId.value,
|
||||||
senderId: loginDomain.user.userId,
|
senderId: loginDomain.user.userId,
|
||||||
senderName: loginDomain.userInfo.username,
|
senderName: loginDomain.userInfo.username,
|
||||||
senderType: 'agent',
|
senderType: 'staff',
|
||||||
content,
|
content,
|
||||||
files: fileIds,
|
files: fileIds,
|
||||||
messageType: 'text'
|
messageType: 'text'
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ const getMeetingParams = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 加载 Jitsi External API 脚本
|
// 加载 Jitsi External API 脚本
|
||||||
const loadJitsiScript = (): Promise<void> => {
|
const loadJitsiScript = (jitsiServerUrl: string): Promise<void> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// 检查是否已经加载
|
// 检查是否已经加载
|
||||||
if ((window as any).JitsiMeetExternalAPI) {
|
if ((window as any).JitsiMeetExternalAPI) {
|
||||||
@@ -61,16 +61,19 @@ const loadJitsiScript = (): Promise<void> => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从 jitsiServerUrl 提取域名
|
||||||
|
const urlObj = new URL(jitsiServerUrl)
|
||||||
|
const scriptUrl = `${urlObj.protocol}//${urlObj.host}/external_api.js`
|
||||||
|
|
||||||
const script = document.createElement('script')
|
const script = document.createElement('script')
|
||||||
// 从 Jitsi 子域名加载 External API
|
script.src = scriptUrl
|
||||||
script.src = 'https://org.xyzh.yslg.jitsi/external_api.js'
|
|
||||||
script.async = true
|
script.async = true
|
||||||
script.onload = () => {
|
script.onload = () => {
|
||||||
console.log('[JitsiMeetingView] Jitsi External API 脚本加载成功')
|
console.log('[JitsiMeetingView] Jitsi External API 脚本加载成功:', scriptUrl)
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
script.onerror = () => {
|
script.onerror = () => {
|
||||||
reject(new Error('加载 Jitsi External API 失败'))
|
reject(new Error('加载 Jitsi External API 失败: ' + scriptUrl))
|
||||||
}
|
}
|
||||||
document.head.appendChild(script)
|
document.head.appendChild(script)
|
||||||
})
|
})
|
||||||
@@ -85,8 +88,8 @@ const initJitsiMeet = async (jitsiServerUrl: string, roomName: string, jwt: stri
|
|||||||
name: displayName
|
name: displayName
|
||||||
})
|
})
|
||||||
|
|
||||||
// 加载 External API 脚本
|
// 加载 External API 脚本(从服务器URL动态获取)
|
||||||
await loadJitsiScript()
|
await loadJitsiScript(jitsiServerUrl)
|
||||||
|
|
||||||
const JitsiMeetExternalAPI = (window as any).JitsiMeetExternalAPI
|
const JitsiMeetExternalAPI = (window as any).JitsiMeetExternalAPI
|
||||||
|
|
||||||
|
|||||||
@@ -39,44 +39,6 @@
|
|||||||
// 检查并选择模式
|
// 检查并选择模式
|
||||||
checkModeSelection() {
|
checkModeSelection() {
|
||||||
const mode = uni.getStorageSync('userMode')
|
const mode = uni.getStorageSync('userMode')
|
||||||
if (!mode) {
|
|
||||||
this.showModeSelector()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 显示模式选择器
|
|
||||||
showModeSelector() {
|
|
||||||
uni.showActionSheet({
|
|
||||||
itemList: ['员工模式 (17857100375)', '访客模式 (17857100377)'],
|
|
||||||
success: (res) => {
|
|
||||||
let wechatId = ''
|
|
||||||
let userMode = ''
|
|
||||||
let phone = ''
|
|
||||||
if (res.tapIndex === 0) {
|
|
||||||
wechatId = '17857100375'
|
|
||||||
phone = '17857100375'
|
|
||||||
userMode = 'staff'
|
|
||||||
} else {
|
|
||||||
wechatId = '17857100377'
|
|
||||||
phone = '17857100377'
|
|
||||||
userMode = 'guest'
|
|
||||||
}
|
|
||||||
// 存储选择
|
|
||||||
uni.setStorageSync('userMode', userMode)
|
|
||||||
uni.setStorageSync('wechatId', wechatId)
|
|
||||||
uni.setStorageSync('phone', phone)
|
|
||||||
console.log('已选择模式:', userMode, 'wechatId:', wechatId)
|
|
||||||
uni.showToast({
|
|
||||||
title: userMode === 'staff' ? '员工模式' : '访客模式',
|
|
||||||
icon: 'success'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
fail: () => {
|
|
||||||
// 用户取消,默认使用访客模式
|
|
||||||
uni.setStorageSync('userMode', 'guest')
|
|
||||||
uni.setStorageSync('wechatId', '17857100377')
|
|
||||||
console.log('默认使用访客模式')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,14 @@ export const workcaseAPI = {
|
|||||||
return request<TbWorkcaseDTO>({ url: `${this.baseUrl}/${workcaseId}`, method: 'DELETE' })
|
return request<TbWorkcaseDTO>({ url: `${this.baseUrl}/${workcaseId}`, method: 'DELETE' })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤销工单
|
||||||
|
* @param workcaseId 工单ID
|
||||||
|
*/
|
||||||
|
revokeWorkcase(workcaseId: string): Promise<ResultDomain<TbWorkcaseProcessDTO>> {
|
||||||
|
return request<TbWorkcaseProcessDTO>({ url: `${this.baseUrl}/revoke/${workcaseId}`, method: 'POST' })
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取工单详情
|
* 获取工单详情
|
||||||
* @param workcaseId 工单ID
|
* @param workcaseId 工单ID
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"uni-app-x" : {},
|
"uni-app-x" : {},
|
||||||
"quickapp" : {},
|
"quickapp" : {},
|
||||||
"mp-weixin" : {
|
"mp-weixin" : {
|
||||||
"appid" : "wx15e67484db6d431f",
|
"appid" : "wx3708f41b1dc31f52",
|
||||||
"setting" : {
|
"setting" : {
|
||||||
"urlCheck" : false,
|
"urlCheck" : false,
|
||||||
"postcss" : true,
|
"postcss" : true,
|
||||||
|
|||||||
@@ -79,9 +79,9 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 普通用户/客服消息 -->
|
<!-- 普通用户/客服消息 -->
|
||||||
<view v-else :class="msg.senderType === 'guest' ? 'self' : 'other'">
|
<view v-else :class="msg.senderId === currentUserId ? 'self' : 'other'">
|
||||||
<!-- 对方消息(左侧) -->
|
<!-- 对方消息(左侧) -->
|
||||||
<view class="message-row other-row" v-if="msg.senderType !== 'guest'">
|
<view class="message-row other-row" v-if="msg.senderId !== currentUserId">
|
||||||
<view>
|
<view>
|
||||||
<view class="avatar">
|
<view class="avatar">
|
||||||
<text class="avatar-text">{{ msg.senderName?.charAt(0) || '客' }}</text>
|
<text class="avatar-text">{{ msg.senderName?.charAt(0) || '客' }}</text>
|
||||||
@@ -174,11 +174,25 @@ const currentUserName = ref<string>('我')
|
|||||||
function loadUserInfo() {
|
function loadUserInfo() {
|
||||||
try {
|
try {
|
||||||
const userInfo = uni.getStorageSync('userInfo')
|
const userInfo = uni.getStorageSync('userInfo')
|
||||||
|
const loginDomain = uni.getStorageSync('loginDomain')
|
||||||
if (userInfo) {
|
if (userInfo) {
|
||||||
const user = typeof userInfo === 'string' ? JSON.parse(userInfo) : userInfo
|
const user = typeof userInfo === 'string' ? JSON.parse(userInfo) : userInfo
|
||||||
currentUserId.value = user.userId || user.id || ''
|
currentUserId.value = user.userId || user.id || ''
|
||||||
currentUserName.value = user.username || user.nickName || '我'
|
// 优先从 loginDomain.userInfo 获取用户名
|
||||||
|
if (loginDomain) {
|
||||||
|
const domain = typeof loginDomain === 'string' ? JSON.parse(loginDomain) : loginDomain
|
||||||
|
if (domain.userInfo && domain.userInfo.username) {
|
||||||
|
currentUserName.value = domain.userInfo.username
|
||||||
|
} else if (domain.userInfo && domain.userInfo.realName) {
|
||||||
|
currentUserName.value = domain.userInfo.realName
|
||||||
|
} else {
|
||||||
|
currentUserName.value = user.username || user.nickName || user.realName || user.name || '用户'
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
currentUserName.value = user.username || user.nickName || user.realName || user.name || '用户'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('[chatRoom] 用户信息:', currentUserId.value, currentUserName.value)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('获取用户信息失败:', e)
|
console.error('获取用户信息失败:', e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -903,3 +903,53 @@
|
|||||||
.skip-auth-btn::after {
|
.skip-auth-btn::after {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 模拟用户选择列表样式
|
||||||
|
.mock-user-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-user-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-title {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #999;
|
||||||
|
font-weight: 500;
|
||||||
|
padding-left: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-user-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mock-user-item:active {
|
||||||
|
background: #e9ecef;
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-name {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-phone {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
<view class="header" :style="{ paddingTop: headerPaddingTop + 'px', height: headerTotalHeight + 'px' }">
|
<view class="header" :style="{ paddingTop: headerPaddingTop + 'px', height: headerTotalHeight + 'px' }">
|
||||||
<text class="title">泰豪小电</text>
|
<text class="title">泰豪小电</text>
|
||||||
<view class="header-right">
|
<view class="header-right">
|
||||||
|
<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="goToChatRoomList">
|
||||||
<text class="btn-text">聊天室</text>
|
<text class="btn-text">聊天室</text>
|
||||||
</button>
|
</button>
|
||||||
@@ -178,22 +181,48 @@
|
|||||||
<view class="modal-mask"></view>
|
<view class="modal-mask"></view>
|
||||||
<view class="modal-content phone-auth-content">
|
<view class="modal-content phone-auth-content">
|
||||||
<view class="modal-header">
|
<view class="modal-header">
|
||||||
<text class="modal-title">欢迎使用泰豪小电</text>
|
<text class="modal-title">选择测试用户</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="modal-body phone-auth-body">
|
<view class="modal-body phone-auth-body">
|
||||||
<view class="auth-icon-wrap">
|
<view class="mock-user-list">
|
||||||
<text class="auth-icon">📱</text>
|
<view class="mock-user-group">
|
||||||
|
<text class="group-title">管理员</text>
|
||||||
|
<view class="mock-user-item" @tap="selectMockUser('17857100375', '超级管理员', '17857100375')">
|
||||||
|
<text class="user-name">超级管理员</text>
|
||||||
|
<text class="user-phone">17857100375</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mock-user-group">
|
||||||
|
<text class="group-title">工程师</text>
|
||||||
|
<view class="mock-user-item" @tap="selectMockUser('13870055185', '魏瑶', '75719954')">
|
||||||
|
<text class="user-name">魏瑶</text>
|
||||||
|
<text class="user-phone">13870055185</text>
|
||||||
|
</view>
|
||||||
|
<view class="mock-user-item" @tap="selectMockUser('15170466624', '刘杰', 'liujie1370984851')">
|
||||||
|
<text class="user-name">刘杰</text>
|
||||||
|
<text class="user-phone">15170466624</text>
|
||||||
|
</view>
|
||||||
|
<view class="mock-user-item" @tap="selectMockUser('15170037929', '万家明', 'WJM15170037929')">
|
||||||
|
<text class="user-name">万家明</text>
|
||||||
|
<text class="user-phone">15170037929</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mock-user-group">
|
||||||
|
<text class="group-title">客户</text>
|
||||||
|
<view class="mock-user-item" @tap="selectMockUser('19100185270', '戴斌', 'BaiBin0714')">
|
||||||
|
<text class="user-name">戴斌</text>
|
||||||
|
<text class="user-phone">19100185270</text>
|
||||||
|
</view>
|
||||||
|
<view class="mock-user-item" @tap="selectMockUser('15797790517', '余其跃', 'a540378218')">
|
||||||
|
<text class="user-name">余其跃</text>
|
||||||
|
<text class="user-phone">15797790517</text>
|
||||||
|
</view>
|
||||||
|
<view class="mock-user-item" @tap="selectMockUser('15879126468', '李小华', 'wxid_vgmmzfdcwx9021')">
|
||||||
|
<text class="user-name">李小华</text>
|
||||||
|
<text class="user-phone">15879126468</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<text class="auth-desc">为了给您提供更好的服务,需要获取您的手机号用于身份识别和工单通知</text>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="modal-footer phone-auth-footer">
|
|
||||||
<button
|
|
||||||
class="modal-btn confirm phone-auth-btn"
|
|
||||||
open-type="getPhoneNumber"
|
|
||||||
@getphonenumber="onGetPhoneNumber"
|
|
||||||
>
|
|
||||||
<text class="btn-text">授权手机号登录</text>
|
|
||||||
</button>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -364,7 +393,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取手机号回调
|
// 获取手机号回调(保留用于正式环境)
|
||||||
async function onGetPhoneNumber(e: any) {
|
async function onGetPhoneNumber(e: any) {
|
||||||
console.log('获取手机号回调:', e)
|
console.log('获取手机号回调:', e)
|
||||||
|
|
||||||
@@ -462,6 +491,72 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 选择模拟用户(测试用)
|
||||||
|
async function selectMockUser(phone: string, name: string, wechatId: string) {
|
||||||
|
showPhoneAuthModal.value = false
|
||||||
|
uni.showLoading({ title: '登录中...' })
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用 identify 接口,使用模拟模式
|
||||||
|
const identifyRes = await guestAPI.identify({
|
||||||
|
phone: phone,
|
||||||
|
wechatId: wechatId,
|
||||||
|
username: name,
|
||||||
|
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,
|
||||||
|
username: name,
|
||||||
|
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 {
|
||||||
|
uni.showToast({
|
||||||
|
title: identifyRes.message || '登录失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
showPhoneAuthModal.value = true
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('模拟登录失败:', error)
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || '登录失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
showPhoneAuthModal.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示用户选择弹窗(切换人员)
|
||||||
|
function showUserSelector() {
|
||||||
|
showPhoneAuthModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
// 生命周期
|
// 生命周期
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 初始化用户信息
|
// 初始化用户信息
|
||||||
|
|||||||
@@ -1149,17 +1149,39 @@ async function submitWorkcase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 撤销工单
|
// 撤销工单
|
||||||
function handleRevoke() {
|
async function handleRevoke() {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '撤销确认',
|
title: '撤销确认',
|
||||||
content: '确认撤销该工单?撤销后无法恢复',
|
content: '确认撤销该工单?撤销后无法恢复',
|
||||||
success: (res) => {
|
success: async (res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
// TODO: 调用 API 撤销工单
|
uni.showLoading({ title: '撤销中...' })
|
||||||
|
try {
|
||||||
|
const result = await workcaseAPI.revokeWorkcase(workcaseId.value)
|
||||||
|
uni.hideLoading()
|
||||||
|
if (result.success) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '工单已撤销',
|
title: '工单已撤销',
|
||||||
icon: 'success'
|
icon: 'success'
|
||||||
})
|
})
|
||||||
|
// 刷新工单详情
|
||||||
|
setTimeout(() => {
|
||||||
|
loadWorkcaseDetail()
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: result.message || '撤销失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
uni.hideLoading()
|
||||||
|
console.error('撤销工单失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || '撤销失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user