diff --git a/track-uniapp/src/api/feedback.js b/track-uniapp/src/api/feedback.js new file mode 100644 index 0000000..c58aa15 --- /dev/null +++ b/track-uniapp/src/api/feedback.js @@ -0,0 +1,37 @@ +/** + * 帮助与反馈 API。 + * + * ⚠️ 后端目前【没有】feedback 接口(已核对 openapi 路由表)。这里不直接写死 + * 一个假函数,而是「先真后假」:先按最终契约 POST /feedback/,只有拿到 + * 404(端点尚未实现)才回退到本地 mock 成功。这样等后端补上接口后,前端 + * 一行都不用改就能自动接上真实链路;而 400/422/断网等真实错误仍会照常 + * 抛出,不会被 mock 悄悄吞掉 —— 否则工人会以为反馈提交成功了,其实没有。 + */ +import request from "../utils/request"; + +/** 反馈问题类型(与页面选择项一一对应) */ +export const FEEDBACK_TYPES = [ + { value: "system", label: "系统问题" }, + { value: "device", label: "设备故障" }, + { value: "other", label: "其他" }, +]; + +/** + * 提交一条反馈。 + * @param {{type: string, content: string, images?: string[], user_id?: string}} payload + * @returns {Promise<{id?: string, mocked?: boolean}>} + */ +export async function submitFeedback(payload) { + try { + // silent:404 会走到下面的 mock 分支,不能先弹一句「请求失败 (404)」再弹「感谢反馈」 + return await request({ url: "/feedback/", method: "POST", data: payload, silent: true }); + } catch (e) { + // 只认「端点不存在」这一种情况回退 mock;其余错误(校验失败/网络断) + // 必须原样抛给页面去提示,不能让用户误以为提交成功 + if (e && e.statusCode === 404) { + console.warn("[feedback] 后端暂无 /feedback/ 接口,回退本地 mock"); + return { id: null, mocked: true }; + } + throw e; + } +} diff --git a/track-uniapp/src/api/stats.js b/track-uniapp/src/api/stats.js new file mode 100644 index 0000000..a68381a --- /dev/null +++ b/track-uniapp/src/api/stats.js @@ -0,0 +1,27 @@ +/** + * 个人效能统计 API — 「个人中心 → 工作统计」数据源。 + * + * 后端 /dashboard/* 系列是「上帝视角」(全厂数据、不按人过滤),且 + * people-history 只返回 WIP/PENDING/COMPLETED、rejected-tasks 压根没有 + * assignee_id 参数 —— 一线工人要看的「我的今日被驳回数」在这两个接口里 + * 都拿不到。故后端补了一个薄桥接端点 /dashboard/my-stats,沿用同一套统计 + * 口径,但强制按 assignee_id 过滤到本人。 + */ +import { get } from "../utils/request"; + +/** + * 获取当前登录用户的个人效能统计(支持自选时段)。 + * + * 返回两组指标: + * 生产战绩 — tasks_completed / tasks_rejected / products_touched + * 操作统计 — receive_count / transfer_count / record_count / op_total + * (与 PC「人员操作统计」严格同口径,已逐字段交叉验证) + * + * @param {string} assigneeId - 负责人ID(即登录用户的 username) + * @param {string} [since] - 起始时间 ISO,**必须带时区偏移**(如 2026-09-01T00:00:00+08:00) + * @param {string} [until] - 截止时间 ISO,同上 + * @returns {Promise} + */ +export function getMyStats(assigneeId, since, until) { + return get("/dashboard/my-stats", { assignee_id: assigneeId, since, until }); +} diff --git a/track-uniapp/src/pages.json b/track-uniapp/src/pages.json index 2a5198b..c42b0f1 100644 --- a/track-uniapp/src/pages.json +++ b/track-uniapp/src/pages.json @@ -36,7 +36,8 @@ "style": { "navigationBarTitleText": "我的任务", "navigationBarBackgroundColor": "#2563EB", - "navigationBarTextStyle": "white" + "navigationBarTextStyle": "white", + "enablePullDownRefresh": true } }, { @@ -44,7 +45,8 @@ "style": { "navigationBarTitleText": "消息通知", "navigationBarBackgroundColor": "#2563EB", - "navigationBarTextStyle": "white" + "navigationBarTextStyle": "white", + "enablePullDownRefresh": true } }, { @@ -54,6 +56,31 @@ "navigationBarBackgroundColor": "#2563EB", "navigationBarTextStyle": "white" } + }, + { + "path": "pages/profile/statistics", + "style": { + "navigationBarTitleText": "工作统计", + "navigationBarBackgroundColor": "#2563EB", + "navigationBarTextStyle": "white", + "enablePullDownRefresh": true + } + }, + { + "path": "pages/profile/settings", + "style": { + "navigationBarTitleText": "设置", + "navigationBarBackgroundColor": "#2563EB", + "navigationBarTextStyle": "white" + } + }, + { + "path": "pages/profile/feedback", + "style": { + "navigationBarTitleText": "帮助与反馈", + "navigationBarBackgroundColor": "#2563EB", + "navigationBarTextStyle": "white" + } } ], "globalStyle": { diff --git a/track-uniapp/src/pages/profile/feedback.vue b/track-uniapp/src/pages/profile/feedback.vue new file mode 100644 index 0000000..637d0a4 --- /dev/null +++ b/track-uniapp/src/pages/profile/feedback.vue @@ -0,0 +1,233 @@ +