From 2ce2c1a31f2cd0fd035fd7d975a454523483dedd Mon Sep 17 00:00:00 2001 From: wlkjyy Date: Wed, 7 Jan 2026 17:21:01 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E5=B7=A5=E5=8D=95=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E4=BC=98=E5=8C=96=20-=20=E4=BF=AE=E5=A4=8D=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E8=B7=B3=E8=BD=AC=E9=97=AE=E9=A2=98=E5=B9=B6=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E7=94=A8=E6=88=B7=E7=AD=9B=E9=80=89=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复工单详情页定时刷新导致的自动跳转问题 - 添加用户搜索选择器,支持按用户筛选工单 - 优化用户搜索体验,使用对话框模式 - 修正API响应数据结构解析 --- src/api/ticket.js | 3 +- src/views/ticket/TicketDetail.vue | 3 +- src/views/ticket/TicketList.vue | 280 +++++++++++++++++++++++++++--- 3 files changed, 262 insertions(+), 24 deletions(-) diff --git a/src/api/ticket.js b/src/api/ticket.js index 7ea0668..5f2c459 100644 --- a/src/api/ticket.js +++ b/src/api/ticket.js @@ -5,11 +5,12 @@ import request from "@/utils/request.js"; * @returns {Promise} */ -export function getTickerList(count, page, status, orderBy, order) { +export function getTickerList(count, page, status, orderBy, order, userId) { const params = { count, page } if (status !== undefined && status !== '') params.status = status if (orderBy) params.orderBy = orderBy if (order) params.order = order + if (userId) params.user_id = userId console.log('工单列表请求参数:', params) // 调试日志 return request.get('/api/v1/admin/work_order/list', params) } diff --git a/src/views/ticket/TicketDetail.vue b/src/views/ticket/TicketDetail.vue index ce79c8c..a1e2b86 100644 --- a/src/views/ticket/TicketDetail.vue +++ b/src/views/ticket/TicketDetail.vue @@ -892,7 +892,8 @@ const goToUserDetail = () => { // 定时刷新 const startAutoRefresh = () => { refreshTimer.value = setInterval(() => { - if (ticketInfo.value?.status !== 'completed') { + // 只有当前路由仍在工单详情页且工单未完成时才刷新 + if (route.path === '/ticket/detail' && route.query.id && ticketInfo.value?.status !== 'completed') { fetchTicketDetail(false) // 定时刷新时不显示 loading } }, 10000) diff --git a/src/views/ticket/TicketList.vue b/src/views/ticket/TicketList.vue index 64fd0d9..bcb3956 100644 --- a/src/views/ticket/TicketList.vue +++ b/src/views/ticket/TicketList.vue @@ -31,14 +31,21 @@ + + :model-value="selectedUser ? selectedUser.user_name : ''" + placeholder="点击选择用户筛选" + readonly + style="width: 180px; cursor: pointer" + @click="showUserDialog = true" + > + + + 刷新 @@ -99,18 +106,74 @@ @current-change="handlePageChange" /> + + + +
+ + + + +
+ +
+ 搜索关键词: {{ userSearchKeyword }} | 用户数量: {{ userList.length }} +
+ +
+ 请输入关键词搜索用户 +
+
+ 未找到匹配的用户 +
+
+
+ {{ user.user_name?.charAt(0) }} +
+
{{ user.user_name }}
+
+ 手机: {{ user.phone }} + 邮箱: {{ user.email }} + UID: {{ user.user_id }} +
+
+ +
+
+
+
+
@@ -365,6 +539,68 @@ onActivated(() => { gap: 8px; } +.user-dialog-content { + display: flex; + flex-direction: column; + gap: 16px; +} + +.user-list-container { + min-height: 300px; + max-height: 400px; + overflow-y: auto; + border: 1px solid #dcdfe6; + border-radius: 4px; +} + +.empty-hint { + display: flex; + align-items: center; + justify-content: center; + height: 300px; + color: #909399; + font-size: 14px; +} + +.user-list { + padding: 8px 0; +} + +.user-list-item { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 16px; + cursor: pointer; + transition: background 0.2s; +} + +.user-list-item:hover { + background: #f5f7fa; +} + +.user-list-info { + flex: 1; + min-width: 0; +} + +.user-list-name { + font-size: 14px; + font-weight: 500; + color: #303133; + margin-bottom: 4px; +} + +.user-list-sub { + font-size: 12px; + color: #909399; +} + +.user-list-arrow { + color: #c0c4cc; + font-size: 16px; +} + .user-info { display: flex; align-items: center; From fe1a1181320fd40427d2f7b273a74e7dfc192b3b Mon Sep 17 00:00:00 2001 From: wlkjyy Date: Wed, 7 Jan 2026 17:27:54 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E5=B7=A5=E5=8D=95=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=B7=BB=E5=8A=A0=E5=85=B3=E9=94=AE=E8=AF=8D=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加关键词搜索输入框,支持搜索工单标题/内容 - 300ms 防抖优化搜索性能 - 支持与用户筛选同时使用 --- src/api/ticket.js | 3 ++- src/views/ticket/TicketList.vue | 34 ++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/api/ticket.js b/src/api/ticket.js index 5f2c459..87d4701 100644 --- a/src/api/ticket.js +++ b/src/api/ticket.js @@ -5,12 +5,13 @@ import request from "@/utils/request.js"; * @returns {Promise} */ -export function getTickerList(count, page, status, orderBy, order, userId) { +export function getTickerList(count, page, status, orderBy, order, userId, keyword) { const params = { count, page } if (status !== undefined && status !== '') params.status = status if (orderBy) params.orderBy = orderBy if (order) params.order = order if (userId) params.user_id = userId + if (keyword) params.keyword = keyword console.log('工单列表请求参数:', params) // 调试日志 return request.get('/api/v1/admin/work_order/list', params) } diff --git a/src/views/ticket/TicketList.vue b/src/views/ticket/TicketList.vue index bcb3956..d918b57 100644 --- a/src/views/ticket/TicketList.vue +++ b/src/views/ticket/TicketList.vue @@ -46,6 +46,19 @@ + + + + 刷新 @@ -187,6 +200,10 @@ const isLoading = ref(false) const ticketList = ref([]) const activeStatus = ref('pending') // 默认选中"待处理" +// 关键词搜索 +const searchKeyword = ref('') +const keywordSearchTimer = ref(null) + // 用户搜索 const userSearchKeyword = ref('') const userList = ref([]) @@ -248,7 +265,8 @@ const fetchTicketList = async () => { statusParam, sortBy.value, sortOrder.value, - selectedUser.value?.user_id + selectedUser.value?.user_id, + searchKeyword.value.trim() ) if (res.code === 200) { @@ -348,6 +366,17 @@ const clearUserFilter = () => { fetchTicketList() } +// 关键词搜索 +const handleKeywordSearch = () => { + if (keywordSearchTimer.value) { + clearTimeout(keywordSearchTimer.value) + } + keywordSearchTimer.value = setTimeout(() => { + currentPage.value = 1 + fetchTicketList() + }, 300) +} + // 按状态过滤 const filterByStatus = (status) => { if (activeStatus.value === status) return @@ -479,6 +508,9 @@ onBeforeUnmount(() => { if (userSearchTimer.value) { clearTimeout(userSearchTimer.value) } + if (keywordSearchTimer.value) { + clearTimeout(keywordSearchTimer.value) + } })