From f907866e56d795ff394e7d01dd4c5ffbce33dedd Mon Sep 17 00:00:00 2001
From: 董国庆 <364620639@qq.com>
Date: 星期三, 18 三月 2026 20:33:59 +0800
Subject: [PATCH] Merge branch 'main' of http://120.76.84.145:10101/gitblit/r/H5/xp-robotaxi-web

---
 src/views/service/ticket/feedback/index.vue                   |  154 ++++++++++++---------
 locales/en_US.json                                            |    2 
 src/assets/public/placeholder.png                             |    0 
 src/views/service/review/policyApplication/index.vue          |   31 +++-
 src/styles/robotaxi.scss                                      |    4 
 src/views/service/review/personnel/index.vue                  |   51 +++++--
 locales/zh_CN.json                                            |   35 ++++
 src/views/service/review/personnel/components/ReviewModal.vue |    2 
 src/views/service/ticket/feedbackType/index.vue               |  125 ++++++++---------
 9 files changed, 246 insertions(+), 158 deletions(-)

diff --git a/locales/en_US.json b/locales/en_US.json
index 396d92e..5909722 100644
--- a/locales/en_US.json
+++ b/locales/en_US.json
@@ -224,7 +224,7 @@
       "remark": "Remark",
       "chooseResult": "Please choose a result",
       "remarkRequired": "Please enter a remark",
-      "save": "Save",
+      "submit": "Submit",
       "validateFail": "Validation failed"
     },
     "policyApplication": {
diff --git a/locales/zh_CN.json b/locales/zh_CN.json
index 6a0fb1a..60629c7 100644
--- a/locales/zh_CN.json
+++ b/locales/zh_CN.json
@@ -15,6 +15,39 @@
     "expand": "展开",
     "collapse": "收起"
   },
+  "ticket": {
+    "feedback": {
+      "index": "序号",
+      "feedbackPerson": "反馈人",
+      "feedbackType": "反馈类型",
+      "feedbackContent": "反馈内容",
+      "image": "图片",
+      "contact": "联系方式",
+      "feedbackTime": "反馈时间",
+      "view": "查看",
+      "imagePreview": "图片预览"
+    },
+    "feedbackType": {
+      "index": "序号",
+      "feedbackType": "反馈类型",
+      "createTime": "创建时间",
+      "actions": "操作",
+      "add": "新增",
+      "edit": "编辑",
+      "delete": "删除",
+      "confirmDelete": "确认删除",
+      "confirmDeleteContent": "确定要删除该反馈类型吗?",
+      "addSuccess": "新增成功",
+      "addFail": "新增失败",
+      "editSuccess": "编辑成功",
+      "editFail": "编辑失败",
+      "deleteSuccess": "删除成功",
+      "deleteFail": "删除失败",
+      "inputPlaceholder": "请输入5个字以内",
+      "required": "请输入反馈类型",
+      "create": "新建"
+    }
+  },
   "app": {
     "loginOut": "退出登录",
     "loginOutTitle": "退出登录",
@@ -247,7 +280,7 @@
       "remark": "备注",
       "chooseResult": "请选择审核结果",
       "remarkRequired": "请输入备注",
-      "save": "保存",
+      "submit": "确定",
       "validateFail": "验证失败"
     },
     "policyApplication": {
diff --git a/src/assets/public/placeholder.png b/src/assets/public/placeholder.png
new file mode 100644
index 0000000..aca2635
--- /dev/null
+++ b/src/assets/public/placeholder.png
Binary files differ
diff --git a/src/styles/robotaxi.scss b/src/styles/robotaxi.scss
index c28a8d1..db5ea94 100644
--- a/src/styles/robotaxi.scss
+++ b/src/styles/robotaxi.scss
@@ -184,6 +184,10 @@
   }
 }
 
+.n-checkbox.n-checkbox--disabled .n-checkbox-box{
+  background-color: rgba(23, 31, 38, 0.15);
+}
+
 // 插槽样式-下拉框
 .arrow-icon {
   transition: transform 0.3s ease;
diff --git a/src/views/service/review/personnel/components/ReviewModal.vue b/src/views/service/review/personnel/components/ReviewModal.vue
index 23cbc4c..72b055d 100644
--- a/src/views/service/review/personnel/components/ReviewModal.vue
+++ b/src/views/service/review/personnel/components/ReviewModal.vue
@@ -121,7 +121,7 @@
       <n-space justify="end">
         <n-button @click="handleCancel">{{ t("common.cancel") }}</n-button>
         <n-button type="primary" @click="handleConfirm">
-          {{ t("serviceReview.common.save") }}
+          {{ t("serviceReview.common.submit") }}
         </n-button>
       </n-space>
     </template>
diff --git a/src/views/service/review/personnel/index.vue b/src/views/service/review/personnel/index.vue
index 6055511..9aeb0ea 100644
--- a/src/views/service/review/personnel/index.vue
+++ b/src/views/service/review/personnel/index.vue
@@ -1,7 +1,7 @@
 <script setup lang="tsx">
 import { onMounted, ref } from 'vue'
 import type { DataTableColumns } from 'naive-ui'
-import { NAvatar, NButton, NImage, NSpace, NTag, NTooltip } from 'naive-ui'
+import { NButton, NImage, NSpace, NTag, NTooltip } from 'naive-ui'
 import { useBoolean } from '@/hooks'
 import {
   auditQualification,
@@ -60,7 +60,7 @@
     resizable: true,
   },
   {
-    title: t('serviceReview.personnel.name'),
+    title: t('serviceReview.personnel.searchName'),
     key: 'nickName',
     width: 150,
     resizable: true,
@@ -68,11 +68,9 @@
       return (
         <div class="flex items-center gap-2">
           {row.avatar && <img src={JSON.parse(row.avatar).url} alt="头像" class="w-24px h-24px rounded-full" />}
-          {!row.avatar && (
-            <div class="w-24px h-24px rounded-full flex justify-center" style="background-color: #F6F7FA;">
-              <img src="/src/assets/public/avater.png" class="w-17px h-21px" />
-            </div>
-          )}
+          {!row.avatar && <div class="w-24px h-24px rounded-full flex justify-center" style="background-color: #F6F7FA;">
+            <img src="/src/assets/public/avater.png" class="w-17px h-21px" />
+            </div>}
           <NTooltip trigger="hover" placement="top" max-width="500px">
             {{
               trigger: () => <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap">{row.nickName}</div>,
@@ -86,7 +84,7 @@
   {
     title: t('serviceReview.personnel.id'),
     key: 'operationsUserId',
-    width: 100,
+    width: 60,
     resizable: true,
   },
   {
@@ -98,7 +96,7 @@
   {
     title: t('serviceReview.personnel.role'),
     key: 'roleNames',
-    width: 300,
+    width: 120,
     resizable: true,
     render: (row) => {
       return (
@@ -131,6 +129,7 @@
               src={idCardFront}
               objectFit="cover"
               previewSrc={idCardFront}
+              fallbackSrc="/src/assets/public/placeholder.png"
             />
             <NImage
               width={60}
@@ -138,6 +137,7 @@
               src={idCardBack}
               objectFit="cover"
               previewSrc={idCardBack}
+              fallbackSrc="/src/assets/public/placeholder.png"
             />
           </div>
         )
@@ -160,6 +160,7 @@
             src={driverLicense}
             objectFit="cover"
             previewSrc={driverLicense}
+            fallbackSrc="/src/assets/public/placeholder.png"
           />
         )
       }
@@ -183,6 +184,7 @@
             src={certificateOfNoCriminalRecord}
             objectFit="cover"
             previewSrc={certificateOfNoCriminalRecord}
+            fallbackSrc="/src/assets/public/placeholder.png"
           />
         )
       }
@@ -206,6 +208,7 @@
             src={trainingGraduationCertificate}
             objectFit="cover"
             previewSrc={trainingGraduationCertificate}
+            fallbackSrc="/src/assets/public/placeholder.png"
           />
         )
       }
@@ -215,7 +218,7 @@
   {
     title: t('serviceReview.personnel.status'),
     key: 'auditStatus',
-    width: 120,
+    width: 100,
     resizable: true,
     render: (row) => {
       const statusText = auditStatusLabelMap[row.auditStatus]
@@ -309,6 +312,7 @@
     content: t('serviceReview.common.deletePersonnelContent'),
     positiveText: t('common.confirm'),
     negativeText: t('common.cancel'),
+    positiveButtonProps: { type: "primary" },
     onPositiveClick: async () => {
       const res = await deleteQualificationAuditById(id)
       if (res.code === 200) {
@@ -444,22 +448,39 @@
       </n-form>
     </div>
 
-    <n-card class="flex-1 robotaxi-table-card">
+    <n-card
+      class="flex-1 robotaxi-table-card"
+      content-style="display: flex; flex-direction: column; flex: 1; min-height: 0; min-width: 0;"
+    >
       <template #header>
         <n-flex v-permission="80111">
-          <NButton strong @click="handleBatchReview">
-            {{ t("serviceReview.common.batchReview") }}
-          </NButton>
+          <n-tooltip trigger="hover" :disabled="selectedIds.length > 0">
+            <template #trigger>
+              <NButton
+                strong
+                @click="handleBatchReview"
+                :disabled="selectedIds.length === 0"
+              >
+                {{ t("serviceReview.common.batchReview") }}
+              </NButton>
+            </template>
+            勾选后可操作
+          </n-tooltip>
         </n-flex>
       </template>
 
-      <div class="flex-1 flex flex-col h-full">
+      <div
+        class="flex-1 flex flex-col h-full"
+        style="min-width: 0; overflow: hidden"
+      >
         <NDataTable
           class="flex-1"
           flex-height
           :columns="columns"
           :data="tableData"
           :loading="loading"
+          :scroll-x="1470"
+          :bordered="false"
           :row-key="(row: any) => row.id"
           @update:checked-row-keys="handleCheck"
         />
diff --git a/src/views/service/review/policyApplication/index.vue b/src/views/service/review/policyApplication/index.vue
index 30325d2..47fd94e 100644
--- a/src/views/service/review/policyApplication/index.vue
+++ b/src/views/service/review/policyApplication/index.vue
@@ -183,7 +183,7 @@
     fixed: "right",
     render: (row) => {
       return (
-        <div class="flex items-center justify-center gap-2">
+        <div class="flex items-center gap-2">
           {row.auditStatus === 1 ? (
             <NButton
               v-permission="80122"
@@ -238,6 +238,7 @@
     content: t("serviceReview.common.deletePolicyContent"),
     positiveText: t("common.confirm"),
     negativeText: t("common.cancel"),
+    positiveButtonProps: { type: "primary" },
     onPositiveClick: async () => {
       const res = await deletePolicyApplicationById(id);
       if (res.code === 200) {
@@ -360,23 +361,39 @@
       </n-form>
     </div>
 
-    <n-card class="flex-1 robotaxi-table-card">
+    <n-card
+      class="flex-1 robotaxi-table-card"
+      content-style="display: flex; flex-direction: column; flex: 1; min-height: 0; min-width: 0;"
+    >
       <template #header>
         <n-flex v-permission="80111">
-          <NButton strong @click="handleBatchReview">
-            {{t("serviceReview.common.batchReview")}}
-          </NButton>
+          <n-tooltip trigger="hover" :disabled="selectedIds.length > 0">
+            <template #trigger>
+              <NButton
+                strong
+                @click="handleBatchReview"
+                :disabled="selectedIds.length === 0"
+              >
+                {{ t("serviceReview.common.batchReview") }}
+              </NButton>
+            </template>
+            勾选后可操作
+          </n-tooltip>
         </n-flex>
       </template>
 
-      <div class="flex-1 flex flex-col h-full">
+      <div
+        class="flex-1 flex flex-col h-full"
+        style="min-width: 0; overflow: hidden"
+      >
         <n-data-table
           class="flex-1"
           flex-height
           :columns="columns"
           :data="tableData"
           :loading="loading"
-          :scroll-x="1500"
+          :scroll-x="1470"
+          :bordered="false"
           :row-key="(row: any) => row.id"
           @update:checked-row-keys="handleCheck"
         />
diff --git a/src/views/service/ticket/feedback/index.vue b/src/views/service/ticket/feedback/index.vue
index ae4cb30..fdff827 100644
--- a/src/views/service/ticket/feedback/index.vue
+++ b/src/views/service/ticket/feedback/index.vue
@@ -1,5 +1,6 @@
-<script setup lang="ts">
-import { ref, h, onMounted } from "vue";
+<script setup lang="tsx">
+import { ref, h, onMounted, computed } from "vue";
+import { useI18n } from "vue-i18n";
 import type { DataTableColumns } from "naive-ui";
 import {
   NButton,
@@ -7,9 +8,13 @@
   NImageGroup,
   NModal,
   NSpace,
-  NAvatar,
+  NTooltip,
 } from "naive-ui";
 import { useBoolean } from "@/hooks";
+
+const { t } = useI18n();
+
+
 import { fetchFeedbackPageList } from "@/service/api/serviceCenter";
 
 const {
@@ -66,12 +71,12 @@
   return normalizeImages(row.feedbackPictures);
 }
 
-const columns: DataTableColumns<FeedbackItem> = [
+const columns = computed<DataTableColumns<any>>(() => [
   {
-    title: "序号",
+    title: t("ticket.feedback.index"),
     key: "index",
     width: 80,
-    align: "center",
+    resizable: true,
     render: (_row, index) =>
       h(
         "span",
@@ -79,44 +84,46 @@
       ),
   },
   {
-    title: "反馈人",
+    title: t("ticket.feedback.feedbackPerson"),
     key: "nickName",
     width: 120,
-    align: "center",
+    resizable: true,
     render: (row) => {
-      const displayName = row.nickName || "-";
-      return h("div", { class: "flex items-center justify-center gap-2" }, [
-        h(
-          NAvatar,
-          {
-            round: true,
-            size: 32,
-            style: { backgroundColor: "#e0e0e0" },
-            src: row.avatar || undefined,
-          },
-          { default: () => displayName.charAt(0) }
-        ),
-        h("span", displayName),
-      ]);
+      return (
+        <div class="flex items-center gap-2">
+          {row.avatar && <img src={JSON.parse(row.avatar).url} alt="头像" class="w-24px h-24px rounded-full" />}
+          {!row.avatar && <div class="w-24px h-24px rounded-full flex justify-center" style="background-color: #F6F7FA;">
+            <img src="/src/assets/public/avater.png" class="w-17px h-21px" />
+            </div>}
+          <NTooltip trigger="hover" placement="top" max-width="500px">
+            {{
+              trigger: () => <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap">{row.nickName}</div>,
+              default: () => row.nickName,
+            }}
+          </NTooltip>
+        </div>
+      )
     },
   },
   {
-    title: "反馈类型",
+    title: t("ticket.feedback.feedbackType"),
     key: "feedbackTypeName",
-    width: 120,
-    align: "center",
+    width: 140,
+    resizable: true,
+    render: (row) => row.feedbackTypeName || "-",
   },
   {
-    title: "反馈内容",
+    title: t("ticket.feedback.feedbackContent"),
     key: "feedbackContent",
-    minWidth: 200,
-    align: "center",
+    minWidth: 600,
+    resizable: true,
+    render: (row) => row.feedbackContent || "-",
   },
   {
-    title: "图片",
+    title: t("ticket.feedback.image"),
     key: "feedbackPictures",
-    width: 120,
-    align: "center",
+    width: 70,
+    resizable: true,
     render: (row) => {
       const images = getImages(row);
       if (!images.length) return h("span", "-");
@@ -127,23 +134,25 @@
           type: "primary",
           onClick: () => handleViewImages(images),
         },
-        { default: () => "查看" }
+        { default: () => t("ticket.feedback.view") }
       );
     },
   },
   {
-    title: "联系方式",
+    title: t("ticket.feedback.contact"),
     key: "phoneNumber",
     width: 140,
-    align: "center",
+    resizable: true,
+    render: (row) => row.phoneNumber || "-",
   },
   {
-    title: "反馈时间",
+    title: t("ticket.feedback.feedbackTime"),
     key: "createTime",
     width: 160,
-    align: "center",
+    resizable: true,
+    render: (row) => row.createTime || "-",
   },
-];
+]);
 
 const handleSearch = () => {
   pagination.value.page = 1;
@@ -190,68 +199,75 @@
 onMounted(() => {
   getFeedbackList();
 });
+
+const filterItems = computed(() => [
+  {
+    label: t('ticket.feedback.feedbackContent'),
+    path: 'feedbackContent',
+    render: () => <n-input v-model:value={searchForm.value.feedbackContent} placeholder={t('common.inputPlaceholder')} />,
+  }
+])
 </script>
 
 <template>
-  <div class="h-full flex flex-col">
-    <n-card style="border-radius: 6px" content-style="padding: 12px">
+  <div class="roboTaxi">
+    <div ref="formRef" class="roboTaxi-form-card mb-12px">
       <n-form
         :model="searchForm"
         label-placement="left"
         inline
         :show-feedback="false"
       >
-        <div class="flex justify-between items-center w-full">
-          <div class="flex gap-4">
-            <n-form-item label="反馈内容">
-              <n-input
-                v-model:value="searchForm.feedbackContent"
-                placeholder="请输入"
-                clearable
-                style="width: 200px"
-              />
+        <SearchPanel>
+          <n-gi v-for="item in filterItems" :key="item.path">
+            <n-form-item :label="item.label" :path="item.path">
+              <component :is="item.render" />
             </n-form-item>
-          </div>
-          <div class="flex gap-2">
-            <n-button style="width: 84px; height: 32px" @click="handleReset"
-              >重置</n-button
-            >
-            <n-button
-              type="primary"
-              style="width: 84px; height: 32px"
-              @click="handleSearch"
-              >查询</n-button
-            >
-          </div>
-        </div>
+          </n-gi>
+          <template #action>
+            <NButton strong @click="handleReset">
+              {{ $t("common.reset") }}
+            </NButton>
+            <NButton type="primary" @click="handleSearch">
+              {{ $t("common.search") }}
+            </NButton>
+          </template>
+        </SearchPanel>
       </n-form>
-    </n-card>
+    </div>
 
     <n-card
-      style="border-radius: 6px; margin-top: 12px"
-      content-style="padding: 12px"
+      class="flex-1 robotaxi-table-card"
+      content-style="display: flex; flex-direction: column; flex: 1; min-height: 0; min-width: 0;"
     >
-      <NSpace vertical>
+      <div
+        class="flex-1 flex flex-col h-full"
+        style="min-width: 0; overflow: hidden"
+      >
         <n-data-table
+          class="flex-1"
+          flex-height
           :columns="columns"
           :data="tableData"
           :loading="loading"
-          :scroll-x="1200"
-          :row-key="(row: FeedbackItem) => row.id"
+          :scroll-x="1410"
+          :bordered="false"
+          :row-key="(row: any) => row.id"
         />
         <Pagination
           :count="count"
           :page="pagination.page"
           :page-size="pagination.pageSize"
+          class="robotaxi-pagination mt-12px"
           @change="changePage"
         />
-      </NSpace>
+      </div>
     </n-card>
 
     <n-modal
       v-model:show="previewVisible"
       preset="card"
-      title="图片预览"
+      :title="$t('ticket.feedback.imagePreview')"
       :style="{ width: '720px' }"
       :bordered="false"
       :segmented="{ content: true, action: true }"
diff --git a/src/views/service/ticket/feedbackType/index.vue b/src/views/service/ticket/feedbackType/index.vue
index 99d4f70..f0a996e 100644
--- a/src/views/service/ticket/feedbackType/index.vue
+++ b/src/views/service/ticket/feedbackType/index.vue
@@ -1,8 +1,12 @@
 <script setup lang="tsx">
 import { ref, h, computed, onMounted } from "vue";
+import { useI18n } from "vue-i18n";
 import type { DataTableColumns, FormInst, FormRules } from "naive-ui";
 import { NButton } from "naive-ui";
 import { useBoolean } from "@/hooks";
+
+const { t } = useI18n();
+
 import {
   fetchFeedbackTypeList,
   saveFeedbackType,
@@ -29,64 +33,62 @@
   feedbackType: "",
 });
 
-const rules: FormRules = {
-  feedbackType: [{ required: true, message: "请输入反馈类型", trigger: "blur" }],
-};
+const rules = computed<FormRules>(() => ({
+  feedbackType: [{ required: true, message: t("ticket.feedbackType.required"), trigger: "blur" }],
+}));
 
 const modalTitle = computed(() =>
-  modalMode.value === "add" ? "新增" : "编辑"
+  modalMode.value === "add" ? t("ticket.feedbackType.create") : t("ticket.feedbackType.edit")
 );
 
-const columns: DataTableColumns<any> = [
+const columns = computed<DataTableColumns<any>>(() => [
   {
-    title: "序号",
+    title: t("ticket.feedbackType.index"),
     key: "index",
-    width: 80,
-    align: "center",
+    width: 100,
+    resizable: true,
     render: (_row, index) => h("span", index + 1),
   },
   {
-    title: "反馈类型",
+    title: t("ticket.feedbackType.feedbackType"),
     key: "feedbackType",
-    minWidth: 200,
-    align: "center",
+    resizable: true,
   },
   {
-    title: "创建时间",
+    title: t("ticket.feedbackType.createTime"),
     key: "createTime",
-    width: 180,
-    align: "center",
+    width: 350,
+    resizable: true,
     render: (row) => row.createTime || "-",
   },
   {
-    title: "操作",
+    title: t("ticket.feedbackType.actions"),
     key: "actions",
-    width: 160,
-    align: "center",
+    width: 100,
     render: (row) => {
       return (
-        <div class="flex items-center justify-center gap-2">
+        <div class="flex items-center gap-2">
           <NButton
             v-permission="80232"
             text
             type="primary"
             onClick={() => handleEdit(row)}
           >
-            编辑
+            {t("ticket.feedbackType.edit")}
           </NButton>
           <NButton
             v-permission="8023"
             text
-            type="error"
+            type="primary"
             onClick={() => handleDelete(row)}
           >
-            删除
+            {t("ticket.feedbackType.delete")}
           </NButton>
         </div>
       );
     },
   },
-];
+]);
 
 function handleAdd() {
   modalMode.value = "add";
@@ -112,11 +114,11 @@
   if (modalMode.value === "add") {
     const res = await saveFeedbackType(payload);
     if (res.code === 200) {
-      window.$message?.success("新增成功");
+      window.$message?.success(t("ticket.feedbackType.addSuccess"));
       modalVisible.value = false;
       getFeedbackTypeList();
     } else {
-      window.$message?.error("新增失败");
+      window.$message?.error(t("ticket.feedbackType.addFail"));
     }
     return;
   }
@@ -125,27 +127,28 @@
     ...payload,
   });
   if (res.code === 200) {
-    window.$message?.success("编辑成功");
+    window.$message?.success(t("ticket.feedbackType.editSuccess"));
     modalVisible.value = false;
     getFeedbackTypeList();
   } else {
-    window.$message?.error("编辑失败");
+    window.$message?.error(t("ticket.feedbackType.editFail"));
   }
 }
 
 function handleDelete(row: FeedbackTypeItem) {
   window.$dialog?.warning({
-    title: "确认删除",
-    content: "确定要删除该反馈类型吗?",
-    positiveText: "确定",
-    negativeText: "取消",
+    title: t("ticket.feedbackType.confirmDelete"),
+    content: t("ticket.feedbackType.confirmDeleteContent"),
+    positiveText: t("common.confirm"),
+    negativeText: t("common.cancel"),
+    positiveButtonProps: { type: "primary" },
     onPositiveClick: async () => {
       const res = await deleteFeedbackType(row.id);
       if (res.code === 200) {
-        window.$message?.success("删除成功");
+        window.$message?.success(t("ticket.feedbackType.deleteSuccess"));
         getFeedbackTypeList();
       } else {
-        window.$message?.error("删除失败");
+        window.$message?.error(t("ticket.feedbackType.deleteFail"));
       }
     },
   });
@@ -174,37 +177,31 @@
 onMounted(() => {
   getFeedbackTypeList();
 });
+
 </script>
 
 <template>
-  <div class="h-full flex flex-col">
-    <n-card
-      style="border-radius: 6px; margin-top: 12px"
-      content-style="padding: 12px"
-    >
-      <div class="mb-4 flex justify-end gap-2">
-        <n-button
-          v-permission="80221"
-          style="
-            width: 84px;
-            height: 32px;
-            color: #0068ff;
-            background-color: #e6f4ff;
-            border: 1px solid #7abdff;
-          "
-          @click="handleAdd"
-          >新增</n-button
-        >
-      </div>
+  <div class="roboTaxi">
+    <n-card class="flex-1">
+      <template #header>
+        <n-flex justify="flex-end" v-permission="80221">
+          <n-button type="primary" secondary @click="handleAdd">{{ $t("ticket.feedbackType.add") }}</n-button>
+        </n-flex>
+      </template>
 
-      <n-data-table
-        :columns="columns"
-        :data="tableData"
-        :loading="loading"
-        :pagination="false"
-        :scroll-x="800"
-        :row-key="(row: FeedbackTypeItem) => row.id"
-      />
+      <div
+        class="flex-1 flex flex-col h-full"
+        style="min-width: 0; overflow: hidden"
+      >
+        <n-data-table
+          :columns="columns"
+          :data="tableData"
+          :loading="loading"
+          :pagination="false"
+          :bordered="false"
+          :row-key="(row: FeedbackTypeItem) => row.id"
+        />
+      </div>
     </n-card>
 
     <n-modal
@@ -219,14 +216,14 @@
         ref="formRef"
         :model="formModel"
         :rules="rules"
-        label-placement="left"
+        label-placement="top"
         label-width="80"
         require-mark-placement="left"
       >
-        <n-form-item label="反馈类型" path="feedbackType">
+        <n-form-item :label="$t('ticket.feedbackType.feedbackType')" path="feedbackType">
           <n-input
             v-model:value="formModel.feedbackType"
-            placeholder="请输入5个字以内"
+            :placeholder="$t('ticket.feedbackType.inputPlaceholder')"
             clearable
             maxlength="5"
           />
@@ -235,8 +232,8 @@
 
       <template #action>
         <n-space justify="end">
-          <n-button @click="handleClose">取消</n-button>
-          <n-button type="primary" @click="handleSave">保存</n-button>
+          <n-button @click="handleClose">{{ $t("common.cancel") }}</n-button>
+          <n-button type="primary" @click="handleSave">{{ $t("common.confirm") }}</n-button>
         </n-space>
       </template>
     </n-modal>

--
Gitblit v1.7.1