Explorar o código

feat: 优化细节

叶静 hai 3 semanas
pai
achega
351ddd0241

+ 156 - 152
src/app/shop/admin/content/sms/index.vue

@@ -3,12 +3,8 @@
     <el-header class="sa-header">
       <!-- 简化搜索组件 -->
       <div class="search-container">
-        <sa-search-simple
-          :searchFields="searchFields"
-          :defaultValues="defaultSearchValues"
-          @search="(val) => getData(1, val)"
-          @reset="getData(1)"
-        >
+        <sa-search-simple :searchFields="searchFields" :defaultValues="defaultSearchValues"
+          v-model="currentSearchParams" @search="handleSearch" @reset="handleReset">
         </sa-search-simple>
       </div>
       <div class="sa-title sa-flex sa-row-between">
@@ -21,15 +17,8 @@
     </el-header>
     <el-main class="sa-p-0">
       <div class="sa-table-wrap panel-block panel-block--bottom" v-loading="loading">
-        <el-table
-          height="100%"
-          class="sa-table"
-          :data="table.data"
-          @selection-change="changeSelection"
-          @sort-change="fieldFilter"
-          row-key="id"
-          stripe
-        >
+        <el-table height="100%" class="sa-table" :data="table.data" @selection-change="changeSelection"
+          @sort-change="fieldFilter" row-key="id" stripe>
           <template #empty>
             <sa-empty />
           </template>
@@ -77,13 +66,8 @@
           <el-table-column fixed="right" label="操作" min-width="120">
             <template #default="scope">
               <el-button class="is-link" type="primary" @click="editRow(scope.row)">编辑</el-button>
-              <el-popconfirm
-                width="fit-content"
-                confirm-button-text="确认"
-                cancel-button-text="取消"
-                title="确认删除这条记录?"
-                @confirm="deleteApi(scope.row.id)"
-              >
+              <el-popconfirm width="fit-content" confirm-button-text="确认" cancel-button-text="取消" title="确认删除这条记录?"
+                @confirm="deleteApi(scope.row.id)">
                 <template #reference>
                   <el-button class="is-link" type="danger"> 删除 </el-button>
                 </template>
@@ -95,11 +79,8 @@
     </el-main>
     <sa-view-bar>
       <template #left>
-        <sa-batch-handle
-          :batchHandleTools="batchHandleTools"
-          :selectedLeng="table.selected.length"
-          @batchHandle="batchHandle"
-        ></sa-batch-handle>
+        <sa-batch-handle :batchHandleTools="batchHandleTools" :selectedLeng="table.selected.length"
+          @batchHandle="batchHandle"></sa-batch-handle>
       </template>
       <template #right>
         <sa-pagination :pageData="pageData" @updateFn="getData" />
@@ -108,141 +89,164 @@
   </el-container>
 </template>
 <script setup>
-  import { onMounted, reactive, ref } from 'vue';
-  import { api } from '../content.service';
-  import { ElMessageBox } from 'element-plus';
-  import { useModal } from '@/sheep/hooks';
-  import { usePagination } from '@/sheep/hooks';
-  import smsEdit from './edit.vue';
-  const { pageData } = usePagination();
+import { onMounted, reactive, ref } from 'vue';
+import { api } from '../content.service';
+import { ElMessageBox } from 'element-plus';
+import { useModal } from '@/sheep/hooks';
+import { usePagination } from '@/sheep/hooks';
+import smsEdit from './edit.vue';
+const { pageData } = usePagination();
 
-  // 搜索字段配置
-  const searchFields = reactive({
-    name: {
-      type: 'input',
-      label: '模板名称',
-      placeholder: '请输入模板名称',
-      width: 200,
-    },
-  });
-  // 默认搜索值
-  const defaultSearchValues = reactive({
-    name: '',
-  });
-  // 列表
-  const table = reactive({
-    data: [],
-    order: '',
-    sort: '',
-    selected: [],
+// 搜索字段配置
+const searchFields = reactive({
+  name: {
+    type: 'input',
+    label: '模板名称',
+    placeholder: '请输入模板名称',
+    width: 200,
+  },
+});
+// 默认搜索值
+const defaultSearchValues = reactive({
+  name: '',
+});
+
+// 当前搜索条件 - 使用 ref 支持双向绑定
+const currentSearchParams = ref({});
+// 列表
+const table = reactive({
+  data: [],
+  order: '',
+  sort: '',
+  selected: [],
+});
+const loading = ref(true);
+// 获取
+async function getData(page, searchParams = null) {
+  if (page) pageData.page = page;
+  loading.value = true;
+
+  // 构建请求参数 - 优先使用传入的参数,否则使用双向绑定的搜索条件
+  const finalSearchParams = searchParams !== null ? searchParams : currentSearchParams.value;
+
+  const { code, data } = await api.list({
+    page: pageData.page,
+    size: pageData.size,
+    order: table.order,
+    ...finalSearchParams,
+    sort: table.sort,
   });
-  const loading = ref(true);
-  // 获取
-  async function getData(page, searchParams = {}) {
-    if (page) pageData.page = page;
-    loading.value = true;
-    const { code, data } = await api.list({
-      page: pageData.page,
-      size: pageData.size,
-      order: table.order,
-      ...searchParams,
-      sort: table.sort,
-    });
-    console.log('API 响应:', error, data);
-    if (code == 200) {
-      table.data = data.data;
-      pageData.page = data.current_page;
-      pageData.size = data.per_page;
-      pageData.total = data.total;
-    }
-    loading.value = false;
-  }
-  // table 字段排序
-  function fieldFilter({ prop, order }) {
-    table.order = order == 'ascending' ? 'asc' : 'desc';
-    table.sort = prop;
-    getData();
+  console.log('API 响应:', error, data);
+  if (code == 200) {
+    table.data = data.data;
+    pageData.page = data.current_page;
+    pageData.size = data.per_page;
+    pageData.total = data.total;
   }
-  //table批量选择
-  function changeSelection(row) {
-    table.selected = row;
-  }
-  // 分页/批量操作
-  const batchHandleTools = [
+  loading.value = false;
+}
+
+// 搜索处理函数
+function handleSearch(searchParams) {
+  // 由于使用了 v-model,currentSearchParams 会自动更新
+  // 直接调用 getData,会自动使用当前的搜索条件
+  getData(1);
+}
+
+// 重置搜索参数处理函数
+function handleReset() {
+  // 手动清空搜索参数
+  currentSearchParams.value = {};
+  // 传递空参数重新请求数据
+  getData(1, {});
+}
+// table 字段排序
+function fieldFilter({ prop, order }) {
+  table.order = order == 'ascending' ? 'asc' : 'desc';
+  table.sort = prop;
+  getData();
+}
+//table批量选择
+function changeSelection(row) {
+  table.selected = row;
+}
+// 分页/批量操作
+const batchHandleTools = [
+  {
+    type: 'delete',
+    label: '删除',
+    auth: 'shop.admin.content.sms.delete',
+    class: 'danger',
+  },
+];
+function addRow() {
+  useModal(
+    smsEdit,
+    { title: '新建短信模板', type: 'add' },
     {
-      type: 'delete',
-      label: '删除',
-      auth: 'shop.admin.content.sms.delete',
-      class: 'danger',
-    },
-  ];
-  function addRow() {
-    useModal(
-      smsEdit,
-      { title: '新建短信模板', type: 'add' },
-      {
-        confirm: () => {
-          getData();
-        },
-      },
-    );
-  }
-  function editRow(row) {
-    useModal(
-      smsEdit,
-      {
-        title: '编辑短信模板',
-        type: 'edit',
-        id: row.id,
-      },
-      {
-        confirm: () => {
-          getData();
-        },
+      confirm: () => {
+        getData();
       },
-    );
-  }
-  // 删除api 单独批量可以直接调用
-  async function deleteApi(id) {
-    await api.delete(id);
-    getData();
-  }
-  async function batchHandle(type) {
-    let ids = [];
-    table.selected.forEach((row) => {
-      ids.push(row.id);
-    });
-    switch (type) {
-      case 'delete':
-        ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning',
-        }).then(() => {
-          deleteApi(ids.join(','));
-        });
-        break;
-      default:
-        await api.edit(ids.join(','), {
-          status: type,
-        });
+    },
+  );
+}
+function editRow(row) {
+  useModal(
+    smsEdit,
+    {
+      title: '编辑短信模板',
+      type: 'edit',
+      id: row.id,
+    },
+    {
+      confirm: () => {
         getData();
-    }
+      },
+    },
+  );
+}
+// 删除api 单独批量可以直接调用
+async function deleteApi(id) {
+  await api.delete(id);
+  getData();
+}
+async function batchHandle(type) {
+  let ids = [];
+  table.selected.forEach((row) => {
+    ids.push(row.id);
+  });
+  switch (type) {
+    case 'delete':
+      ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+      }).then(() => {
+        deleteApi(ids.join(','));
+      });
+      break;
+    default:
+      await api.edit(ids.join(','), {
+        status: type,
+      });
+      getData();
   }
+}
 
-  onMounted(() => {
-    getData();
-  });
+onMounted(() => {
+  getData();
+});
 </script>
 <style lang="scss" scoped>
-  .sms-view {
-    .el-header {
-      height: auto;
-    }
-    .el-main {
-      .sa-table-wrap {
-        height: 100%;
-      }
+.sms-view {
+  .el-header {
+    height: auto;
+  }
+
+  .el-main {
+    .sa-table-wrap {
+      height: 100%;
     }
   }
+}
 </style>

+ 0 - 1
src/app/shop/admin/data/report/components/dataDisplayEdit.vue

@@ -75,7 +75,6 @@ import { useI18n } from 'vue-i18n';
 import { useFormConfig } from '@/hooks/useFormConfig';
 import { api } from '../../data.service.js';
 import ReportChart from './report-chart.vue';
-import dsDetailData from '../dsDetail.json'
 
 // 使用国际化
 const { t } = useI18n();

+ 0 - 1
src/app/shop/admin/data/report/index.vue

@@ -144,7 +144,6 @@ import dataDisplayEdit from './components/dataDisplayEdit.vue';
 import dashboardEdit from './components/dashboardEdit.vue';
 import chartEdit from './components/chartEdit.vue';
 import reportChart from './components/report-chart.vue';
-import detailData from './detail.json';
 
 // 使用国际化
 const { t } = useI18n();

+ 16 - 15
src/app/shop/admin/finance/commission/index.vue

@@ -3,8 +3,8 @@
     <el-header class="sa-header">
       <!-- 简化搜索组件 -->
       <div class="search-container">
-        <sa-search-simple :searchFields="searchFields" :defaultValues="defaultSearchValues" @search="handleSearch"
-          @reset="handleReset">
+        <sa-search-simple :searchFields="searchFields" :defaultValues="defaultSearchValues"
+          v-model="currentSearchParams" @search="handleSearch" @reset="handleReset">
         </sa-search-simple>
       </div>
       <div class="sa-title sa-flex sa-row-between">
@@ -170,18 +170,17 @@ const exportLoading = ref(false);
 
 // 搜索处理函数
 function handleSearch(searchParams) {
-  // 保存当前搜索参数
-  currentSearchParams.value = { ...searchParams };
-  // 执行搜索
-  getData(1, searchParams);
+  // 由于使用了 v-model,currentSearchParams 会自动更新
+  // 直接调用 getData,会自动使用当前的搜索条件
+  getData(1);
 }
 
 // 重置搜索参数处理函数
 function handleReset() {
-  // 清空当前搜索参数
+  // 手动清空搜索参数
   currentSearchParams.value = {};
-  // 执行重置
-  getData(1);
+  // 传递空参数重新请求数据
+  getData(1, {});
 }
 
 // 列表
@@ -229,22 +228,24 @@ async function getCommissionTypes() {
 }
 
 // 获取数据
-async function getData(page, searchParams = {}) {
+async function getData(page, searchParams = null) {
   if (page) pageData.page = page;
   loading.value = true;
 
   try {
-    // 构建请求参数
+    // 构建请求参数 - 优先使用传入的参数,否则使用双向绑定的搜索条件
+    const finalSearchParams = searchParams !== null ? searchParams : currentSearchParams.value;
+
     let params = {
       page: pageData.page,
       size: pageData.size,
-      ...searchParams,
+      ...finalSearchParams,
     };
 
     // 处理日期范围
-    if (searchParams.date_range && searchParams.date_range.length === 2) {
-      params.startTime = searchParams.date_range[0];
-      params.endTime = searchParams.date_range[1];
+    if (finalSearchParams.date_range && finalSearchParams.date_range.length === 2) {
+      params.startTime = finalSearchParams.date_range[0];
+      params.endTime = finalSearchParams.date_range[1];
       delete params.date_range;
     }
 

+ 5 - 6
src/app/shop/admin/finance/recharge/index.vue

@@ -3,8 +3,8 @@
     <el-header class="sa-header">
       <!-- 简化搜索组件 -->
       <div class="search-container">
-        <sa-search-simple :searchFields="searchFields" :defaultValues="defaultSearchValues" @search="handleSearch"
-          @reset="handleReset">
+        <sa-search-simple :searchFields="searchFields" :defaultValues="defaultSearchValues"
+          v-model="currentSearchParams" @search="handleSearch" @reset="handleReset">
         </sa-search-simple>
       </div>
       <!-- 状态Tab切换 -->
@@ -247,8 +247,7 @@ const handleTabChange = (status) => {
 
 // 搜索处理
 const handleSearch = (searchParams) => {
-  currentSearchParams.value = searchParams;
-
+  // 由于使用了 v-model,currentSearchParams 会自动更新
   // 获取当前tab的状态参数
   let statusParams = {};
   if (currentStatus.value !== 'all') {
@@ -256,14 +255,14 @@ const handleSearch = (searchParams) => {
   }
 
   // 整合搜索条件和状态筛选
-  const allParams = { ...searchParams, ...statusParams };
+  const allParams = { ...currentSearchParams.value, ...statusParams };
   getData(1, allParams);
 };
 
 // 重置处理
 const handleReset = () => {
+  // 手动清空搜索参数
   currentSearchParams.value = {};
-
   // 获取当前tab的状态参数
   let statusParams = {};
   if (currentStatus.value !== 'all') {

+ 26 - 8
src/app/shop/admin/finance/report/index.vue

@@ -4,7 +4,7 @@
       <!-- 简化搜索组件 -->
       <div class="search-container">
         <sa-search-simple :searchFields="searchFields" :defaultValues="defaultSearchValues"
-          @search="(val) => getData(1, val)" @reset="refreshData">
+          v-model="currentSearchParams" @search="handleSearch" @reset="handleReset">
           <template #custom="{ data }">
             <el-form-item label="">
               <el-date-picker v-model="data.createTime" type="daterange" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
@@ -241,17 +241,20 @@ function fieldFilter({ prop, order }) {
 }
 
 // 获取数据
-async function getData(page = 1, searchParams = {}) {
+async function getData(page = 1, searchParams = null) {
+  // 构建请求参数 - 优先使用传入的参数,否则使用双向绑定的搜索条件
+  const finalSearchParams = searchParams !== null ? searchParams : currentSearchParams.value;
+
   // 保存搜索条件供导出使用
-  if (Object.keys(searchParams).length > 0) {
-    currentSearchParams.value = { ...searchParams };
+  if (Object.keys(finalSearchParams).length > 0) {
+    currentSearchParams.value = { ...finalSearchParams };
   }
   loading.value = true;
 
   try {
     // 构建请求参数
     const params = {
-      ...searchParams,
+      ...finalSearchParams,
     };
 
     // 添加排序参数
@@ -261,9 +264,9 @@ async function getData(page = 1, searchParams = {}) {
     }
 
     // 处理时间范围搜索,直接使用年月日格式
-    if (searchParams.createTime && searchParams.createTime.length === 2) {
-      params.startTime = searchParams.createTime[0];
-      params.endTime = searchParams.createTime[1];
+    if (finalSearchParams.createTime && finalSearchParams.createTime.length === 2) {
+      params.startTime = finalSearchParams.createTime[0];
+      params.endTime = finalSearchParams.createTime[1];
       delete params.createTime;
     }
 
@@ -280,6 +283,21 @@ async function getData(page = 1, searchParams = {}) {
   }
 }
 
+// 搜索处理函数
+function handleSearch(searchParams) {
+  // 由于使用了 v-model,currentSearchParams 会自动更新
+  // 直接调用 getData,会自动使用当前的搜索条件
+  getData(1);
+}
+
+// 重置搜索参数处理函数
+function handleReset() {
+  // 手动清空搜索参数
+  currentSearchParams.value = {};
+  // 使用默认时间范围刷新数据
+  refreshData();
+}
+
 // 导出报表
 async function exportReport() {
   if (exportLoading.value) return; // 防止重复点击

+ 4 - 5
src/app/shop/admin/finance/withdraw/index.vue

@@ -4,7 +4,7 @@
       <!-- 简化搜索组件 -->
       <div class="search-container">
         <sa-search-simple key="withdraw-search" :searchFields="searchFields" :defaultValues="defaultSearchValues"
-          @search="handleSearch" @reset="handleReset" />
+          v-model="currentSearchParams" @search="handleSearch" @reset="handleReset" />
       </div>
       <!-- 状态Tab切换 -->
       <el-tabs class="sa-tabs" v-model="currentStatus" @tab-change="handleTabChange">
@@ -267,8 +267,7 @@ const handleTabChange = (status) => {
 
 // 搜索处理
 const handleSearch = (searchParams) => {
-  currentSearchParams.value = searchParams;
-
+  // 由于使用了 v-model,currentSearchParams 会自动更新
   // 获取当前tab的状态参数
   let statusParams = {};
   if (currentStatus.value !== 'all') {
@@ -276,14 +275,14 @@ const handleSearch = (searchParams) => {
   }
 
   // 整合搜索条件和状态筛选
-  const allParams = { ...searchParams, ...statusParams };
+  const allParams = { ...currentSearchParams.value, ...statusParams };
   getData(1, allParams);
 };
 
 // 重置处理
 const handleReset = () => {
+  // 手动清空搜索参数
   currentSearchParams.value = {};
-
   // 获取当前tab的状态参数
   let statusParams = {};
   if (currentStatus.value !== 'all') {

+ 25 - 3
src/app/shop/admin/goods/category/index.vue

@@ -4,7 +4,7 @@
       <!-- 简化搜索组件 -->
       <div class="search-container">
         <sa-search-simple :searchFields="searchFields" :defaultValues="defaultSearchValues"
-          @search="(val) => getData(1, val)" @reset="getData(1)">
+          v-model="currentSearchParams" @search="handleSearch" @reset="handleReset">
         </sa-search-simple>
       </div>
       <div class="sa-title sa-flex sa-row-between">
@@ -104,6 +104,9 @@ const searchFields = reactive({
 const defaultSearchValues = reactive({
   name: '',
 });
+
+// 当前搜索条件 - 使用 ref 支持双向绑定
+const currentSearchParams = ref({});
 // 列表
 const table = reactive({
   data: [],
@@ -113,13 +116,17 @@ const table = reactive({
 });
 const loading = ref(true);
 // 获取
-async function getData(page, searchParams = {}) {
+async function getData(page, searchParams = null) {
   if (page) pageData.page = page;
   loading.value = true;
+
+  // 构建请求参数 - 优先使用传入的参数,否则使用双向绑定的搜索条件
+  const finalSearchParams = searchParams !== null ? searchParams : currentSearchParams.value;
+
   const { code, data } = await api.category.list({
     page: pageData.page,
     size: pageData.size,
-    ...searchParams,
+    ...finalSearchParams,
   });
   if (code == 200) {
     table.data = data.list;
@@ -129,6 +136,21 @@ async function getData(page, searchParams = {}) {
   }
   loading.value = false;
 }
+
+// 搜索处理函数
+function handleSearch(searchParams) {
+  // 由于使用了 v-model,currentSearchParams 会自动更新
+  // 直接调用 getData,会自动使用当前的搜索条件
+  getData(1);
+}
+
+// 重置搜索参数处理函数
+function handleReset() {
+  // 手动清空搜索参数
+  currentSearchParams.value = {};
+  // 传递空参数重新请求数据
+  getData(1, {});
+}
 // table 字段排序
 function fieldFilter({ prop, order }) {
   table.order = order == 'ascending' ? 'asc' : 'desc';

+ 1 - 1
src/app/shop/admin/goods/goods/index.vue

@@ -229,7 +229,7 @@ const handleSearch = (searchParams) => {
 const handleReset = () => {
   // 由于使用了 v-model,currentSearchParams 会自动清空
   // 直接调用 getData,会自动使用当前的搜索条件和状态
-  getData(1);
+  getData(1, {});
 };
 
 // 获取状态数量

+ 24 - 3
src/app/shop/admin/goods/goods/select.vue

@@ -3,7 +3,7 @@
     <el-container>
       <el-header class="goods-search">
         <sa-search-simple :searchFields="searchFields" :defaultValues="defaultSearchValues"
-          @search="(val) => getData(1, val)" @reset="getData(1)" />
+          v-model="currentSearchParams" @search="handleSearch" @reset="handleReset" />
       </el-header>
       <el-main v-loading="loading">
         <el-table class="sa-table" ref="multipleTableRef" :data="table.list" @select="selectRow" @select-all="selectAll"
@@ -97,6 +97,9 @@ const defaultSearchValues = reactive({
   title: '',
 });
 
+// 当前搜索条件 - 使用 ref 支持双向绑定
+const currentSearchParams = ref({});
+
 const loading = ref(true);
 const table = reactive({
   list: [],
@@ -104,16 +107,19 @@ const table = reactive({
   selectedGoods: new Map(), // 使用Map存储选中的商品完整数据,key为商品id
   preloadedGoods: new Map(), // 存储预加载的商品数据
 });
-async function getData(page, searchParams = {}) {
+async function getData(page, searchParams = null) {
   if (page) pageData.page = page;
   loading.value = true;
 
   try {
+    // 构建请求参数 - 优先使用传入的参数,否则使用双向绑定的搜索条件
+    const finalSearchParams = searchParams !== null ? searchParams : currentSearchParams.value;
+
     const params = {
       page: pageData.page,
       size: pageData.size,
       isShow: 1,
-      ...searchParams,
+      ...finalSearchParams,
     };
     const { code, data } = await api.goods.list(params);
     if (code == '200') {
@@ -136,6 +142,21 @@ async function getData(page, searchParams = {}) {
   }
 }
 
+// 搜索处理函数
+function handleSearch(searchParams) {
+  // 由于使用了 v-model,currentSearchParams 会自动更新
+  // 直接调用 getData,会自动使用当前的搜索条件
+  getData(1);
+}
+
+// 重置搜索参数处理函数
+function handleReset() {
+  // 手动清空搜索参数
+  currentSearchParams.value = {};
+  // 传递空参数重新请求数据
+  getData(1, {});
+}
+
 // 设置默认选中
 function setDefaultSelected() {
   // 确保 table.list 存在且为数组

+ 4 - 3
src/app/shop/admin/marketing/group/index.vue

@@ -251,9 +251,10 @@ const handleSearch = (searchParams) => {
 
 // 重置搜索
 const handleReset = () => {
-  // 由于使用了 v-model,currentSearchParams 会自动清空
-  // 直接调用 getData,会自动使用当前的搜索条件和状态
-  getData(1);
+  // 手动清空搜索参数
+  currentSearchParams.value = {};
+  // 传递空参数重新请求数据
+  getData(1, {});
 };
 // table 字段排序
 function fieldFilter({ prop, order }) {

+ 15 - 13
src/app/shop/admin/order/order/index.vue

@@ -232,19 +232,6 @@ const statusMap = {
   completed: { status: 8 }, // 订单完成:订单状态为8
 };
 
-// 搜索处理
-const handleSearch = (searchParams) => {
-  // 由于使用了 v-model,currentSearchParams 会自动更新
-  // 直接调用 getData,会自动使用当前的搜索条件和状态
-  getData(1);
-};
-
-// 重置处理
-const handleReset = () => {
-  // 由于使用了 v-model,currentSearchParams 会自动清空
-  // 直接调用 getData,会自动使用当前的搜索条件和状态
-  getData(1);
-};
 
 // 标签切换处理
 const handleTabChange = (status) => {
@@ -337,6 +324,21 @@ async function getData(page, searchParams = null) {
   }
 }
 
+// 搜索处理函数
+function handleSearch(searchParams) {
+  // 由于使用了 v-model,currentSearchParams 会自动更新
+  // 直接调用 getData,会自动使用当前的搜索条件
+  getData(1);
+}
+
+// 重置搜索参数处理函数
+function handleReset() {
+  // 手动清空搜索参数
+  currentSearchParams.value = {};
+  // 传递空参数重新请求数据
+  getData(1, {});
+}
+
 // table 字段排序
 function fieldFilter({ prop, order }) {
   table.order = order == 'ascending' ? 'asc' : 'desc';

+ 157 - 158
src/app/shop/admin/user/level/index.vue

@@ -3,12 +3,8 @@
     <el-header class="sa-header">
       <!-- 简化搜索组件 -->
       <div class="search-container">
-        <sa-search-simple
-          :searchFields="searchFields"
-          :defaultValues="defaultSearchValues"
-          @search="(val) => getData(1, val)"
-          @reset="getData(1)"
-        >
+        <sa-search-simple :searchFields="searchFields" :defaultValues="defaultSearchValues"
+          v-model="currentSearchParams" @search="handleSearch" @reset="handleReset">
         </sa-search-simple>
       </div>
       <div class="sa-title sa-flex sa-row-between">
@@ -21,15 +17,8 @@
     </el-header>
     <el-main class="sa-p-0">
       <div class="sa-table-wrap panel-block panel-block--bottom" v-loading="loading">
-        <el-table
-          height="100%"
-          class="sa-table"
-          :data="table.data"
-          @selection-change="changeSelection"
-          @sort-change="fieldFilter"
-          row-key="id"
-          stripe
-        >
+        <el-table height="100%" class="sa-table" :data="table.data" @selection-change="changeSelection"
+          @sort-change="fieldFilter" row-key="id" stripe>
           <template #empty>
             <sa-empty />
           </template>
@@ -45,12 +34,7 @@
           </el-table-column>
           <el-table-column label="等级图标" min-width="100">
             <template #default="scope">
-              <el-image
-                v-if="scope.row.icon"
-                :src="scope.row.icon"
-                style="width: 40px; height: 40px"
-                fit="cover"
-              />
+              <el-image v-if="scope.row.icon" :src="scope.row.icon" style="width: 40px; height: 40px" fit="cover" />
               <span v-else>-</span>
             </template>
           </el-table-column>
@@ -75,13 +59,8 @@
           <el-table-column fixed="right" label="操作" min-width="120">
             <template #default="scope">
               <el-button class="is-link" type="primary" @click="editRow(scope.row)">编辑</el-button>
-              <el-popconfirm
-                width="fit-content"
-                confirm-button-text="确认"
-                cancel-button-text="取消"
-                title="确认删除这条记录?"
-                @confirm="deleteApi(scope.row.id)"
-              >
+              <el-popconfirm width="fit-content" confirm-button-text="确认" cancel-button-text="取消" title="确认删除这条记录?"
+                @confirm="deleteApi(scope.row.id)">
                 <template #reference>
                   <el-button class="is-link" type="danger"> 删除 </el-button>
                 </template>
@@ -93,11 +72,8 @@
     </el-main>
     <sa-view-bar>
       <template #left>
-        <sa-batch-handle
-          :batchHandleTools="batchHandleTools"
-          :selectedLeng="table.selected.length"
-          @batchHandle="batchHandle"
-        ></sa-batch-handle>
+        <sa-batch-handle :batchHandleTools="batchHandleTools" :selectedLeng="table.selected.length"
+          @batchHandle="batchHandle"></sa-batch-handle>
       </template>
       <template #right>
         <sa-pagination :pageData="pageData" @updateFn="getData" />
@@ -106,141 +82,164 @@
   </el-container>
 </template>
 <script setup>
-  import { onMounted, reactive, ref } from 'vue';
-  import { api } from '../user.service';
-  import { ElMessageBox } from 'element-plus';
-  import { useModal } from '@/sheep/hooks';
-  import { usePagination } from '@/sheep/hooks';
-  import levelEdit from './edit.vue';
-  const { pageData } = usePagination();
+import { onMounted, reactive, ref } from 'vue';
+import { api } from '../user.service';
+import { ElMessageBox } from 'element-plus';
+import { useModal } from '@/sheep/hooks';
+import { usePagination } from '@/sheep/hooks';
+import levelEdit from './edit.vue';
+const { pageData } = usePagination();
 
-  // 搜索字段配置
-  const searchFields = reactive({
-    name: {
-      type: 'input',
-      label: '等级名称',
-      placeholder: '请输入等级名称',
-      width: 200,
-    },
-  });
-  // 默认搜索值
-  const defaultSearchValues = reactive({
-    name: '',
-  });
-  // 列表
-  const table = reactive({
-    data: [],
-    order: '',
-    sort: '',
-    selected: [],
+// 搜索字段配置
+const searchFields = reactive({
+  name: {
+    type: 'input',
+    label: '等级名称',
+    placeholder: '请输入等级名称',
+    width: 200,
+  },
+});
+// 默认搜索值
+const defaultSearchValues = reactive({
+  name: '',
+});
+
+// 当前搜索条件 - 使用 ref 支持双向绑定
+const currentSearchParams = ref({});
+// 列表
+const table = reactive({
+  data: [],
+  order: '',
+  sort: '',
+  selected: [],
+});
+const loading = ref(true);
+// 获取
+async function getData(page, searchParams = null) {
+  if (page) pageData.page = page;
+  loading.value = true;
+
+  // 构建请求参数 - 优先使用传入的参数,否则使用双向绑定的搜索条件
+  const finalSearchParams = searchParams !== null ? searchParams : currentSearchParams.value;
+
+  const { code, data } = await api.level.list({
+    page: pageData.page,
+    size: pageData.size,
+    order: table.order,
+    ...finalSearchParams,
+    sort: table.sort,
   });
-  const loading = ref(true);
-  // 获取
-  async function getData(page, searchParams = {}) {
-    if (page) pageData.page = page;
-    loading.value = true;
-    const { code, data } = await api.level.list({
-      page: pageData.page,
-      size: pageData.size,
-      order: table.order,
-      ...searchParams,
-      sort: table.sort,
-    });
-    console.log('API 响应:', error, data);
-    if (code == 200) {
-      table.data = data.data;
-      pageData.page = data.current_page;
-      pageData.size = data.per_page;
-      pageData.total = data.total;
-    }
-    loading.value = false;
-  }
-  // table 字段排序
-  function fieldFilter({ prop, order }) {
-    table.order = order == 'ascending' ? 'asc' : 'desc';
-    table.sort = prop;
-    getData();
+  console.log('API 响应:', error, data);
+  if (code == 200) {
+    table.data = data.data;
+    pageData.page = data.current_page;
+    pageData.size = data.per_page;
+    pageData.total = data.total;
   }
-  //table批量选择
-  function changeSelection(row) {
-    table.selected = row;
-  }
-  // 分页/批量操作
-  const batchHandleTools = [
+  loading.value = false;
+}
+
+// 搜索处理函数
+function handleSearch(searchParams) {
+  // 由于使用了 v-model,currentSearchParams 会自动更新
+  // 直接调用 getData,会自动使用当前的搜索条件
+  getData(1);
+}
+
+// 重置搜索参数处理函数
+function handleReset() {
+  // 手动清空搜索参数
+  currentSearchParams.value = {};
+  // 传递空参数重新请求数据
+  getData(1, {});
+}
+// table 字段排序
+function fieldFilter({ prop, order }) {
+  table.order = order == 'ascending' ? 'asc' : 'desc';
+  table.sort = prop;
+  getData();
+}
+//table批量选择
+function changeSelection(row) {
+  table.selected = row;
+}
+// 分页/批量操作
+const batchHandleTools = [
+  {
+    type: 'delete',
+    label: '删除',
+    auth: 'shop.admin.user.level.delete',
+    class: 'danger',
+  },
+];
+function addRow() {
+  useModal(
+    levelEdit,
+    { title: '新建等级', type: 'add' },
     {
-      type: 'delete',
-      label: '删除',
-      auth: 'shop.admin.user.level.delete',
-      class: 'danger',
-    },
-  ];
-  function addRow() {
-    useModal(
-      levelEdit,
-      { title: '新建等级', type: 'add' },
-      {
-        confirm: () => {
-          getData();
-        },
-      },
-    );
-  }
-  function editRow(row) {
-    useModal(
-      levelEdit,
-      {
-        title: '编辑等级',
-        type: 'edit',
-        id: row.id,
-      },
-      {
-        confirm: () => {
-          getData();
-        },
+      confirm: () => {
+        getData();
       },
-    );
-  }
-  // 删除api 单独批量可以直接调用
-  async function deleteApi(id) {
-    await api.level.delete(id);
-    getData();
-  }
-  async function batchHandle(type) {
-    let ids = [];
-    table.selected.forEach((row) => {
-      ids.push(row.id);
-    });
-    switch (type) {
-      case 'delete':
-        ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning',
-        }).then(() => {
-          deleteApi(ids.join(','));
-        });
-        break;
-      default:
-        await api.level.edit(ids.join(','), {
-          status: type,
-        });
+    },
+  );
+}
+function editRow(row) {
+  useModal(
+    levelEdit,
+    {
+      title: '编辑等级',
+      type: 'edit',
+      id: row.id,
+    },
+    {
+      confirm: () => {
         getData();
-    }
+      },
+    },
+  );
+}
+// 删除api 单独批量可以直接调用
+async function deleteApi(id) {
+  await api.level.delete(id);
+  getData();
+}
+async function batchHandle(type) {
+  let ids = [];
+  table.selected.forEach((row) => {
+    ids.push(row.id);
+  });
+  switch (type) {
+    case 'delete':
+      ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+      }).then(() => {
+        deleteApi(ids.join(','));
+      });
+      break;
+    default:
+      await api.level.edit(ids.join(','), {
+        status: type,
+      });
+      getData();
   }
+}
 
-  onMounted(() => {
-    getData();
-  });
+onMounted(() => {
+  getData();
+});
 </script>
 <style lang="scss" scoped>
-  .user-level-view {
-    .el-header {
-      height: auto;
-    }
-    .el-main {
-      .sa-table-wrap {
-        height: 100%;
-      }
+.user-level-view {
+  .el-header {
+    height: auto;
+  }
+
+  .el-main {
+    .sa-table-wrap {
+      height: 100%;
     }
   }
+}
 </style>

+ 1 - 1
src/app/shop/admin/user/list/index.vue

@@ -323,7 +323,7 @@ function handleSearch(searchParams) {
 function handleReset() {
   // 由于使用了 v-model,currentSearchParams 会自动清空
   // 直接调用 getData,会自动使用当前的搜索条件
-  getData(1);
+  getData(1, {});
 }
 
 // 导出用户数据

+ 4 - 3
src/app/shop/admin/user/tag/index.vue

@@ -221,9 +221,10 @@ const handleSearch = (searchParams) => {
 
 // 重置处理
 const handleReset = () => {
-  // 由于使用了 v-model,currentSearchParams 会自动清空
-  // 直接调用 getData,会自动使用当前的搜索条件
-  getData(1);
+  // 手动清空搜索参数
+  currentSearchParams.value = {};
+  // 传递空参数重新请求数据
+  getData(1, {});
 };
 
 onMounted(() => {

+ 49 - 54
src/sheep/components/sa-table/sa-pagination/index.global.vue

@@ -1,70 +1,65 @@
 <template>
-  <el-pagination
-    class="sa-pagination"
-    :small="small"
-    v-model:currentPage="pageData.page"
-    v-model:page-size="pageData.size"
-    :page-sizes="[10, 50, 100]"
-    :layout="layout"
-    :pager-count="5"
-    :total="pageData.total"
-    @size-change="changeSize"
-    @current-change="changeCurrent"
-  />
+  <el-pagination class="sa-pagination" :small="small" v-model:currentPage="pageData.page"
+    v-model:page-size="pageData.size" :page-sizes="[20, 50, 100]" :layout="layout" :pager-count="5"
+    :total="pageData.total" @size-change="changeSize" @current-change="changeCurrent" />
 </template>
 <script>
-  export default {
-    name: 'SaPagination',
-  };
+export default {
+  name: 'SaPagination',
+};
 </script>
 <script setup>
-  const emit = defineEmits(['updateFn']);
-  const props = defineProps({
-    pageData: {
-      type: Object,
-    },
-    small: {
-      type: Boolean,
-      default: false,
-    },
-    layout: {
-      type: String,
-      default: 'total, sizes, prev, pager, next, jumper',
-    },
-  });
+const emit = defineEmits(['updateFn']);
+const props = defineProps({
+  pageData: {
+    type: Object,
+  },
+  small: {
+    type: Boolean,
+    default: false,
+  },
+  layout: {
+    type: String,
+    default: 'total, sizes, prev, pager, next, jumper',
+  },
+});
 
-  function changeSize(size) {
-    props.pageData.size = size;
-    emit('updateFn');
-  }
-  function changeCurrent(page) {
-    props.pageData.page = page;
-    emit('updateFn');
-  }
+function changeSize(size) {
+  props.pageData.size = size;
+  emit('updateFn');
+}
+function changeCurrent(page) {
+  props.pageData.page = page;
+  emit('updateFn');
+}
 </script>
 
 <style lang="scss" scoped>
-  .sa-pagination {
-    padding: 0;
-    @media only screen and (max-width: 768px) {
-      &.el-pagination {
-        :deep() {
-          .el-pagination__jump {
-            display: none !important;
-          }
-          .el-pagination__sizes {
-            display: none !important;
-          }
-          .el-pager {
-            li {
-              display: none;
-              &.is-active {
-                display: flex;
-              }
+.sa-pagination {
+  padding: 0;
+
+  @media only screen and (max-width: 768px) {
+    &.el-pagination {
+      :deep() {
+        .el-pagination__jump {
+          display: none !important;
+        }
+
+        .el-pagination__sizes {
+          display: none !important;
+        }
+
+        .el-pager {
+          li {
+            display: none;
+
+            &.is-active {
+              display: flex;
             }
           }
         }
       }
     }
   }
+}
 </style>

+ 1 - 1
src/sheep/components/sa-table/sa-pagination/usePagination.js

@@ -3,7 +3,7 @@ import { reactive } from 'vue';
 const usePagination = () => {
   const pageData = reactive({
     page: 1,
-    size: 10,
+    size: 20,
     total: 0,
   });
   return { pageData };

+ 1 - 1
src/sheep/layouts/index.vue

@@ -12,7 +12,7 @@
             <taskbar />
           </div>
           <div class="app-layout__container">
-            <div class="app-layout__view" v-loading="appLayout.pageLoading">
+            <div class="app-layout__view pb-6px" v-loading="appLayout.pageLoading">
               <router-view v-slot="{ Component, route }">
                 <keep-alive :include="taskbarHistory">
                   <component :is="Component" :key="route.fullPath" />