diff --git a/src/api/demands.js b/src/api/demands.js new file mode 100644 index 0000000..5d4fcca --- /dev/null +++ b/src/api/demands.js @@ -0,0 +1,136 @@ +import axios from 'axios'; + +const API_BASE_URL = 'http://zybdatasupport.online:8000'; // 与 tournament.js 一致 + +// 创建 axios 实例,可以复用 tournament.js 中的拦截器逻辑,或者单独设置 +const axiosInstance = axios.create({ + baseURL: API_BASE_URL, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest' + }, + timeout: 10000 +}); + +// 请求拦截器 (添加token) +axiosInstance.interceptors.request.use( + config => { + const token = localStorage.getItem('access_token'); + if (token) { + config.headers.Authorization = `bearer ${token}`; + } + return config; + }, + error => { + return Promise.reject(error); + } +); + +// 响应拦截器 (基本错误处理) +axiosInstance.interceptors.response.use( + response => response, + error => { + if (error.response) { + console.error('API请求错误 (demands.js):', { + status: error.response.status, + data: error.response.data, + config: error.config + }); + } else if (error.request) { + console.error('网络错误 (demands.js):', error.request); + } else { + console.error('请求配置错误 (demands.js):', error.message); + } + return Promise.reject(error); + } +); + +/** + * 获取需求列表 + * @returns {Promise>} 返回需求列表数据 + */ +export const getDemandsList = async () => { + try { + const response = await axiosInstance.get('/demands/getlist'); + return response.data; // 假设直接返回数组 + } catch (error) { + console.error('获取需求列表失败:', error); + throw error; + } +}; + +/** + * 添加需求 (注意:管理员后台可能不常用此功能) + * @param {Object} demandData - 需求数据 + * @param {string} [demandData.requester] - 请求者 + * @param {string} [demandData.qq_code] - QQ号 + * @param {string} demandData.sendcontent - 请求内容 (对应后端的 sendcontent 和 content) + * @param {string} [demandData.reward] - 悬赏金额 + * @param {string} demandData.date - 日期 (后端API会自动生成,但模型中包含此字段,前端添加时也提交此字段,如YYYY-MM-DD HH:MM:SS) + * @returns {Promise} 返回添加需求的响应数据 + */ +export const addDemand = async (demandData) => { + try { + const payload = { + ...demandData, + content: demandData.sendcontent // 确保 content 与 sendcontent 一致 + }; + const response = await axiosInstance.post('/demands/add', payload); + return response.data; + } catch (error) { + console.error('添加需求失败:', error); + throw error; + } +}; + +/** + * 更新需求 + * @param {number} id - 需求ID + * @param {Object} dataToUpdate - 需要更新的数据 + * @param {string} dataToUpdate.sendcontent - 新的请求内容 + * // 如果后端允许更新其他字段,在此处添加 + * @returns {Promise} 返回更新需求的响应数据 + */ +export const updateDemand = async (id, dataToUpdate) => { + try { + // 根据后端PUT /demands/update/{id} 的定义,它期望整个DemandModel作为item + // 但只更新了 sendcontent。为安全起见,先获取原始数据,再更新。 + // 或者,如果API设计为只接受要修改的字段,则直接发送 { sendcontent: dataToUpdate.sendcontent } + // 这里假设API会处理部分更新,或者前端会发送完整的模型(即使只改一个字段) + // 为简单起见,我们先假设API能接受只包含sendcontent的更新,或者前端需要先获取完整模型再提交 + // 参照后端 item: DemandModel, 它会接收一个完整的模型,但仅使用了 item.sendcontent + // 因此,我们需要传递一个至少包含 sendcontent 的对象,但为了模型验证,最好是完整的模型结构 + const payload = { + sendcontent: dataToUpdate.sendcontent, + // 根据 DemandModel,补齐其他必填或可选字段,即使它们不被后端 update 逻辑使用 + // 这部分需要参照 DemandModel 的具体定义来决定哪些字段是必要的 + // 以下为推测,需要根据实际 DemandModel 调整 + requester: dataToUpdate.requester || '', + qq_code: dataToUpdate.qq_code || '', + content: dataToUpdate.sendcontent, // 保持一致 + reward: dataToUpdate.reward || '', + date: dataToUpdate.date || new Date().toISOString().slice(0, 19).replace('T', ' ') // 确保有日期 + }; + const response = await axiosInstance.put(`/demands/update/${id}`, payload); + return response.data; + } catch (error) { + console.error('更新需求失败:', error); + throw error; + } +}; + +/** + * 删除需求 + * @param {number} id - 需求ID + * @returns {Promise} 返回删除需求的响应数据 + */ +export const deleteDemand = async (id) => { + try { + const response = await axiosInstance.delete(`/demands/delete/${id}`); + return response.data; + } catch (error) { + console.error('删除需求失败:', error); + throw error; + } +}; \ No newline at end of file diff --git a/src/components/backend/PlayerForm.vue b/src/components/backend/PlayerForm.vue new file mode 100644 index 0000000..6d52c80 --- /dev/null +++ b/src/components/backend/PlayerForm.vue @@ -0,0 +1,260 @@ + + + + + \ No newline at end of file diff --git a/src/components/backend/PlayerList.vue b/src/components/backend/PlayerList.vue new file mode 100644 index 0000000..1cd6562 --- /dev/null +++ b/src/components/backend/PlayerList.vue @@ -0,0 +1,328 @@ + + + + + \ No newline at end of file diff --git a/src/components/backend/ServiceHallView.vue b/src/components/backend/ServiceHallView.vue new file mode 100644 index 0000000..f30bf1c --- /dev/null +++ b/src/components/backend/ServiceHallView.vue @@ -0,0 +1,526 @@ + + + + + \ No newline at end of file diff --git a/src/components/backend/TournamentForm.vue b/src/components/backend/TournamentForm.vue new file mode 100644 index 0000000..c261760 --- /dev/null +++ b/src/components/backend/TournamentForm.vue @@ -0,0 +1,210 @@ + + + + + \ No newline at end of file diff --git a/src/components/backend/TournamentList.vue b/src/components/backend/TournamentList.vue new file mode 100644 index 0000000..a541c56 --- /dev/null +++ b/src/components/backend/TournamentList.vue @@ -0,0 +1,294 @@ + + + + + \ No newline at end of file diff --git a/src/components/login_module.vue b/src/components/login_module.vue index 6e52612..0b1b108 100644 --- a/src/components/login_module.vue +++ b/src/components/login_module.vue @@ -191,7 +191,11 @@ const handleLogin = async () => { // 登录成功,跳转到首页 if (response.access_token) { + // 存储 token 和用户ID (QQ号) + localStorage.setItem('access_token', response.access_token) + localStorage.setItem('user_id', username.value) // username.value 是用户输入的QQ号 router.push('/') + } else { throw new Error('登录失败:未获取到访问令牌') } diff --git a/src/views/backend/Dashboard.vue b/src/views/backend/Dashboard.vue index 08e0189..598ad7d 100644 --- a/src/views/backend/Dashboard.vue +++ b/src/views/backend/Dashboard.vue @@ -1,15 +1,71 @@ \ No newline at end of file