diff --git a/backend/src/main/java/com/nursinghome/controller/AdminController.java b/backend/src/main/java/com/nursinghome/controller/AdminController.java index cd404b2..38f6012 100644 --- a/backend/src/main/java/com/nursinghome/controller/AdminController.java +++ b/backend/src/main/java/com/nursinghome/controller/AdminController.java @@ -211,6 +211,26 @@ public class AdminController { return ApiResponse.success(billService.createBill(bill)); } + @PutMapping("/bills") + public ApiResponse updateBill(@RequestBody BillRequest request) { + Bill existing = billMapper.findById(request.getId()); + if (existing == null) { + throw new ApiException("账单不存在"); + } + Bill bill = new Bill(); + bill.setId(request.getId()); + bill.setElderId(request.getElderId()); + bill.setMonth(request.getMonth()); + bill.setBedFee(request.getBedFee()); + bill.setCareFee(request.getCareFee()); + bill.setMealFee(request.getMealFee()); + bill.setOtherFee(request.getOtherFee()); + bill.setTotal(billService.calcTotal(bill)); + bill.setStatus(existing.getStatus()); + billMapper.update(bill); + return ApiResponse.success(); + } + @GetMapping("/bills") public ApiResponse> listBills(@RequestParam(required = false) Long elderId) { if (elderId == null) { @@ -219,6 +239,16 @@ public class AdminController { return ApiResponse.success(billService.listByElderId(elderId)); } + @DeleteMapping("/bills/{id}") + public ApiResponse deleteBill(@PathVariable Long id) { + Bill existing = billMapper.findById(id); + if (existing == null) { + throw new ApiException("账单不存在"); + } + billMapper.delete(id); + return ApiResponse.success(); + } + @GetMapping("/feedback") public ApiResponse> listFeedback() { return ApiResponse.success(feedbackMapper.listAll()); diff --git a/backend/src/main/java/com/nursinghome/controller/FamilyController.java b/backend/src/main/java/com/nursinghome/controller/FamilyController.java index b002415..c76623a 100644 --- a/backend/src/main/java/com/nursinghome/controller/FamilyController.java +++ b/backend/src/main/java/com/nursinghome/controller/FamilyController.java @@ -149,6 +149,12 @@ public class FamilyController { return ApiResponse.success(feedback); } + @GetMapping("/feedback") + public ApiResponse> listFeedback() { + Long familyId = Long.valueOf(StpUtil.getLoginId().toString()); + return ApiResponse.success(feedbackMapper.listByFamilyId(familyId)); + } + @GetMapping("/notices") public ApiResponse> listNotices() { Long familyId = Long.valueOf(StpUtil.getLoginId().toString()); diff --git a/backend/src/main/java/com/nursinghome/dto/BillRequest.java b/backend/src/main/java/com/nursinghome/dto/BillRequest.java index 6e2855e..e12ad15 100644 --- a/backend/src/main/java/com/nursinghome/dto/BillRequest.java +++ b/backend/src/main/java/com/nursinghome/dto/BillRequest.java @@ -3,6 +3,7 @@ package com.nursinghome.dto; import java.math.BigDecimal; public class BillRequest { + private Long id; private Long elderId; private String month; private BigDecimal bedFee; @@ -10,6 +11,14 @@ public class BillRequest { private BigDecimal mealFee; private BigDecimal otherFee; + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public Long getElderId() { return elderId; } diff --git a/backend/src/main/java/com/nursinghome/mapper/BillMapper.java b/backend/src/main/java/com/nursinghome/mapper/BillMapper.java index 7a1f250..ef6321d 100644 --- a/backend/src/main/java/com/nursinghome/mapper/BillMapper.java +++ b/backend/src/main/java/com/nursinghome/mapper/BillMapper.java @@ -25,4 +25,10 @@ public interface BillMapper { @Update("UPDATE bill SET status=#{status}, paid_at=#{paidAt} WHERE id=#{id}") int updateStatus(Bill bill); + + @Update("UPDATE bill SET elder_id=#{elderId}, month=#{month}, bed_fee=#{bedFee}, care_fee=#{careFee}, meal_fee=#{mealFee}, other_fee=#{otherFee}, total=#{total}, status=#{status} WHERE id=#{id}") + int update(Bill bill); + + @Delete("DELETE FROM bill WHERE id=#{id}") + int delete(Long id); } diff --git a/backend/src/main/java/com/nursinghome/mapper/FeedbackMapper.java b/backend/src/main/java/com/nursinghome/mapper/FeedbackMapper.java index bad63e5..9b80d16 100644 --- a/backend/src/main/java/com/nursinghome/mapper/FeedbackMapper.java +++ b/backend/src/main/java/com/nursinghome/mapper/FeedbackMapper.java @@ -14,6 +14,9 @@ public interface FeedbackMapper { @Select("SELECT * FROM feedback ORDER BY created_at DESC") List listAll(); + @Select("SELECT * FROM feedback WHERE family_id = #{familyId} ORDER BY created_at DESC") + List listByFamilyId(Long familyId); + @Update("UPDATE feedback SET status=#{status}, reply=#{reply}, updated_at=NOW() WHERE id=#{id}") int updateStatus(Feedback feedback); } diff --git a/backend/src/main/java/com/nursinghome/service/BillService.java b/backend/src/main/java/com/nursinghome/service/BillService.java index 92890b5..d7ec2dc 100644 --- a/backend/src/main/java/com/nursinghome/service/BillService.java +++ b/backend/src/main/java/com/nursinghome/service/BillService.java @@ -22,12 +22,7 @@ public class BillService { public Bill createBill(Bill bill) { if (bill.getTotal() == null) { - BigDecimal total = BigDecimal.ZERO; - if (bill.getBedFee() != null) total = total.add(bill.getBedFee()); - if (bill.getCareFee() != null) total = total.add(bill.getCareFee()); - if (bill.getMealFee() != null) total = total.add(bill.getMealFee()); - if (bill.getOtherFee() != null) total = total.add(bill.getOtherFee()); - bill.setTotal(total); + bill.setTotal(calcTotal(bill)); } if (bill.getStatus() == null) { bill.setStatus("UNPAID"); @@ -36,6 +31,15 @@ public class BillService { return bill; } + public BigDecimal calcTotal(Bill bill) { + BigDecimal total = BigDecimal.ZERO; + if (bill.getBedFee() != null) total = total.add(bill.getBedFee()); + if (bill.getCareFee() != null) total = total.add(bill.getCareFee()); + if (bill.getMealFee() != null) total = total.add(bill.getMealFee()); + if (bill.getOtherFee() != null) total = total.add(bill.getOtherFee()); + return total; + } + public List listByElderId(Long elderId) { return billMapper.listByElderId(elderId); } diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 058b361..de4e6ea 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -19,7 +19,6 @@ mybatis: sa-token: token-name: satoken timeout: 86400 - activity-timeout: -1 is-concurrent: true is-share: true token-style: uuid diff --git a/frontend/src/api/http.js b/frontend/src/api/http.js index 84888e0..348cfe9 100644 --- a/frontend/src/api/http.js +++ b/frontend/src/api/http.js @@ -16,11 +16,24 @@ http.interceptors.response.use( (response) => { const data = response.data; if (data && data.code !== 0) { - return Promise.reject(new Error(data.message || "request error")); + if (data.message && (data.message.includes("未登录") || data.message.includes("token"))) { + localStorage.removeItem("token"); + localStorage.removeItem("role"); + window.location.href = "/login"; + } + return Promise.reject(new Error(data.message || "请求失败")); } return response; }, - (error) => Promise.reject(error) + (error) => { + if (error && error.response && error.response.status === 401) { + localStorage.removeItem("token"); + localStorage.removeItem("role"); + window.location.href = "/login"; + } + return Promise.reject(error); + } ); export default http; + diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js index a00f2a7..17fd173 100644 --- a/frontend/src/api/index.js +++ b/frontend/src/api/index.js @@ -23,6 +23,8 @@ export const scheduleUpdate = (payload) => http.put("/admin/schedules", payload) export const scheduleDelete = (id) => http.delete(`/admin/schedules/${id}`); export const billsCreate = (payload) => http.post("/admin/bills", payload); +export const billsUpdate = (payload) => http.put("/admin/bills", payload); +export const billsDelete = (id) => http.delete(`/admin/bills/${id}`); export const billsList = (elderId) => http.get("/admin/bills", { params: { elderId } }); export const feedbackList = () => http.get("/admin/feedback"); @@ -47,6 +49,7 @@ export const familyHealthList = (elderId) => http.get("/family/health-records", export const familyBills = (elderId) => http.get("/family/bills", { params: { elderId } }); export const familyPay = (id, payload) => http.post(`/family/bills/${id}/pay`, payload); export const familyFeedback = (payload) => http.post("/family/feedback", payload); +export const familyFeedbackList = () => http.get("/family/feedback"); export const familyNoticeList = () => http.get("/family/notices"); export const uploadFile = (file) => { diff --git a/frontend/src/views/Login.vue b/frontend/src/views/Login.vue index 637af36..7f39447 100644 --- a/frontend/src/views/Login.vue +++ b/frontend/src/views/Login.vue @@ -46,7 +46,7 @@ export default { this.$router.push("/family"); } } catch (e) { - this.$message.error(e.message || "login failed"); + this.$message.error(e.message || "登录失败"); } } } @@ -73,3 +73,4 @@ export default { text-align: center; } + diff --git a/frontend/src/views/Register.vue b/frontend/src/views/Register.vue index aa82865..547dd9d 100644 --- a/frontend/src/views/Register.vue +++ b/frontend/src/views/Register.vue @@ -50,10 +50,10 @@ export default { async handleRegister() { try { await register(this.form); - this.$message.success("registered"); + this.$message.success("注册成功"); this.$router.push("/login"); } catch (e) { - this.$message.error(e.message || "register failed"); + this.$message.error(e.message || "注册失败"); } } } @@ -80,3 +80,5 @@ export default { text-align: center; } + + diff --git a/frontend/src/views/admin/Bills.vue b/frontend/src/views/admin/Bills.vue index 2c3c25d..b354f74 100644 --- a/frontend/src/views/admin/Bills.vue +++ b/frontend/src/views/admin/Bills.vue @@ -8,7 +8,11 @@ - + + + @@ -18,12 +22,24 @@ + + + - - + + + + + + + + @@ -34,25 +50,74 @@ 创建 + + + + + + + + + + + + + + + + + + 取消 + 保存 + + + diff --git a/frontend/src/views/admin/Dashboard.vue b/frontend/src/views/admin/Dashboard.vue index 623f33d..e11a1de 100644 --- a/frontend/src/views/admin/Dashboard.vue +++ b/frontend/src/views/admin/Dashboard.vue @@ -42,8 +42,9 @@ export default { const res = await adminStats(); this.stats = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } } }; + diff --git a/frontend/src/views/admin/Elders.vue b/frontend/src/views/admin/Elders.vue index 91bd521..767a643 100644 --- a/frontend/src/views/admin/Elders.vue +++ b/frontend/src/views/admin/Elders.vue @@ -7,7 +7,11 @@ - + + + @@ -107,12 +111,17 @@ export default { this.load(); }, methods: { + genderLabel(value) { + if (value === "M") return "男"; + if (value === "F") return "女"; + return value || "-"; + }, async load() { try { const res = await eldersList(); this.elders = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } }, async createElder() { @@ -126,7 +135,7 @@ export default { this.showCreate = false; this.load(); } catch (e) { - this.$message.error(e.message || "create failed"); + this.$message.error(e.message || "创建失败"); } }, editElder(row) { @@ -144,7 +153,7 @@ export default { this.showEdit = false; this.load(); } catch (e) { - this.$message.error(e.message || "update failed"); + this.$message.error(e.message || "更新失败"); } }, async deleteElder(row) { @@ -152,7 +161,7 @@ export default { await eldersDelete(row.id); this.load(); } catch (e) { - this.$message.error(e.message || "delete failed"); + this.$message.error(e.message || "删除失败"); } }, syncBirthday(type) { @@ -182,3 +191,4 @@ export default { } }; + diff --git a/frontend/src/views/admin/Feedback.vue b/frontend/src/views/admin/Feedback.vue index b033683..e37a80e 100644 --- a/frontend/src/views/admin/Feedback.vue +++ b/frontend/src/views/admin/Feedback.vue @@ -3,7 +3,11 @@

反馈处理

- + + + + diff --git a/frontend/src/views/admin/Notices.vue b/frontend/src/views/admin/Notices.vue index bee2e00..34eee49 100644 --- a/frontend/src/views/admin/Notices.vue +++ b/frontend/src/views/admin/Notices.vue @@ -70,7 +70,7 @@ export default { const res = await noticeList(); this.items = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } }, async create() { @@ -80,9 +80,10 @@ export default { this.showCreate = false; this.load(); } catch (e) { - this.$message.error(e.message || "create failed"); + this.$message.error(e.message || "创建失败"); } } } }; + diff --git a/frontend/src/views/admin/Users.vue b/frontend/src/views/admin/Users.vue index aa0f790..75d79f1 100644 --- a/frontend/src/views/admin/Users.vue +++ b/frontend/src/views/admin/Users.vue @@ -112,7 +112,7 @@ export default { const res = await adminUsers(this.role || null); this.users = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } }, async createUser() { @@ -121,7 +121,7 @@ export default { this.showCreate = false; this.loadUsers(); } catch (e) { - this.$message.error(e.message || "create failed"); + this.$message.error(e.message || "创建失败"); } }, editUser(row) { @@ -134,17 +134,19 @@ export default { this.showEdit = false; this.loadUsers(); } catch (e) { - this.$message.error(e.message || "update failed"); + this.$message.error(e.message || "更新失败"); } }, async resetPwd(row) { try { await adminResetPassword(row.id, "123456"); - this.$message.success("reset to 123456"); + this.$message.success("已重置为123456"); } catch (e) { - this.$message.error(e.message || "reset failed"); + this.$message.error(e.message || "重置失败"); } } } }; + + diff --git a/frontend/src/views/family/Bills.vue b/frontend/src/views/family/Bills.vue index 59f68e6..e282c2e 100644 --- a/frontend/src/views/family/Bills.vue +++ b/frontend/src/views/family/Bills.vue @@ -39,7 +39,7 @@ export default { const res = await familyElders(); this.elders = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } }, methods: { @@ -59,18 +59,19 @@ export default { const res = await familyBills(this.elderId); this.items = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } }, async pay(row) { try { await familyPay(row.id, { method: "ONLINE" }); - this.$message.success("paid"); + this.$message.success("支付成功"); this.load(); } catch (e) { - this.$message.error(e.message || "pay failed"); + this.$message.error(e.message || "支付失败"); } } } }; + diff --git a/frontend/src/views/family/CareRecords.vue b/frontend/src/views/family/CareRecords.vue index c2a5eea..89ef07a 100644 --- a/frontend/src/views/family/CareRecords.vue +++ b/frontend/src/views/family/CareRecords.vue @@ -26,7 +26,7 @@ export default { const res = await familyElders(); this.elders = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } }, methods: { @@ -36,9 +36,10 @@ export default { const res = await familyCareList(this.elderId); this.items = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } } } }; + diff --git a/frontend/src/views/family/Elders.vue b/frontend/src/views/family/Elders.vue index f6c29e6..a324079 100644 --- a/frontend/src/views/family/Elders.vue +++ b/frontend/src/views/family/Elders.vue @@ -3,7 +3,11 @@

亲人档案

- + + + @@ -22,8 +26,16 @@ export default { const res = await familyElders(); this.elders = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); + } + }, + methods: { + genderLabel(value) { + if (value === "M") return "男"; + if (value === "F") return "女"; + return value || "-"; } } }; + diff --git a/frontend/src/views/family/Feedback.vue b/frontend/src/views/family/Feedback.vue index 251b1e1..f6b4248 100644 --- a/frontend/src/views/family/Feedback.vue +++ b/frontend/src/views/family/Feedback.vue @@ -17,41 +17,104 @@ - - + + 提交 +
+

我的反馈

+ + + + + + + + + + + +
+ + + diff --git a/frontend/src/views/family/HealthRecords.vue b/frontend/src/views/family/HealthRecords.vue index 5613d2a..6c0c892 100644 --- a/frontend/src/views/family/HealthRecords.vue +++ b/frontend/src/views/family/HealthRecords.vue @@ -28,7 +28,7 @@ export default { const res = await familyElders(); this.elders = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } }, methods: { @@ -38,9 +38,10 @@ export default { const res = await familyHealthList(this.elderId); this.items = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } } } }; + diff --git a/frontend/src/views/family/Notices.vue b/frontend/src/views/family/Notices.vue index d95eb8b..c8aa584 100644 --- a/frontend/src/views/family/Notices.vue +++ b/frontend/src/views/family/Notices.vue @@ -21,8 +21,9 @@ export default { const res = await familyNoticeList(); this.items = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } } }; + diff --git a/frontend/src/views/nurse/CareRecords.vue b/frontend/src/views/nurse/CareRecords.vue index 7debcc6..39a9e62 100644 --- a/frontend/src/views/nurse/CareRecords.vue +++ b/frontend/src/views/nurse/CareRecords.vue @@ -46,16 +46,16 @@ export default { const res = await uploadFile(option.file); this.form.attachmentUrl = res.data.data.url; } catch (e) { - this.$message.error(e.message || "upload failed"); + this.$message.error(e.message || "上传失败"); } }, async create() { try { const payload = { ...this.form, recordTime: formatDateTime(this.form.recordTime) }; await nurseCareCreate(payload); - this.$message.success("saved"); + this.$message.success("保存成功"); } catch (e) { - this.$message.error(e.message || "save failed"); + this.$message.error(e.message || "保存失败"); } }, async load() { @@ -64,9 +64,11 @@ export default { const res = await nurseCareList(this.filterElderId); this.items = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } } } }; + + diff --git a/frontend/src/views/nurse/Handovers.vue b/frontend/src/views/nurse/Handovers.vue index d4a1fa2..bb05782 100644 --- a/frontend/src/views/nurse/Handovers.vue +++ b/frontend/src/views/nurse/Handovers.vue @@ -34,19 +34,21 @@ export default { const res = await nurseHandoverList(); this.items = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } }, async create() { try { const payload = { ...this.form, date: formatDate(this.form.date) }; await nurseHandoverCreate(payload); - this.$message.success("saved"); + this.$message.success("保存成功"); this.load(); } catch (e) { - this.$message.error(e.message || "save failed"); + this.$message.error(e.message || "保存失败"); } } } }; + + diff --git a/frontend/src/views/nurse/HealthRecords.vue b/frontend/src/views/nurse/HealthRecords.vue index 0dfceff..937aeeb 100644 --- a/frontend/src/views/nurse/HealthRecords.vue +++ b/frontend/src/views/nurse/HealthRecords.vue @@ -48,9 +48,9 @@ export default { try { const payload = { ...this.form, recordTime: formatDateTime(this.form.recordTime) }; await nurseHealthCreate(payload); - this.$message.success("saved"); + this.$message.success("保存成功"); } catch (e) { - this.$message.error(e.message || "save failed"); + this.$message.error(e.message || "保存失败"); } }, async load() { @@ -59,9 +59,11 @@ export default { const res = await nurseHealthList(this.filterElderId); this.items = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } } } }; + + diff --git a/frontend/src/views/nurse/Notices.vue b/frontend/src/views/nurse/Notices.vue index df4b0d6..458de57 100644 --- a/frontend/src/views/nurse/Notices.vue +++ b/frontend/src/views/nurse/Notices.vue @@ -21,8 +21,9 @@ export default { const res = await nurseNoticeList(); this.items = res.data.data; } catch (e) { - this.$message.error(e.message || "load failed"); + this.$message.error(e.message || "加载失败"); } } }; +