Forráskód Böngészése

问题上报及纠错反馈

zuypeng 1 éve
szülő
commit
52b2debe98

+ 31 - 1
admin-web/src/router/route.ts

@@ -138,7 +138,7 @@ export const adminRoutes: Array<RouteRecordRaw> = [
                         name: 'adminStationList',
                         component: () => import('/@/views/admin/station/list/index.vue'),
                         meta: {
-                            title: '站监控',
+                            title: '站监控',
                             isLink: '',
                             isHide: false,
                             isKeepAlive: true,
@@ -425,6 +425,36 @@ export const adminRoutes: Array<RouteRecordRaw> = [
                             icon: 'ele-Collection',
                         },
                     },
+                    {
+                        path: '/org/faq',
+                        name: 'adminFaq',
+                        component: () => import('/@/views/admin/faq/index.vue'),
+                        meta: {
+                            title: '常见问题',
+                            isLink: '',
+                            isHide: false,
+                            isKeepAlive: true,
+                            isAffix: false,
+                            isIframe: false,
+                            icon: 'ele-Tickets',
+                            perm:"",
+                        },
+                    },
+                    {
+                        path: '/org/feedback',
+                        name: 'adminFeedback',
+                        component: () => import('/@/views/admin/feedback/index.vue'),
+                        meta: {
+                            title: '反馈上报',
+                            isLink: '',
+                            isHide: false,
+                            isKeepAlive: true,
+                            isAffix: false,
+                            isIframe: false,
+                            icon: 'ele-Tickets',
+                            perm:"",
+                        },
+                    },
                 ]
             },
    /*         {

+ 258 - 0
admin-web/src/views/admin/faq/index.vue

@@ -0,0 +1,258 @@
+<style scoped lang="scss">
+.system-container {
+
+  :deep(.el-card__body) {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    flex: 1;
+    overflow: auto;
+
+    .el-table {
+      flex: 1;
+    }
+
+  }
+}
+
+.page-content {
+  margin-bottom: 20px;
+}
+
+.page-pager {
+  background-color: #fff;
+  height: 24px;
+}
+</style>
+<template>
+  <div class="system-container layout-padding">
+    <el-card shadow="hover" class="layout-padding-auto">
+
+
+      <el-form
+          :model="state.formQuery"
+          ref="queryRef"
+          size="default" label-width="0px" class="mt5 mb5">
+        <el-input
+            v-model="state.formQuery.mobilePhone"
+            placeholder="用户手机号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+        <el-input
+            v-model="state.formQuery.outTradeNo"
+            placeholder="商户订单号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+        <el-input
+            v-model="state.formQuery.transactionId"
+            placeholder="微信订单号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+        <!--        <el-input
+                    v-model="state.formQuery.tradeType"
+                    placeholder="交易类型,枚举值:JSAPI:公众号支付 NATIVE:扫码支付 APP:APP支付 MICROPAY:付款码支付 MWEB:H5支付 FACEPAY:刷脸支付"
+                    clearable
+                    @blur="loadData(true)"
+                    class="wd150 mr10">
+                </el-input>-->
+        <!--        <el-input
+                    v-model="state.formQuery.tradeState"
+                    placeholder="交易状态,枚举值:SUCCESS:支付成功REFUND:转入退款NOTPAY:未支付CLOSED:已关闭REVOKED:已撤销(付款码支付)USERPAYING:用户支付中(付款码支付)PAYERROR:支付失败(其他原因,如银行返回失败)"
+                    clearable
+                    @blur="loadData(true)"
+                    class="wd150 mr10">
+                </el-input>-->
+
+
+        <el-button class="ml10" plain size="default" type="success" @click="loadData(true)">
+          <SvgIcon name="ele-Search"/>
+          查询
+        </el-button>
+      </el-form>
+
+      <el-table
+          border
+          stripe="stripe"
+          :height="state.tableData.height"
+          highlight-current-row
+          current-row-key="id"
+          row-key="id"
+          :data="state.tableData.data"
+          v-loading="state.tableData.loading"
+          @selection-change="handleTableSelectionChange"
+          @sort-change="handleTableSortChange">
+        <template #empty>
+          <el-empty></el-empty>
+        </template>
+        <el-table-column
+            v-for="field in state.tableData.columns"
+            :key="field.prop"
+            :label="field.label"
+            :column-key="field.prop"
+            :width="field.width"
+            :min-width="field.minWidth"
+            :fixed="field.fixed"
+            :sortable="field.sortable"
+            :show-overflow-tooltip="!field.fixed&&field.width>150"
+        >
+          <template #default="{row}">
+            <template v-if="field.prop==='expand'">
+              <p style="padding-left: 2em;" v-html="row[field.prop]"></p>
+            </template>
+            <template v-if="field.prop==='rechargeAmount'">
+              {{u.fmt.fmtMoney(row[field.prop])}}
+            </template>
+            <template v-else>
+              <div>{{ row[field.prop] }}</div>
+            </template>
+
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <ext-page class="page-pager" v-model:value="state.pageQuery" @change="loadData(false)"/>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts" name="PayLogList">
+import {nextTick, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue';
+import {$get} from "/@/utils/request";
+import {Msg} from "/@/utils/message";
+import u from "/@/utils/u"
+
+import {useRoute} from "vue-router";
+import ExtPage from '/@/components/form/ExtPage.vue'
+
+import mittBus from '/@/utils/mitt';
+
+const route = useRoute();
+
+
+//定义引用
+const queryRef = ref();
+const payLogDialogRef = ref();
+
+//定义变量
+const state = reactive({
+  formQuery: {},
+  pageQuery: {
+    pageNum: 1,
+    pageSize: 10,
+    total: 0
+  },
+  tableData: {
+    height: 500,
+    data: [] as Array<any>,
+    loading: false,
+    columns: [
+      {label: '用户ID', prop: 'userId', width: 200, resizable: true, fixed: 'left'},
+      {label: '用户手机号', prop: 'mobilePhone', width: 150, resizable: true, fixed: 'left'},
+      {label: '商户订单号', prop: 'outTradeNo', width: 250, resizable: true},
+      {label: '微信订单号', prop: 'transactionId', width: 250, resizable: true},
+      {label: '订单总金额', prop: 'rechargeAmount', resizable: true, width: 130},
+      // {label: '交易类型', prop: 'tradeType', width: 150, resizable: true},
+      {label: '交易状态', prop: 'tradeState', width: 150, resizable: true},
+      {label: '用户支付币种', prop: 'currency', width: 150, resizable: true},
+      {label: '支付完成时间', prop: 'transactionTime', sortable: 'custom', resizable: true, width: 200, fixed: 'right'},
+    ],
+  },
+})
+
+
+// 监听双向绑定 modelValue 的变化
+// watch(
+//         () => state.pageNum,
+//         () => {
+//
+//         }
+// );
+
+//生命周期钩子
+onBeforeMount(() => {
+})
+
+onMounted(() => {
+  var query = route.query;
+  console.log(route.params, route.query)
+  if (query.mobilePhone) {
+    state.formQuery.mobilePhone = query.mobilePhone;
+  }
+
+  loadData();
+
+  nextTick(() => {
+    let bodyHeight = document.body.clientHeight;
+    let queryHeight = queryRef.value.$el.clientHeight;
+    state.tableData.height = bodyHeight - queryHeight - 320
+  })
+
+  mittBus.on("payLog.refresh", () => {
+    loadData();
+  })
+});
+
+onBeforeUnmount(() => {
+  mittBus.off("payLog.refresh")
+})
+
+
+//region 方法区
+// 初始化表格数据
+const loadData = (refresh: boolean = false) => {
+  if (refresh) {
+    state.pageQuery.pageNum = 1;
+  }
+  state.tableData.loading = true;
+  $get(`/custom/listRecharge`, {...state.formQuery, ...state.pageQuery}).then((res: any) => {
+    let {list, total} = res;
+    state.tableData.data = list;
+    state.pageQuery.total = total;
+    state.tableData.loading = false;
+  }).catch(e => {
+    console.error(e)
+    state.tableData.loading = false;
+  })
+};
+
+// 打开修改用户弹窗
+const onRowClick = (type: string, row: any) => {
+  payLogDialogRef.value.open(type, row);
+};
+
+// 删除用户
+const onRowDel = (row: any) => {
+  Msg.confirm(`此操作将永久删除:『${row.name}』,是否继续?`).then(() => {
+    $get(`/payLog/delete/${row.id}`).then(() => {
+      Msg.message("删除成功", 'success')
+    }).catch(() => {
+      Msg.message("删除失败", 'error')
+    })
+  });
+};
+
+const handleTableSelectionChange = (selection: any) => {
+  console.log("handleTableSelectionChange>>", selection)
+  // emit("on-check-change", selection)
+}
+
+const handleTableSortChange = (column, prop, order) => {
+  console.log("handleTableSortChange>>", column, prop, order)
+  // emit("on-sort-change", column)
+}
+
+
+//endregion
+
+
+// 暴露变量
+// defineExpose({
+//     loadData,
+// });
+</script>

+ 258 - 0
admin-web/src/views/admin/feedback/index.vue

@@ -0,0 +1,258 @@
+<style scoped lang="scss">
+.system-container {
+
+  :deep(.el-card__body) {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    flex: 1;
+    overflow: auto;
+
+    .el-table {
+      flex: 1;
+    }
+
+  }
+}
+
+.page-content {
+  margin-bottom: 20px;
+}
+
+.page-pager {
+  background-color: #fff;
+  height: 24px;
+}
+</style>
+<template>
+  <div class="system-container layout-padding">
+    <el-card shadow="hover" class="layout-padding-auto">
+
+
+      <el-form
+          :model="state.formQuery"
+          ref="queryRef"
+          size="default" label-width="0px" class="mt5 mb5">
+        <el-input
+            v-model="state.formQuery.mobilePhone"
+            placeholder="用户手机号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+        <el-input
+            v-model="state.formQuery.outTradeNo"
+            placeholder="商户订单号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+        <el-input
+            v-model="state.formQuery.transactionId"
+            placeholder="微信订单号"
+            clearable
+            @blur="loadData(true)"
+            class="wd150 mr10">
+        </el-input>
+        <!--        <el-input
+                    v-model="state.formQuery.tradeType"
+                    placeholder="交易类型,枚举值:JSAPI:公众号支付 NATIVE:扫码支付 APP:APP支付 MICROPAY:付款码支付 MWEB:H5支付 FACEPAY:刷脸支付"
+                    clearable
+                    @blur="loadData(true)"
+                    class="wd150 mr10">
+                </el-input>-->
+        <!--        <el-input
+                    v-model="state.formQuery.tradeState"
+                    placeholder="交易状态,枚举值:SUCCESS:支付成功REFUND:转入退款NOTPAY:未支付CLOSED:已关闭REVOKED:已撤销(付款码支付)USERPAYING:用户支付中(付款码支付)PAYERROR:支付失败(其他原因,如银行返回失败)"
+                    clearable
+                    @blur="loadData(true)"
+                    class="wd150 mr10">
+                </el-input>-->
+
+
+        <el-button class="ml10" plain size="default" type="success" @click="loadData(true)">
+          <SvgIcon name="ele-Search"/>
+          查询
+        </el-button>
+      </el-form>
+
+      <el-table
+          border
+          stripe="stripe"
+          :height="state.tableData.height"
+          highlight-current-row
+          current-row-key="id"
+          row-key="id"
+          :data="state.tableData.data"
+          v-loading="state.tableData.loading"
+          @selection-change="handleTableSelectionChange"
+          @sort-change="handleTableSortChange">
+        <template #empty>
+          <el-empty></el-empty>
+        </template>
+        <el-table-column
+            v-for="field in state.tableData.columns"
+            :key="field.prop"
+            :label="field.label"
+            :column-key="field.prop"
+            :width="field.width"
+            :min-width="field.minWidth"
+            :fixed="field.fixed"
+            :sortable="field.sortable"
+            :show-overflow-tooltip="!field.fixed&&field.width>150"
+        >
+          <template #default="{row}">
+            <template v-if="field.prop==='expand'">
+              <p style="padding-left: 2em;" v-html="row[field.prop]"></p>
+            </template>
+            <template v-if="field.prop==='rechargeAmount'">
+              {{u.fmt.fmtMoney(row[field.prop])}}
+            </template>
+            <template v-else>
+              <div>{{ row[field.prop] }}</div>
+            </template>
+
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <ext-page class="page-pager" v-model:value="state.pageQuery" @change="loadData(false)"/>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts" name="PayLogList">
+import {nextTick, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue';
+import {$get} from "/@/utils/request";
+import {Msg} from "/@/utils/message";
+import u from "/@/utils/u"
+
+import {useRoute} from "vue-router";
+import ExtPage from '/@/components/form/ExtPage.vue'
+
+import mittBus from '/@/utils/mitt';
+
+const route = useRoute();
+
+
+//定义引用
+const queryRef = ref();
+const payLogDialogRef = ref();
+
+//定义变量
+const state = reactive({
+  formQuery: {},
+  pageQuery: {
+    pageNum: 1,
+    pageSize: 10,
+    total: 0
+  },
+  tableData: {
+    height: 500,
+    data: [] as Array<any>,
+    loading: false,
+    columns: [
+      {label: '用户ID', prop: 'userId', width: 200, resizable: true, fixed: 'left'},
+      {label: '用户手机号', prop: 'mobilePhone', width: 150, resizable: true, fixed: 'left'},
+      {label: '商户订单号', prop: 'outTradeNo', width: 250, resizable: true},
+      {label: '微信订单号', prop: 'transactionId', width: 250, resizable: true},
+      {label: '订单总金额', prop: 'rechargeAmount', resizable: true, width: 130},
+      // {label: '交易类型', prop: 'tradeType', width: 150, resizable: true},
+      {label: '交易状态', prop: 'tradeState', width: 150, resizable: true},
+      {label: '用户支付币种', prop: 'currency', width: 150, resizable: true},
+      {label: '支付完成时间', prop: 'transactionTime', sortable: 'custom', resizable: true, width: 200, fixed: 'right'},
+    ],
+  },
+})
+
+
+// 监听双向绑定 modelValue 的变化
+// watch(
+//         () => state.pageNum,
+//         () => {
+//
+//         }
+// );
+
+//生命周期钩子
+onBeforeMount(() => {
+})
+
+onMounted(() => {
+  var query = route.query;
+  console.log(route.params, route.query)
+  if (query.mobilePhone) {
+    state.formQuery.mobilePhone = query.mobilePhone;
+  }
+
+  loadData();
+
+  nextTick(() => {
+    let bodyHeight = document.body.clientHeight;
+    let queryHeight = queryRef.value.$el.clientHeight;
+    state.tableData.height = bodyHeight - queryHeight - 320
+  })
+
+  mittBus.on("payLog.refresh", () => {
+    loadData();
+  })
+});
+
+onBeforeUnmount(() => {
+  mittBus.off("payLog.refresh")
+})
+
+
+//region 方法区
+// 初始化表格数据
+const loadData = (refresh: boolean = false) => {
+  if (refresh) {
+    state.pageQuery.pageNum = 1;
+  }
+  state.tableData.loading = true;
+  $get(`/custom/listRecharge`, {...state.formQuery, ...state.pageQuery}).then((res: any) => {
+    let {list, total} = res;
+    state.tableData.data = list;
+    state.pageQuery.total = total;
+    state.tableData.loading = false;
+  }).catch(e => {
+    console.error(e)
+    state.tableData.loading = false;
+  })
+};
+
+// 打开修改用户弹窗
+const onRowClick = (type: string, row: any) => {
+  payLogDialogRef.value.open(type, row);
+};
+
+// 删除用户
+const onRowDel = (row: any) => {
+  Msg.confirm(`此操作将永久删除:『${row.name}』,是否继续?`).then(() => {
+    $get(`/payLog/delete/${row.id}`).then(() => {
+      Msg.message("删除成功", 'success')
+    }).catch(() => {
+      Msg.message("删除失败", 'error')
+    })
+  });
+};
+
+const handleTableSelectionChange = (selection: any) => {
+  console.log("handleTableSelectionChange>>", selection)
+  // emit("on-check-change", selection)
+}
+
+const handleTableSortChange = (column, prop, order) => {
+  console.log("handleTableSortChange>>", column, prop, order)
+  // emit("on-sort-change", column)
+}
+
+
+//endregion
+
+
+// 暴露变量
+// defineExpose({
+//     loadData,
+// });
+</script>

+ 112 - 0
car-wash-admin/src/main/java/com/kym/admin/controller/FaqController.java

@@ -0,0 +1,112 @@
+package com.kym.admin.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.kym.common.R;
+import com.kym.common.annotation.SysLog;
+import com.kym.common.controller.IController;
+import com.kym.entity.admin.Faq;
+import com.kym.entity.admin.queryParams.FaqQueryParam;
+import com.kym.service.admin.FaqService;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 常见问题 前端控制器
+ * </p>
+ *
+ * @since 2024-11-12
+ */
+@RestController
+@RequestMapping("/faq")
+public class FaqController extends IController {
+
+    @Resource
+    private FaqService faqService;
+
+
+    /**
+     * 纠错反馈新增接口
+     *
+     * @param faq 新增纠错反馈
+     * @return Res
+     */
+    @SaCheckPermission(value = "faq.add")
+    @PostMapping("add")
+    @SysLog(value = "纠错反馈新增接口")
+    public R<?> add(@Valid @RequestBody Faq faq) {
+//other params checked
+        return resp(() -> faqService.add(faq));
+    }
+
+    /**
+     * 纠错反馈编辑
+     *
+     * @return Res
+     */
+    @SaCheckPermission(value = "faq.modify")
+    @PostMapping("modify")
+    @SysLog(value = "纠错反馈更新接口")
+    public R<?> modify(@Valid @RequestBody Faq faq) {
+        return resp((t) -> faqService.modify(faq));
+    }
+
+
+    /**
+     * 纠错反馈查询接口
+     *
+     * @return Res
+     */
+    @SaCheckPermission(value = "faq.list")
+    @PostMapping("list")
+    @SysLog(value = "纠错反馈列表查询接口")
+    public R<?> list(@RequestBody FaqQueryParam query) {
+        return resp(() -> faqService.list(query));
+    }
+
+
+    /**
+     * 纠错反馈查询详情接口
+     *
+     * @return Res
+     */
+    @SaCheckPermission(value = "faq.list")
+    @GetMapping("detail/{id}")
+    @SysLog(value = "纠错反馈详情查询接口")
+    public R<?> detail(@PathVariable long id) {
+        return resp(() -> faqService.detail(id));
+    }
+
+
+    /**
+     * 纠错反馈变更状态接口
+     *
+     * @return Res
+     */
+    @SaCheckPermission(value = "faq.modify")
+    @GetMapping("status/{id}/{status}")
+    @SysLog(value = "纠错反馈变更状态")
+    public R<?> status(@PathVariable long id, @PathVariable int status) {
+        return resp((t) -> faqService.status(id, status));
+    }
+
+
+    /**
+     * 纠错反馈删除接口
+     *
+     * @return Res
+     */
+    @SaCheckPermission(value = "faq.remove")
+    @GetMapping("remove/{id}")
+    @SysLog(value = "纠错反馈删除")
+    public R<?> remove(@PathVariable long id) {
+        return resp((t) -> faqService.remove(id));
+    }
+
+}

+ 4 - 3
car-wash-admin/src/main/java/com/kym/admin/controller/FeedbackController.java

@@ -5,6 +5,7 @@ import com.kym.common.R;
 import com.kym.common.annotation.SysLog;
 import com.kym.common.controller.IController;
 import com.kym.entity.admin.Feedback;
+import com.kym.entity.admin.queryParams.FeedbackQueryParam;
 import com.kym.service.admin.FeedbackService;
 import jakarta.annotation.Resource;
 import jakarta.validation.Valid;
@@ -38,7 +39,7 @@ public class FeedbackController extends IController {
     @SaCheckPermission(value = "feedback.add")
     @PostMapping("add")
     @SysLog(value = "纠错反馈新增接口")
-    public R<?> add(@Valid @RequestBody Feedback.FeedbackInfo feedback) {
+    public R<?> add(@Valid @RequestBody Feedback feedback) {
 //other params checked
         return resp(() -> feedbackService.add(feedback));
     }
@@ -51,7 +52,7 @@ public class FeedbackController extends IController {
     @SaCheckPermission(value = "feedback.modify")
     @PostMapping("modify")
     @SysLog(value = "纠错反馈更新接口")
-    public R<?> reply(@Valid @RequestBody Feedback.FeedbackInfo feedback) {
+    public R<?> reply(@Valid @RequestBody Feedback feedback) {
         return resp((t) -> feedbackService.reply(feedback));
     }
 
@@ -64,7 +65,7 @@ public class FeedbackController extends IController {
     @SaCheckPermission(value = "feedback.list")
     @PostMapping("list")
     @SysLog(value = "纠错反馈列表查询接口")
-    public R<?> list(@RequestBody Feedback.FeedbackBasicQuery query) {
+    public R<?> list(@RequestBody FeedbackQueryParam query) {
         return resp(() -> feedbackService.list(query));
     }
 

+ 8 - 8
car-wash-admin/src/main/java/com/kym/admin/utils/MybatisPlusGeneratorForAdmin.java

@@ -21,7 +21,7 @@ public class MybatisPlusGeneratorForAdmin {
 
     public static void main(String[] args) {
         // 指定数据源
-        FastAutoGenerator.create("jdbc:mysql://121.40.98.15:3307/car-wash", "root", "KuaiyuMan/*-")
+        FastAutoGenerator.create("jdbc:mysql://121.40.98.15:3307/car_wash", "root", "KuaiyuMan/*-")
                 .globalConfig(builder -> {
                     builder.author("skyline")
                             // 指定输出目录
@@ -50,12 +50,12 @@ public class MybatisPlusGeneratorForAdmin {
                             .controller("admin.controller")
                             // 设置mapperXml生成路径
                             .pathInfo(Map.of(
-                                    OutputFile.entity, "D://快与慢充电桩/code/car-wash-java/car-wash-entity/src/main/java/com/kym/entity/admin",
-                                    OutputFile.service, "D://快与慢充电桩/code/car-wash-java/car-wash-service/src/main/java/com/kym/service/admin",
-                                    OutputFile.serviceImpl, "D://快与慢充电桩/code/car-wash-java/car-wash-service/src/main/java/com/kym/service/admin/impl",
-                                    OutputFile.mapper, "D://快与慢充电桩/code/car-wash-java/car-wash-mapper/src/main/java/com/kym/mapper/admin",
-                                    OutputFile.controller, "D://快与慢充电桩/code/car-wash-java/car-wash-admin/src/main/java/com/kym/admin/controller",
-                                    OutputFile.xml, "D://快与慢充电桩/code/car-wash-java/car-wash-mapper/src/main/resources/mappers/admin"
+                                    OutputFile.entity, "D:\\2.code\\car-wash-java\\car-wash-entity\\src\\main\\java\\com\\kym\\entity\\admin",
+                                    OutputFile.service, "D:\\2.code\\car-wash-java\\car-wash-service\\src\\main\\java\\com\\kym\\service\\admin",
+                                    OutputFile.serviceImpl, "D:\\2.code\\car-wash-java\\car-wash-service\\src\\main\\java\\com\\kym\\service\\admin\\impl",
+                                    OutputFile.mapper, "D:\\2.code\\car-wash-java\\car-wash-mapper\\src\\main\\java\\com\\kym\\mapper\\admin",
+                                    OutputFile.controller, "D:\\2.code\\car-wash-java\\car-wash-admin\\src\\main\\java\\com\\kym\\admin\\controller",
+                                    OutputFile.xml, "D:\\2.code\\car-wash-java\\car-wash-mapper\\src\\main\\resources\\mappers\\admin"
 
                             ));
                 })
@@ -63,7 +63,7 @@ public class MybatisPlusGeneratorForAdmin {
                 .strategyConfig(builder -> {
                     // 设置需要生成的表名
                     builder.addInclude(
-//                            "t_equipment_info",
+                                    "t_feedback", "t_faq"
                             )
                             // 设置过滤表前缀
                             .addTablePrefix("t_");

+ 41 - 0
car-wash-entity/src/main/java/com/kym/entity/admin/Faq.java

@@ -0,0 +1,41 @@
+package com.kym.entity.admin;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.kym.entity.BaseEntity;
+import java.io.Serializable;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 常见问题
+ * </p>
+ *
+ * @author skyline
+ * @since 2024-11-12
+ */
+@Getter
+@Setter
+@TableName("t_faq")
+public class Faq extends BaseEntity {
+
+    public static final int STATUS_启用 = 1;
+    public static final int STATUS_禁用 = 2;
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 问题
+     */
+    private String question;
+
+    /**
+     * 状态
+     */
+    private Integer status;
+
+    /**
+     * 答案
+     */
+    private String answer;
+}

+ 53 - 59
car-wash-entity/src/main/java/com/kym/entity/admin/Feedback.java

@@ -1,80 +1,74 @@
 package com.kym.entity.admin;
 
-
-import com.kym.entity.miniapp.Attachment;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.kym.entity.BaseEntity;
 import java.io.Serializable;
-import java.util.Date;
-import java.util.List;
-
+import java.time.LocalDateTime;
+import lombok.Getter;
+import lombok.Setter;
 
 /**
+ * <p>
  * 纠错反馈
+ * </p>
  *
- * @date 2024-09-22T20:40:35.300431885
+ * @author skyline
+ * @since 2024-11-12
  */
-@Data
-@EqualsAndHashCode(callSuper = false)
-public class Feedback implements Serializable {
-
-    public static final int TYPE_ERROR = 1; //纠错
-    public static final int TYPE_SUGGEST = 2; //建议
-    public static final int TYPE_OTHER = 3; //其他
+@Getter
+@Setter
+@TableName("t_feedback")
+public class Feedback extends BaseEntity {
 
-    public static final int STATUS_UNREPLY = 1; //未回复
-    public static final int STATUS_REPLIED = 2; //已回复
+    private static final long serialVersionUID = 1L;
 
-    private long id;
+    /**
+     * 反馈标题
+     */
     private String title;
-    private int type;
-    private String content;
-    private List<Attachment> attachList;
-    private int status;
 
-    private Date submitTime;
-    private long submitUserId;
+    /**
+     * 纠错类型
+     */
+    private Integer type;
 
-    private String replyContent;
-    private Date replyTime;
-    private long replyUserId;
+    /**
+     * 状态
+     */
+    private Integer status;
 
-    private Date createTime;
-    private Date updateTime;
+    /**
+     * 详情描述
+     */
+    private String content;
 
-    @Data
-    @EqualsAndHashCode(callSuper = true)
-    public static class FeedbackInfo extends Feedback {
+    /**
+     * 提交时间
+     */
+    private LocalDateTime submitTime;
 
-        // @One(mkf = "updateBy", tf = "name", comment = "更新人")
-        // private String updateName;
-    }
+    /**
+     * 附件列表
+     */
+    private String attachList;
 
-    @Data
-    @EqualsAndHashCode(callSuper = false)
-    public static class FeedbackBasicQuery  {
-        private String content;
-        private Long id;
-        private long submitUserId;
-        private String replyContent;
-        private Integer status;
-        private String title;
-        private Integer type;
-        private long replyUserId;
+    /**
+     * 反馈人
+     */
+    private Long submitUserId;
 
-        //region date query
-        //endregion
+    /**
+     * 回复内容
+     */
+    private String replyContent;
 
+    /**
+     * 回复时间
+     */
+    private LocalDateTime replyTime;
 
-        //region sort query
-        private Integer createTimeSort;
-        private Integer idSort;
-        private Integer replyTimeSort;
-        private Integer statusSort;
-        private Integer submitTimeSort;
-        private Integer typeSort;
-        private Integer updateTimeSort;
-        //endregion
-    }
+    /**
+     * 回复人
+     */
+    private Long replyUserId;
 }

+ 11 - 0
car-wash-entity/src/main/java/com/kym/entity/admin/queryParams/FaqQueryParam.java

@@ -0,0 +1,11 @@
+package com.kym.entity.admin.queryParams;
+
+import com.kym.entity.common.PageParams;
+import lombok.Data;
+
+@Data
+public class FaqQueryParam extends PageParams {
+    private Integer status;
+    private String question;
+    private String answer;
+}

+ 56 - 0
car-wash-entity/src/main/java/com/kym/entity/admin/queryParams/FeedbackQueryParam.java

@@ -0,0 +1,56 @@
+package com.kym.entity.admin.queryParams;
+
+import com.kym.entity.common.PageParams;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+
+@Data
+public class FeedbackQueryParam extends PageParams {
+    /**
+     * 反馈标题
+     */
+    private String title;
+
+    /**
+     * 纠错类型
+     */
+    private Integer type;
+
+    /**
+     * 状态
+     */
+    private Integer status;
+
+    /**
+     * 详情描述
+     */
+    private String content;
+
+    /**
+     * 提交时间
+     */
+    private LocalDateTime submitTime;
+
+
+    /**
+     * 反馈人
+     */
+    private Long submitUserId;
+
+    /**
+     * 回复内容
+     */
+    private String replyContent;
+
+    /**
+     * 回复时间
+     */
+    private LocalDateTime replyTime;
+
+    /**
+     * 回复人
+     */
+    private Long replyUserId;
+}

+ 16 - 0
car-wash-mapper/src/main/java/com/kym/mapper/admin/FaqMapper.java

@@ -0,0 +1,16 @@
+package com.kym.mapper.admin;
+
+import com.kym.entity.admin.Faq;
+import com.kym.mapper.mybatisplus.MyBaseMapper;
+
+/**
+ * <p>
+ * 常见问题 Mapper 接口
+ * </p>
+ *
+ * @author skyline
+ * @since 2024-11-12
+ */
+public interface FaqMapper extends MyBaseMapper<Faq> {
+
+}

+ 16 - 0
car-wash-mapper/src/main/java/com/kym/mapper/admin/FeedbackMapper.java

@@ -0,0 +1,16 @@
+package com.kym.mapper.admin;
+
+import com.kym.entity.admin.Feedback;
+import com.kym.mapper.mybatisplus.MyBaseMapper;
+
+/**
+ * <p>
+ * 纠错反馈 Mapper 接口
+ * </p>
+ *
+ * @author skyline
+ * @since 2024-11-12
+ */
+public interface FeedbackMapper extends MyBaseMapper<Feedback> {
+
+}

+ 17 - 0
car-wash-mapper/src/main/resources/mappers/admin/FaqMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.kym.mapper.admin.FaqMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.kym.entity.admin.Faq">
+        <result column="question" property="question" />
+        <result column="status" property="status" />
+        <result column="answer" property="answer" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        question, status, answer
+    </sql>
+
+</mapper>

+ 24 - 0
car-wash-mapper/src/main/resources/mappers/admin/FeedbackMapper.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.kym.mapper.admin.FeedbackMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.kym.entity.admin.Feedback">
+        <result column="title" property="title" />
+        <result column="type" property="type" />
+        <result column="status" property="status" />
+        <result column="content" property="content" />
+        <result column="submit_time" property="submitTime" />
+        <result column="attach_list" property="attachList" />
+        <result column="submit_user_id" property="submitUserId" />
+        <result column="reply_content" property="replyContent" />
+        <result column="reply_time" property="replyTime" />
+        <result column="reply_user_id" property="replyUserId" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        title, type, status, content, submit_time, attach_list, submit_user_id, reply_content, reply_time, reply_user_id
+    </sql>
+
+</mapper>

+ 28 - 0
car-wash-service/src/main/java/com/kym/service/admin/FaqService.java

@@ -0,0 +1,28 @@
+package com.kym.service.admin;
+
+import com.kym.entity.admin.Faq;
+import com.kym.entity.admin.queryParams.FaqQueryParam;
+import com.kym.service.mybatisplus.MyBaseService;
+
+/**
+ * <p>
+ * 常见问题 服务类
+ * </p>
+ *
+ * @author skyline
+ * @since 2024-11-12
+ */
+public interface FaqService extends MyBaseService<Faq> {
+
+    Long add(Faq faq);
+
+    void modify(Faq faq);
+
+    Object list(FaqQueryParam query);
+
+    Faq detail(long id);
+
+    void status(long id, int status);
+
+    void remove(long id);
+}

+ 17 - 34
car-wash-service/src/main/java/com/kym/service/admin/FeedbackService.java

@@ -1,47 +1,30 @@
 package com.kym.service.admin;
 
-import com.kym.common.R;
-import com.kym.entity.admin.Feedback.FeedbackBasicQuery;
-import com.kym.entity.admin.Feedback.FeedbackInfo;
-import com.kym.entity.common.PageBean;
-
+import com.kym.entity.admin.Feedback;
+import com.kym.entity.admin.queryParams.FeedbackQueryParam;
+import com.kym.service.mybatisplus.MyBaseService;
 
 /**
- * 纠错反馈业务类
- * @date 2024-09-22T20:40:35.300431885
+ * <p>
+ * 纠错反馈 服务类
+ * </p>
+ *
+ * @author skyline
+ * @since 2024-11-12
  */
-public interface  FeedbackService {
-
-    /**
-     * 纠错反馈分页查询
-     */
-     PageBean<?> list(FeedbackBasicQuery query);
-
-    /**
-     * 查询纠错反馈详情
-     */
-     FeedbackInfo detail(long id);
+public interface FeedbackService extends MyBaseService<Feedback> {
 
+    int add(Feedback faq);
 
-    /**
-     * 纠错反馈状态变更
-     */
-     void status(long id, int status);
+    void modify(Feedback faq);
 
+    void reply(Feedback faq);
 
-    /**
-     * 新增纠错反馈
-     */
-     long add(FeedbackInfo feedback);
+    Object list(FeedbackQueryParam query);
 
-    /**
-     * 物理删除纠错反馈
-     */
-      R<?> remove(long id);
+    Feedback detail(long id);
 
-    /**
-     * 编辑纠错反馈
-     */
-     void reply(FeedbackInfo feedback);
+    void status(long id, int status);
 
+    void remove(long id);
 }

+ 71 - 0
car-wash-service/src/main/java/com/kym/service/admin/impl/FaqServiceImpl.java

@@ -0,0 +1,71 @@
+package com.kym.service.admin.impl;
+
+import com.github.pagehelper.PageHelper;
+import com.kym.common.utils.CommUtil;
+import com.kym.entity.admin.Faq;
+import com.kym.entity.admin.queryParams.FaqQueryParam;
+import com.kym.entity.common.PageBean;
+import com.kym.mapper.admin.FaqMapper;
+import com.kym.service.admin.FaqService;
+import com.kym.service.mybatisplus.MyBaseServiceImpl;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Optional;
+
+/**
+ * <p>
+ * 常见问题 服务实现类
+ * </p>
+ *
+ * @author skyline
+ * @since 2024-11-12
+ */
+@Service
+public class FaqServiceImpl extends MyBaseServiceImpl<FaqMapper, Faq> implements FaqService {
+
+    @Override
+    public Long add(Faq faq) {
+        Optional<Faq> optionalFaq = lambdaQuery().eq(Faq::getQuestion, faq.getQuestion()).oneOpt();
+        CommUtil.asserts(optionalFaq.isEmpty(), "问题名称已存在");
+        faq.setStatus(Faq.STATUS_启用);
+        save(faq);
+        return faq.getId();
+    }
+
+    @Override
+    public void modify(Faq faq) {
+        Faq old = getById(faq.getId());
+        CommUtil.asserts(old.getStatus() == Faq.STATUS_禁用, "已启用的问题无法编辑,请先禁用");
+        //标题重名的校验
+        Optional<Faq> optionalFaq = lambdaQuery().eq(Faq::getQuestion, faq.getQuestion()).ne(Faq::getId, faq.getId()).oneOpt();
+        CommUtil.asserts(optionalFaq.isEmpty(), "问题名称已存在");
+        lambdaUpdate().set(Faq::getQuestion, faq.getQuestion()).set(Faq::getAnswer, faq.getAnswer()).eq(Faq::getId, old.getId()).update();
+    }
+
+    @Override
+    public Object list(FaqQueryParam query) {
+        PageHelper.startPage(query.getPageNum(), query.getPageSize());
+        var res = lambdaQuery()
+                .like(CommUtil.isNotEmptyAndNull(query.getQuestion()), Faq::getQuestion, query.getQuestion())
+                .like(CommUtil.isNotEmptyAndNull(query.getAnswer()), Faq::getAnswer, query.getAnswer())
+                .eq(CommUtil.isNotEmptyAndNull(query.getStatus()), Faq::getStatus, query.getStatus()).list();
+        return new PageBean<>(res);
+    }
+
+    @Override
+    public Faq detail(long id) {
+        return getById(id);
+
+    }
+
+    @Override
+    public void status(long id, int status) {
+        lambdaUpdate().set(Faq::getStatus, status).eq(Faq::getId, id).update();
+    }
+
+    @Override
+    public void remove(long id) {
+        removeById(id);
+    }
+}

+ 43 - 46
car-wash-service/src/main/java/com/kym/service/admin/impl/FeedbackServiceImpl.java

@@ -1,70 +1,67 @@
 package com.kym.service.admin.impl;
 
-import com.kym.common.R;
-import com.kym.entity.admin.Feedback.FeedbackBasicQuery;
-import com.kym.entity.admin.Feedback.FeedbackInfo;
+import cn.dev33.satoken.stp.StpUtil;
+import com.github.pagehelper.PageHelper;
+import com.kym.common.utils.CommUtil;
+import com.kym.entity.admin.Faq;
+import com.kym.entity.admin.Feedback;
+import com.kym.entity.admin.queryParams.FeedbackQueryParam;
 import com.kym.entity.common.PageBean;
+import com.kym.mapper.admin.FeedbackMapper;
 import com.kym.service.admin.FeedbackService;
+import com.kym.service.mybatisplus.MyBaseServiceImpl;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
 
 /**
- * 纠错反馈业务类
+ * <p>
+ * 纠错反馈 服务实现类
+ * </p>
  *
- * @date 2024-09-22T20:40:35.300431885
+ * @author skyline
+ * @since 2024-11-12
  */
-@Service("feedbackService")
-public class FeedbackServiceImpl implements FeedbackService {
-
+@Service
+public class FeedbackServiceImpl extends MyBaseServiceImpl<FeedbackMapper, Feedback> implements FeedbackService {
 
-    /**
-     * 纠错反馈分页查询
-     */
-    public PageBean<FeedbackInfo> list(FeedbackBasicQuery query) {
-        return null;
+    @Override
+    public int add(Feedback feedback) {
+        save(feedback);
+        return 0;
     }
 
-    /**
-     * 查询纠错反馈详情
-     */
-    public FeedbackInfo detail(long id) {
-        return null;
-    }
-
-
-    /**
-     * 纠错反馈状态变更
-     */
-    @Transactional(rollbackFor = Exception.class)
-    public void status(long id, int status) {
+    @Override
+    public void modify(Feedback feedback) {
 
     }
 
+    @Override
+    public void reply(Feedback feedback) {
 
-    /**
-     * 新增纠错反馈
-     */
-    @Transactional(rollbackFor = Exception.class)
-    public long add(FeedbackInfo feedback) {
-        return 0L;
     }
 
-    /**
-     * 物理删除纠错反馈
-     */
-    @Transactional(rollbackFor = Exception.class)
-    public R<?> remove(long id) {
-        return null;
+    @Override
+    public Object list(FeedbackQueryParam query) {
+        PageHelper.startPage(query.getPageNum(), query.getPageSize());
+        var res = lambdaQuery()
+                .like(CommUtil.isNotEmptyAndNull(query.getTitle()), Feedback::getTitle, query.getTitle())
+                .eq(CommUtil.isNotEmptyAndNull(query.getType()), Feedback::getType, query.getType())
+                .eq(CommUtil.isNotEmptyAndNull(query.getStatus()), Feedback::getStatus, query.getStatus())
+                .eq(CommUtil.isNotEmptyAndNull(query.getSubmitUserId()), Feedback::getSubmitUserId, StpUtil.getLoginIdAsLong()).list();
+        return new PageBean<>(res);
     }
 
-    /**
-     * 编辑纠错反馈
-     */
-    @Transactional(rollbackFor = Exception.class)
-    public void reply(FeedbackInfo feedback) {
-
+    @Override
+    public Feedback detail(long id) {
+        return getById(id);
     }
 
+    @Override
+    public void status(long id, int status) {
+        lambdaUpdate().set(Feedback::getStatus, status).eq(Feedback::getId, id).update();
+    }
 
+    @Override
+    public void remove(long id) {
+        removeById(id);
+    }
 }