需求改了好多,不需要自己输用户名和qq号了
This commit is contained in:
parent
d2f8d3fad2
commit
c40638eca2
@ -2,6 +2,7 @@ import axios from 'axios';
|
|||||||
import { logoutUser } from '../utils/jwt'; // logoutUser会处理清除存储和重定向
|
import { logoutUser } from '../utils/jwt'; // logoutUser会处理清除存储和重定向
|
||||||
|
|
||||||
const API_BASE_URL = 'https://api.zybdatasupport.online';
|
const API_BASE_URL = 'https://api.zybdatasupport.online';
|
||||||
|
//const API_BASE_URL = 'http://hk.zybdatasupport.online:8000/';
|
||||||
|
|
||||||
const axiosInstance = axios.create({
|
const axiosInstance = axios.create({
|
||||||
baseURL: API_BASE_URL,
|
baseURL: API_BASE_URL,
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
<th>需求创建时间</th>
|
<th>需求创建时间</th>
|
||||||
<th>回复数量</th>
|
<th>回复数量</th>
|
||||||
<th>回复</th>
|
<th>回复</th>
|
||||||
|
<th>状态</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -47,6 +48,11 @@
|
|||||||
<td>
|
<td>
|
||||||
<button class="btn-common btn-gradient btn-reply" @click.stop="showReply(demand)">回复</button>
|
<button class="btn-common btn-gradient btn-reply" @click.stop="showReply(demand)">回复</button>
|
||||||
</td>
|
</td>
|
||||||
|
<td class="status">
|
||||||
|
<span :class="['tag', getStatusClass(demand.status)]">
|
||||||
|
{{ getStatusText(demand.status) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -61,28 +67,28 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form class="add-modal-form" @submit.prevent="submitReply">
|
<form class="add-modal-form" @submit.prevent="submitReply">
|
||||||
<div class="form-row">
|
<!-- <div class="form-row">-->
|
||||||
<span class="label">昵称:</span>
|
<!-- <span class="label">昵称:</span>-->
|
||||||
<input
|
<!-- <input-->
|
||||||
v-model="addForm.author"
|
<!-- v-model="addForm.author"-->
|
||||||
class="input"
|
<!-- class="input"-->
|
||||||
placeholder="请输入您的昵称"
|
<!-- placeholder="请输入您的昵称"-->
|
||||||
required
|
<!-- required-->
|
||||||
/>
|
<!-- />-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="form-row">
|
<!-- <div class="form-row">-->
|
||||||
<span class="label">QQ号:</span>
|
<!-- <span class="label">QQ号:</span>-->
|
||||||
<input
|
<!-- <input-->
|
||||||
v-model="addForm.author_contact"
|
<!-- v-model="addForm.author_contact"-->
|
||||||
class="input"
|
<!-- class="input"-->
|
||||||
placeholder="请输入您的QQ号"
|
<!-- placeholder="请输入您的QQ号"-->
|
||||||
type="text"
|
<!-- type="text"-->
|
||||||
pattern="[0-9]*"
|
<!-- pattern="[0-9]*"-->
|
||||||
inputmode="numeric"
|
<!-- inputmode="numeric"-->
|
||||||
readonly
|
<!-- readonly-->
|
||||||
required
|
<!-- required-->
|
||||||
/>
|
<!-- />-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<span class="label">内容:</span>
|
<span class="label">内容:</span>
|
||||||
<textarea
|
<textarea
|
||||||
@ -143,6 +149,12 @@
|
|||||||
<span class="label">发布时间:</span>
|
<span class="label">发布时间:</span>
|
||||||
<span class="value">{{ formatDate(selectedDemand?.date) }}</span>
|
<span class="value">{{ formatDate(selectedDemand?.date) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="detail-item">
|
||||||
|
<span class="label">状态:</span>
|
||||||
|
<span :class="['tag', getStatusClass(selectedDemand?.status)]">
|
||||||
|
{{ getStatusText(selectedDemand?.status) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div class="reply-section">
|
<div class="reply-section">
|
||||||
<h3>回复内容</h3>
|
<h3>回复内容</h3>
|
||||||
<div class="reply-list">
|
<div class="reply-list">
|
||||||
@ -156,16 +168,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="no-reply">
|
<div v-else class="no-reply">
|
||||||
<div v-if="selectedDemand?.sendcontent">
|
<div v-if="selectedDemand?.sendcontent && replyParsedTexts.length > 0">
|
||||||
<div v-for="(reply, index) in selectedDemand.sendcontent.split('|')" :key="index" class="reply-content">
|
<div v-for="(parsedReply, index) in replyParsedTexts" :key="index" class="reply-content">
|
||||||
<div class="reply-with-avatar">
|
<div class="reply-with-avatar">
|
||||||
<img :src="`https://q1.qlogo.cn/g?b=qq&nk=${extractQQ(reply)}&s=40`" alt="User Avatar" class="reply-avatar" />
|
<img :src="`https://q1.qlogo.cn/g?b=qq&nk=${extractQQ(selectedDemand.sendcontent.split('|')[index])}&s=40`" alt="User Avatar" class="reply-avatar" />
|
||||||
<div class="reply-text">
|
<div class="reply-text">
|
||||||
<b>{{ parseReplyText(reply).user }}</b> {{ parseReplyText(reply).content }}
|
<b>{{ parsedReply.user }}</b>
|
||||||
|
<span class="reply-content-with-newlines">{{ parsedReply.content }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="selectedDemand?.sendcontent && replyParsedTexts.length === 0">
|
||||||
|
加载中...
|
||||||
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
暂无回复
|
暂无回复
|
||||||
</div>
|
</div>
|
||||||
@ -188,22 +204,22 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form class="add-modal-form" @submit.prevent="submitAddForm">
|
<form class="add-modal-form" @submit.prevent="submitAddForm">
|
||||||
<div class="form-row">
|
<!-- <div class="form-row">-->
|
||||||
<span class="label">请求者:</span>
|
<!-- <span class="label">请求者:</span>-->
|
||||||
<input v-model="addForm.requester" class="input" placeholder="可选" />
|
<!-- <input v-model="addForm.requester" class="input" placeholder="可选" />-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="form-row">
|
<!-- <div class="form-row">-->
|
||||||
<span class="label">QQ号:</span>
|
<!-- <span class="label">QQ号:</span>-->
|
||||||
<input
|
<!-- <input -->
|
||||||
v-model="addForm.qq_code"
|
<!-- v-model="addForm.qq_code" -->
|
||||||
class="input"
|
<!-- class="input" -->
|
||||||
placeholder="可选"
|
<!-- placeholder="可选" -->
|
||||||
type="text"
|
<!-- type="text"-->
|
||||||
pattern="[0-9]*"
|
<!-- pattern="[0-9]*"-->
|
||||||
inputmode="numeric"
|
<!-- inputmode="numeric"-->
|
||||||
readonly
|
<!-- readonly-->
|
||||||
/>
|
<!-- />-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<span class="label">需求内容:</span>
|
<span class="label">需求内容:</span>
|
||||||
<textarea
|
<textarea
|
||||||
@ -237,14 +253,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form class="add-modal-form" @submit.prevent="handleEditSubmit">
|
<form class="add-modal-form" @submit.prevent="handleEditSubmit">
|
||||||
<div class="form-row">
|
<!-- <div class="form-row">-->
|
||||||
<span class="label">请求者:</span>
|
<!-- <span class="label">请求者:</span>-->
|
||||||
<input v-model="editForm.requester" class="input" required />
|
<!-- <input v-model="editForm.requester" class="input" required />-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="form-row">
|
<!-- <div class="form-row">-->
|
||||||
<span class="label">QQ号:</span>
|
<!-- <span class="label">QQ号:</span>-->
|
||||||
<input v-model="editForm.qq_code" class="input" required readonly />
|
<!-- <input v-model="editForm.qq_code" class="input" required readonly />-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<span class="label">需求内容:</span>
|
<span class="label">需求内容:</span>
|
||||||
<textarea v-model="editForm.content" class="input" rows="3" required></textarea>
|
<textarea v-model="editForm.content" class="input" rows="3" required></textarea>
|
||||||
@ -262,9 +278,9 @@
|
|||||||
<div v-if="showDeleteConfirm" class="modal-overlay" style="z-index:2000;">
|
<div v-if="showDeleteConfirm" class="modal-overlay" style="z-index:2000;">
|
||||||
<div class="modal-content" style="max-width:350px;text-align:center;">
|
<div class="modal-content" style="max-width:350px;text-align:center;">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h2 style="color:#F56C6C;">隐藏并删除</h2>
|
<h2 style="color:#F56C6C;">删除</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" style="font-size:16px;">确定要隐藏并删除该需求吗?此操作不可恢复。</div>
|
<div class="modal-body" style="font-size:16px;">确定要删除该需求吗?此操作不可恢复。</div>
|
||||||
<div class="delete-dialog-footer" style="display:flex;justify-content:center;gap:18px;margin:18px 0 8px 0;">
|
<div class="delete-dialog-footer" style="display:flex;justify-content:center;gap:18px;margin:18px 0 8px 0;">
|
||||||
<button class="confirm-button" @click="confirmDelete">确认</button>
|
<button class="confirm-button" @click="confirmDelete">确认</button>
|
||||||
<button class="cancel-button" @click="cancelDelete">取消</button>
|
<button class="cancel-button" @click="cancelDelete">取消</button>
|
||||||
@ -279,6 +295,7 @@
|
|||||||
import { ref, onMounted, nextTick, computed } from 'vue'
|
import { ref, onMounted, nextTick, computed } from 'vue'
|
||||||
import { getDemandsList, addDemand, updateDemand, deleteDemand, addDemandReply } from '../../api/demands'
|
import { getDemandsList, addDemand, updateDemand, deleteDemand, addDemandReply } from '../../api/demands'
|
||||||
import { getStoredUser } from '@/utils/jwt'
|
import { getStoredUser } from '@/utils/jwt'
|
||||||
|
import { getUserByInfo } from '../../api/login'
|
||||||
import ErrorDialog from '@/components/ErrorDialog.vue'
|
import ErrorDialog from '@/components/ErrorDialog.vue'
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
@ -289,6 +306,7 @@ const showModal = ref(false)
|
|||||||
const reply = ref(null)
|
const reply = ref(null)
|
||||||
const replyModal = ref(false)
|
const replyModal = ref(false)
|
||||||
const selectedDemand = ref(null)
|
const selectedDemand = ref(null)
|
||||||
|
const replyParsedTexts = ref([])
|
||||||
const showAddModal = ref(false)
|
const showAddModal = ref(false)
|
||||||
const addError = ref('')
|
const addError = ref('')
|
||||||
const addForm = ref({
|
const addForm = ref({
|
||||||
@ -322,9 +340,23 @@ const isNoReward = (reward) => {
|
|||||||
return !reward || reward === '无赏金'
|
return !reward || reward === '无赏金'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 过滤掉已删除的需求(带有&DEL标记)
|
// 过滤需求:过滤掉已删除的需求,管理员隐藏的需求只有创建者可以看到
|
||||||
const filteredDemands = computed(() => {
|
const filteredDemands = computed(() => {
|
||||||
return demands.value.filter(demand => !demand.content?.startsWith('&DEL'))
|
const user = getStoredUser()
|
||||||
|
return demands.value.filter(demand => {
|
||||||
|
// 过滤掉已删除的需求(状态为DEL或带有&DEL标记的旧数据)
|
||||||
|
if (demand.status === 'DEL' || demand.content?.startsWith('&DEL')) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是管理员隐藏的需求,只有创建者自己可以看到
|
||||||
|
if (demand.status === 'HIDE') {
|
||||||
|
return user && demand.qq_code && String(user.qq_code) === String(demand.qq_code)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 正常状态的需求所有人都可以看到
|
||||||
|
return true
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const getReplyCount = (demand) => {
|
const getReplyCount = (demand) => {
|
||||||
@ -339,6 +371,34 @@ const getReplyCount = (demand) => {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取状态样式类
|
||||||
|
const getStatusClass = (status) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'NORMAL':
|
||||||
|
return 'status-normal'
|
||||||
|
case 'DEL':
|
||||||
|
return 'status-deleted'
|
||||||
|
case 'HIDE':
|
||||||
|
return 'status-hidden'
|
||||||
|
default:
|
||||||
|
return 'status-normal'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取状态显示文本
|
||||||
|
const getStatusText = (status) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'NORMAL':
|
||||||
|
return '正常'
|
||||||
|
case 'DEL':
|
||||||
|
return '已删除'
|
||||||
|
case 'HIDE':
|
||||||
|
return '管理员已隐藏'
|
||||||
|
default:
|
||||||
|
return '正常'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 格式化日期
|
// 格式化日期
|
||||||
const formatDate = (dateString) => {
|
const formatDate = (dateString) => {
|
||||||
if (!dateString || dateString === 'Test_date') return '日期未提供'
|
if (!dateString || dateString === 'Test_date') return '日期未提供'
|
||||||
@ -377,25 +437,44 @@ const fetchDemands = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//回复显示弹窗
|
//回复显示弹窗
|
||||||
const showReply = (demand) => {
|
const showReply = async (demand) => {
|
||||||
reply.value = demand
|
reply.value = demand
|
||||||
replyModal.value = true
|
replyModal.value = true
|
||||||
resetReplyForm();
|
await resetReplyForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭回复弹窗
|
// 关闭回复弹窗
|
||||||
const closeReplyModal = () => {
|
const closeReplyModal = async () => {
|
||||||
replyModal.value = false;
|
replyModal.value = false;
|
||||||
resetReplyForm();
|
await resetReplyForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置回复表单
|
// 重置回复表单
|
||||||
const resetReplyForm = () => {
|
const resetReplyForm = async () => {
|
||||||
// 获取用户存储的qq_code
|
// 获取用户存储的qq_code
|
||||||
const user = getStoredUser()
|
const user = getStoredUser()
|
||||||
|
let authorName = ''
|
||||||
|
|
||||||
|
// 如果用户已登录,尝试获取用户昵称
|
||||||
|
if (user && user.qq_code) {
|
||||||
|
try {
|
||||||
|
console.log('回复表单 - 正在获取用户信息,QQ号:', user.qq_code)
|
||||||
|
const userInfo = await getUserByInfo({ qq_code: user.qq_code })
|
||||||
|
console.log('回复表单 - 获取到的用户信息:', userInfo)
|
||||||
|
// authorName = userInfo.name || ''
|
||||||
|
authorName = userInfo.username || '' // 使用username字段而不是name字段
|
||||||
|
console.log('回复表单 - 设置的作者昵称:', authorName)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('回复表单 - 获取用户昵称失败:', error)
|
||||||
|
// 如果获取失败,使用空字符串
|
||||||
|
authorName = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addForm.value = {
|
addForm.value = {
|
||||||
sendcontent: '',
|
sendcontent: '',
|
||||||
author: '',
|
// author: '',
|
||||||
|
author: authorName, // 使用从接口获取的用户昵称
|
||||||
author_contact: user && user.qq_code ? user.qq_code : ''
|
author_contact: user && user.qq_code ? user.qq_code : ''
|
||||||
};
|
};
|
||||||
addError.value = '';
|
addError.value = '';
|
||||||
@ -406,9 +485,19 @@ const resetReplyForm = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 显示详情弹窗
|
// 显示详情弹窗
|
||||||
const showDetail = (demand) => {
|
const showDetail = async (demand) => {
|
||||||
selectedDemand.value = demand
|
selectedDemand.value = demand
|
||||||
showModal.value = true
|
showModal.value = true
|
||||||
|
|
||||||
|
// 如果有sendcontent,解析所有回复文本
|
||||||
|
if (demand.sendcontent) {
|
||||||
|
replyParsedTexts.value = []
|
||||||
|
const replies = demand.sendcontent.split('|')
|
||||||
|
for (let i = 0; i < replies.length; i++) {
|
||||||
|
const parsed = await parseReplyText(replies[i])
|
||||||
|
replyParsedTexts.value[i] = parsed
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
@ -418,11 +507,30 @@ const closeModal = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
const openAddModal = () => {
|
const openAddModal = async () => {
|
||||||
// 重置表单数据
|
// 重置表单数据
|
||||||
const user = getStoredUser()
|
const user = getStoredUser()
|
||||||
|
let requesterName = ''
|
||||||
|
|
||||||
|
// 如果用户已登录,尝试获取用户昵称
|
||||||
|
if (user && user.qq_code) {
|
||||||
|
try {
|
||||||
|
console.log('正在获取用户信息,QQ号:', user.qq_code)
|
||||||
|
const userInfo = await getUserByInfo({ qq_code: user.qq_code })
|
||||||
|
console.log('获取到的用户信息:', userInfo)
|
||||||
|
// requesterName = userInfo.name || ''
|
||||||
|
requesterName = userInfo.username || '' // 使用username字段而不是name字段
|
||||||
|
console.log('设置的请求者昵称:', requesterName)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('获取用户昵称失败:', error)
|
||||||
|
// 如果获取失败,使用空字符串
|
||||||
|
requesterName = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addForm.value = {
|
addForm.value = {
|
||||||
requester: '',
|
// requester: '',
|
||||||
|
requester: requesterName, // 使用从接口获取的用户昵称
|
||||||
content: '',
|
content: '',
|
||||||
reward: '',
|
reward: '',
|
||||||
qq_code: user && user.qq_code ? user.qq_code : '',
|
qq_code: user && user.qq_code ? user.qq_code : '',
|
||||||
@ -440,11 +548,11 @@ function closeAddModal() {
|
|||||||
addError.value = ''
|
addError.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在 script setup 部分添加验证函数
|
// // 在 script setup 部分添加验证函数
|
||||||
const validateQQ = (event) => {
|
// const validateQQ = (event) => {
|
||||||
// 只保留数字
|
// // 只保留数字
|
||||||
addForm.value.qq_code = event.target.value.replace(/[^\d]/g, '');
|
// addForm.value.qq_code = event.target.value.replace(/[^\d]/g, '');
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 修改 submitAddForm 函数,添加 QQ 号验证
|
// 修改 submitAddForm 函数,添加 QQ 号验证
|
||||||
async function submitAddForm() {
|
async function submitAddForm() {
|
||||||
@ -504,13 +612,13 @@ const submitReply = async () => {
|
|||||||
addError.value = '';
|
addError.value = '';
|
||||||
try {
|
try {
|
||||||
const replyData = {
|
const replyData = {
|
||||||
reply: addForm.value.sendcontent
|
reply: addForm.value.sendcontent.replace(/\n/g, ' ').replace(/\r/g, ' ')
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('提交的回复数据:', replyData);
|
console.log('提交的回复数据:', replyData);
|
||||||
await addDemandReply(reply.value.id, replyData);
|
await addDemandReply(reply.value.id, replyData);
|
||||||
replyModal.value = false;
|
replyModal.value = false;
|
||||||
resetReplyForm();
|
await resetReplyForm();
|
||||||
fetchDemands(); // 刷新列表
|
fetchDemands(); // 刷新列表
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('提交回复失败:', e);
|
console.error('提交回复失败:', e);
|
||||||
@ -536,40 +644,83 @@ function autoResize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function extractQQ(str) {
|
function extractQQ(str) {
|
||||||
// 首先尝试解析 qq:内容 格式
|
// 首先尝试解析新格式:qq:内容 格式
|
||||||
const qqMatch = str.match(/^(\d+):(.+)$/)
|
const newFormatMatch = str.match(/^(\d+):(.*)$/)
|
||||||
if (qqMatch) {
|
if (newFormatMatch) {
|
||||||
return qqMatch[1]
|
return newFormatMatch[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 兼容原有的昵称(QQ号)格式
|
// 兼容旧格式:昵称(QQ号):内容 格式
|
||||||
const match = str.match(/[((]([1-9][0-9]{4,})[))]/)
|
const oldFormatMatch = str.match(/^(.+?)\((\d+)\):(.*)$/)
|
||||||
return match ? match[1] : ''
|
if (oldFormatMatch) {
|
||||||
|
return oldFormatMatch[2] // QQ号部分
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更宽松的旧格式匹配
|
||||||
|
const flexibleOldMatch = str.match(/[((](\d+)[))]/);
|
||||||
|
return flexibleOldMatch ? flexibleOldMatch[1] : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseReplyText(str) {
|
// 用于缓存用户名查询结果
|
||||||
// 首先尝试解析 qq:内容 格式
|
const usernameCache = ref({})
|
||||||
const qqMatch = str.match(/^(\d+):(.+)$/)
|
|
||||||
if (qqMatch) {
|
async function parseReplyText(str) {
|
||||||
|
// 首先尝试解析新格式:qq:内容 格式
|
||||||
|
const newFormatMatch = str.match(/^(\d+):(.*)$/)
|
||||||
|
if (newFormatMatch) {
|
||||||
|
const qqNumber = newFormatMatch[1]
|
||||||
|
let username = qqNumber // 默认显示QQ号
|
||||||
|
|
||||||
|
// 尝试从缓存获取用户名
|
||||||
|
if (usernameCache.value[qqNumber]) {
|
||||||
|
username = usernameCache.value[qqNumber]
|
||||||
|
} else {
|
||||||
|
// 通过API查询用户名
|
||||||
|
try {
|
||||||
|
const userInfo = await getUserByInfo({ qq_code: qqNumber })
|
||||||
|
if (userInfo && userInfo.username) {
|
||||||
|
username = `${userInfo.username}(${qqNumber})`
|
||||||
|
usernameCache.value[qqNumber] = username
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('获取用户信息失败:', error)
|
||||||
|
// 失败时使用QQ号作为显示名
|
||||||
|
username = qqNumber
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user: qqMatch[1],
|
user: username,
|
||||||
content: qqMatch[2].trim()
|
content: newFormatMatch[2].trim().replace(/\\n/g, '\n').replace(/\\r/g, '').replace(/\\t/g, ' ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 兼容原有的昵称(QQ号)格式,允许有空格
|
// 兼容旧格式:昵称(QQ号):内容 格式
|
||||||
const match = str.match(/^(.+?[((][1-9][0-9]{4,}[))])(.*)$/)
|
const oldFormatMatch = str.match(/^(.+?)\((\d+)\):(.*)$/)
|
||||||
if (match) {
|
if (oldFormatMatch) {
|
||||||
// match[1] 是昵称(QQ号),match[2] 是剩余内容(可能有"回复 xxx "等)
|
const nickname = oldFormatMatch[1].trim()
|
||||||
|
const qqNumber = oldFormatMatch[2]
|
||||||
return {
|
return {
|
||||||
user: match[1].trim(),
|
user: `${nickname}(${qqNumber})`, // 保持旧格式的显示样式
|
||||||
content: match[2].replace(/^:|^:/, '').trim()
|
content: oldFormatMatch[3].trim().replace(/\\n/g, ' ').replace(/\\r/g, '').replace(/\\t/g, ' ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fallback
|
|
||||||
|
// 更宽松的旧格式匹配:处理可能的变体
|
||||||
|
const flexibleOldMatch = str.match(/^(.+?)[((](\d+)[))][::](.*)$/)
|
||||||
|
if (flexibleOldMatch) {
|
||||||
|
const nickname = flexibleOldMatch[1].trim()
|
||||||
|
const qqNumber = flexibleOldMatch[2]
|
||||||
|
return {
|
||||||
|
user: `${nickname}(${qqNumber})`,
|
||||||
|
content: flexibleOldMatch[3].trim().replace(/\\n/g, ' ').replace(/\\r/g, '').replace(/\\t/g, ' ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback:如果都不匹配,返回原始内容
|
||||||
return {
|
return {
|
||||||
user: '',
|
user: '',
|
||||||
content: str
|
content: str.replace(/\\n/g, ' ').replace(/\\r/g, '').replace(/\\t/g, ' ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,15 +774,15 @@ function handleDeleteDemand() {
|
|||||||
|
|
||||||
async function confirmDelete() {
|
async function confirmDelete() {
|
||||||
try {
|
try {
|
||||||
// 使用updateDemand API,在content前面添加&DEL标记
|
// 修改状态为DEL,保持原content内容不变
|
||||||
const updatedContent = `&DEL${selectedDemand.value.content}`
|
|
||||||
await updateDemand(pendingDeleteId.value, {
|
await updateDemand(pendingDeleteId.value, {
|
||||||
requester: selectedDemand.value.requester,
|
requester: selectedDemand.value.requester,
|
||||||
qq_code: selectedDemand.value.qq_code,
|
qq_code: selectedDemand.value.qq_code,
|
||||||
content: updatedContent,
|
content: selectedDemand.value.content,
|
||||||
reward: selectedDemand.value.reward,
|
reward: selectedDemand.value.reward,
|
||||||
date: selectedDemand.value.date,
|
date: selectedDemand.value.date,
|
||||||
sendcontent: selectedDemand.value.sendcontent
|
sendcontent: selectedDemand.value.sendcontent,
|
||||||
|
status: 'DEL'
|
||||||
})
|
})
|
||||||
fetchDemands()
|
fetchDemands()
|
||||||
closeModal()
|
closeModal()
|
||||||
@ -742,8 +893,27 @@ const onRefresh = () => {
|
|||||||
border: 1px solid #b6d2ff;
|
border: 1px solid #b6d2ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status-normal {
|
||||||
|
background: #f0f9ff;
|
||||||
|
color: #0369a1;
|
||||||
|
border: 1px solid #7dd3fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-deleted {
|
||||||
|
background: #fef2f2;
|
||||||
|
color: #dc2626;
|
||||||
|
border: 1px solid #fca5a5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-hidden {
|
||||||
|
background: #fefce8;
|
||||||
|
color: #a16207;
|
||||||
|
border: 1px solid #fcd34d;
|
||||||
|
}
|
||||||
|
|
||||||
.maps-table td.reward,
|
.maps-table td.reward,
|
||||||
.maps-table td.reply-count,
|
.maps-table td.reply-count,
|
||||||
|
.maps-table td.status,
|
||||||
.maps-table tr {
|
.maps-table tr {
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
filter: none !important;
|
filter: none !important;
|
||||||
@ -1039,6 +1209,11 @@ const onRefresh = () => {
|
|||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reply-content-with-newlines {
|
||||||
|
white-space: pre-wrap; /* 保留换行符和空白字符 */
|
||||||
|
word-wrap: break-word; /* 长单词自动换行 */
|
||||||
|
}
|
||||||
|
|
||||||
.warning-tip {
|
.warning-tip {
|
||||||
background: linear-gradient(90deg, #ffeaea 0%, #ffd6d6 100%);
|
background: linear-gradient(90deg, #ffeaea 0%, #ffd6d6 100%);
|
||||||
color: #d32f2f;
|
color: #d32f2f;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user