Przeglądaj źródła

feat: 收费记录查询页面——报表查询→收费记录,支持车牌/支付方式/日期筛选

lq 1 miesiąc temu
rodzic
commit
e8abbf171a

+ 10 - 0
frontend/src/api/payment.js

@@ -0,0 +1,10 @@
+import service from '@/utils/request'
+
+// 收费记录列表
+export const getPaymentList = (params) => {
+  return service({
+    url: '/payment/list',
+    method: 'get',
+    params
+  })
+}

+ 1 - 0
frontend/src/lang/en.js

@@ -222,4 +222,5 @@ export default {
   change: 'Change',
   confirmPayAndExit: 'Confirm & Release',
   insufficientAmount: 'Insufficient amount',
+  paymentRecord: 'Payment Record',
 }

+ 1 - 0
frontend/src/lang/zh-CN.js

@@ -222,4 +222,5 @@ export default {
   change: '找零',
   confirmPayAndExit: '确认收款并放行',
   insufficientAmount: '实收金额不足',
+  paymentRecord: '收费记录',
 }

+ 1 - 0
frontend/src/lang/zh-HK.js

@@ -214,4 +214,5 @@ export default {
   pleaseSelectPark: '請選擇停車場',
   rfidInput: '請輸入RFID標籤',
   exitRecordDetail: '進場: {entryTime} | 停留: {duration} | 費用: ¥{fee}',
+  paymentRecord: '收費記錄',
 }

+ 1 - 0
frontend/src/lang/zh-TW.js

@@ -214,4 +214,5 @@ export default {
   pleaseSelectPark: '請選擇停車場',
   rfidInput: '請輸入RFID標籤',
   exitRecordDetail: '進場: {entryTime} | 停留: {duration} | 費用: ¥{fee}',
+  paymentRecord: '收費記錄',
 }

+ 94 - 0
frontend/src/view/report/paymentRecord.vue

@@ -0,0 +1,94 @@
+<template>
+  <div>
+    <el-form inline>
+      <el-form-item :label="$t.value.LicensePlateNo">
+        <el-input v-model="queryForm.plate_number" :placeholder="$t.value.carPlateInput" clearable />
+      </el-form-item>
+      <el-form-item :label="$t.value.paymentMethod">
+        <el-select v-model="queryForm.payment_method" clearable :placeholder="$t.value.pleaseSelect" style="width:140px">
+          <el-option label="现金" value="cash" />
+          <el-option label="免密" value="free" />
+        </el-select>
+      </el-form-item>
+      <el-form-item :label="$t.value.EntryTime">
+        <el-date-picker v-model="dateRange" type="daterange" start-placeholder="开始" end-placeholder="结束" value-format="YYYY-MM-DD" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="fetchList">{{ $t.value.Search }}</el-button>
+        <el-button @click="resetQuery">{{ $t.value.Reset }}</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-table :data="list" height="605" border>
+      <el-table-column :label="$t.value.licensePlate" prop="plate_number" align="center" width="120" />
+      <el-table-column :label="$t.value.paymentMethod" align="center" width="100">
+        <template #default="{ row }">
+          <el-tag :type="row.payment_method === 'cash' ? '' : 'success'">{{ row.payment_method === 'cash' ? '现金' : '免密' }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column :label="$t.value.Fee" prop="amount" align="center" width="100">
+        <template #default="{ row }">¥{{ row.amount.toFixed(2) }}</template>
+      </el-table-column>
+      <el-table-column label="实收" align="center" width="100">
+        <template #default="{ row }">¥{{ (row.paid_amount || 0).toFixed(2) }}</template>
+      </el-table-column>
+      <el-table-column label="找零" align="center" width="100">
+        <template #default="{ row }">¥{{ (row.change_amount || 0).toFixed(2) }}</template>
+      </el-table-column>
+      <el-table-column :label="$t.value.EntryTime" align="center" width="170">
+        <template #default="{ row }">{{ row.entry_time }}</template>
+      </el-table-column>
+      <el-table-column :label="$t.value.ExitTime" align="center" width="170">
+        <template #default="{ row }">{{ row.exit_time }}</template>
+      </el-table-column>
+      <el-table-column label="收款时间" align="center" width="170">
+        <template #default="{ row }">{{ row.paid_at }}</template>
+      </el-table-column>
+    </el-table>
+
+    <el-pagination
+      v-model:current-page="queryForm.page"
+      :page-size="queryForm.page_size"
+      :total="total"
+      layout="total, prev, pager, next"
+      style="margin-top:12px; justify-content:flex-end"
+      @current-change="fetchList"
+    />
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { getPaymentList } from '@/api/payment'
+
+const queryForm = reactive({ plate_number: '', payment_method: '', page: 1, page_size: 10, start_date: '', end_date: '' })
+const dateRange = ref([])
+const list = ref([])
+const total = ref(0)
+
+onMounted(() => fetchList())
+
+function fetchList() {
+  if (dateRange.value && dateRange.value.length === 2) {
+    queryForm.start_date = dateRange.value[0]
+    queryForm.end_date = dateRange.value[1]
+  } else {
+    queryForm.start_date = ''
+    queryForm.end_date = ''
+  }
+  getPaymentList(queryForm).then(res => {
+    if (res.code === 0) {
+      list.value = res.data.list || []
+      total.value = res.data.total || 0
+    }
+  })
+}
+
+function resetQuery() {
+  queryForm.plate_number = ''
+  queryForm.payment_method = ''
+  queryForm.page = 1
+  dateRange.value = []
+  fetchList()
+}
+</script>

+ 6 - 0
internal/initialize/seed.go

@@ -125,6 +125,7 @@ func SeedSystemData() {
 		{MenuLevel: 0, ParentId: 0, Path: "report", Name: "report", Hidden: false, Component: "", Sort: 3, Meta: dao.Meta{Title: "报表查询", Icon: "data-analysis"}},
 		{MenuLevel: 0, ParentId: 25, Path: "enter", Name: "enter", Hidden: false, Component: "view/report/enter.vue", Sort: 1, Meta: dao.Meta{Title: "进出记录", Icon: "sort"}},
 		{MenuLevel: 0, ParentId: 25, Path: "sheet", Name: "sheet", Hidden: false, Component: "view/report/sheet.vue", Sort: 2, Meta: dao.Meta{Title: "异常报表", Icon: "document-copy"}},
+		{MenuLevel: 0, ParentId: 25, Path: "paymentRecord", Name: "paymentRecord", Hidden: false, Component: "view/report/paymentRecord.vue", Sort: 3, Meta: dao.Meta{Title: "收费记录", Icon: "money"}},
 		// 统计查询 (ID=28)
 		{MenuLevel: 0, ParentId: 0, Path: "statistics", Name: "statistics", Hidden: false, Component: "", Sort: 4, Meta: dao.Meta{Title: "统计查询", Icon: "chat-line-round"}},
 		{MenuLevel: 0, ParentId: 28, Path: "vehicle", Name: "vehicle", Hidden: false, Component: "view/statistics/vehicle.vue", Sort: 1, Meta: dao.Meta{Title: "在线车辆统计", Icon: "van"}},
@@ -169,6 +170,8 @@ func SeedSystemData() {
 		{MenuId: "25", AuthorityId: "618"}, {MenuId: "25", AuthorityId: "888"}, {MenuId: "25", AuthorityId: "9527"},
 		{MenuId: "26", AuthorityId: "618"}, {MenuId: "26", AuthorityId: "888"}, {MenuId: "26", AuthorityId: "9527"},
 		{MenuId: "27", AuthorityId: "618"}, {MenuId: "27", AuthorityId: "888"}, {MenuId: "27", AuthorityId: "9527"},
+		// 收费记录 (32) — admin + operator
+		{MenuId: "32", AuthorityId: "618"}, {MenuId: "32", AuthorityId: "888"}, {MenuId: "32", AuthorityId: "9527"},
 		// 统计查询 + 子菜单 (28-29) — admin + operator
 		{MenuId: "28", AuthorityId: "618"}, {MenuId: "28", AuthorityId: "888"}, {MenuId: "28", AuthorityId: "9527"},
 		{MenuId: "29", AuthorityId: "618"}, {MenuId: "29", AuthorityId: "888"}, {MenuId: "29", AuthorityId: "9527"},
@@ -412,6 +415,9 @@ func SeedSystemData() {
 		{"p", "618", "/vehicle/exit/preview", "POST", "", "", ""},
 		{"p", "888", "/vehicle/exit/confirm", "POST", "", "", ""},
 		{"p", "618", "/vehicle/exit/confirm", "POST", "", "", ""},
+		// 收费记录查询
+		{"p", "888", "/payment/list", "GET", "", "", ""},
+		{"p", "618", "/payment/list", "GET", "", "", ""},
 	}
 	// Ensure casbin_rule table exists before seeding
 	db.Exec(`CREATE TABLE IF NOT EXISTS casbin_rule (