Просмотр исходного кода

feat(admin): 列头排序增强 — 单列循环 + 多列组合排序

- SortMixin: 点击列头升序→降序→取消循环,点击其他列追加为次级排序
- sort.css: 新增 sort-index badge 样式(绿色升序/橙色降序)
- 9个管理页面列头直接显示排序序号badge
- Foods.vue: 清理重复方法定义
Sisyphus 1 месяц назад
Родитель
Сommit
79902e734f

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-2b9b7ca1f6705ae786e39206090940d9a9cd747f
+658d71cc13bdf5bac3938e95f20a533cba24e5da

+ 1 - 1
cfc-web/package.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "cfc-web",
   "name": "cfc-web",
-  "version": "1.0.1107",
+  "version": "1.0.1108",
   "private": true,
   "private": true,
   "scripts": {
   "scripts": {
     "dev": "vue-cli-service serve",
     "dev": "vue-cli-service serve",

+ 13 - 0
cfc-web/public/CHANGELOG-v1.0.md

@@ -4,6 +4,19 @@
 
 
 ---
 ---
 
 
+## v1.0.1108 (2026-08-17)
+
+### 新功能
+- 统一AI接口走Java后端,删除前端直连LangGraph
+
+### 其他
+- - 前端4个AI函数改为直连Java /api/ai/*路由
+- - 删除langgraphRequest适配层及LANGGRAPH_BASE_URL配置
+- - 后端:systemPoints/CF值命名统一,PointsService方法重命名为awardCfPoints/deductCfPoints/getCfPointsBalance
+- - 前端ProfileHeader.vue:系统积分改显示为CF值
+- 
+
+
 ## v1.0.1107 (2026-08-17)
 ## v1.0.1107 (2026-08-17)
 
 
 ### Bug 修复
 ### Bug 修复

+ 14 - 1
cfc-web/public/CHANGELOG.md

@@ -1,6 +1,6 @@
 # 更新日志
 # 更新日志
 
 
-> 当前版本: v1.0.1107
+> 当前版本: v1.0.1108
 
 
 ## 历史版本
 ## 历史版本
 
 
@@ -8,6 +8,19 @@
 
 
 ---
 ---
 
 
+## v1.0.1108 (2026-08-17)
+
+### 新功能
+- 统一AI接口走Java后端,删除前端直连LangGraph
+
+### 其他
+- - 前端4个AI函数改为直连Java /api/ai/*路由
+- - 删除langgraphRequest适配层及LANGGRAPH_BASE_URL配置
+- - 后端:systemPoints/CF值命名统一,PointsService方法重命名为awardCfPoints/deductCfPoints/getCfPointsBalance
+- - 前端ProfileHeader.vue:系统积分改显示为CF值
+- 
+
+
 ## v1.0.1107 (2026-08-17)
 ## v1.0.1107 (2026-08-17)
 
 
 ### Bug 修复
 ### Bug 修复

+ 27 - 0
cfc-web/src/assets/css/sort.css

@@ -4,6 +4,9 @@
   font-weight: 500;
   font-weight: 500;
   font-size: 12px;
   font-size: 12px;
   white-space: nowrap;
   white-space: nowrap;
+  display: inline-flex;
+  align-items: center;
+  gap: 3px;
 }
 }
 .sort-header:hover {
 .sort-header:hover {
   color: #409eff;
   color: #409eff;
@@ -12,6 +15,30 @@
   color: #409eff !important;
   color: #409eff !important;
   font-weight: 600;
   font-weight: 600;
 }
 }
+
+/* 多列排序序号 badge */
+.sort-index {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  min-width: 14px;
+  height: 14px;
+  padding: 0 4px;
+  border-radius: 7px;
+  background: #409eff;
+  color: #fff;
+  font-size: 10px;
+  font-weight: 600;
+  line-height: 1;
+  flex-shrink: 0;
+}
+.sort-index.sort-asc-badge {
+  background: #67c23a;
+}
+.sort-index.sort-desc-badge {
+  background: #e6a23c;
+}
+
 .sort-tag {
 .sort-tag {
   margin-left: 8px;
   margin-left: 8px;
   cursor: pointer;
   cursor: pointer;

+ 21 - 43
cfc-web/src/mixins/SortMixin.js

@@ -1,12 +1,18 @@
 /**
 /**
  * 通用多列排序 Mixin
  * 通用多列排序 Mixin
- * 用法:在页面 data() 中声明 sortableColumns,在 loadList() 中加入 sortParams,
- *       在 el-table-column 的 slot="header" 中调用 this.sortHeader(col)。
+ *
+ * 点击列头行为:
+ *   - 首次点击:升序 ↑
+ *   - 再次点击:降序 ↓
+ *   - 第三次点击:取消排序
+ *   - 点击其他列:追加为次级排序(多列排序)
+ *
+ * 用法:在页面 data() 中声明 sortableColumns,在 loadList() 中调用 applySortToParams(params)。
  */
  */
 export default {
 export default {
   data() {
   data() {
     return {
     return {
-      sortState: [],          // [{column, order:'asc'|'desc'}]
+      sortState: [], // [{column, order:'asc'|'desc'}]
     }
     }
   },
   },
   computed: {
   computed: {
@@ -20,19 +26,6 @@ export default {
     }
     }
   },
   },
   methods: {
   methods: {
-    /**
-     * 渲染排序列头 HTML 字符串(供 slot 内联使用)
-     * 用法: <span v-html="sortHeader('name')"></span>
-     */
-    sortHeader(col, label) {
-      const icon = this.sortIcon(col)
-      const cls = this.sortClass(col)
-      const safeCol = col.replace(/[."']/g, '')
-      return `<span class="sort-header ${cls}" `
-        + `onclick="window.__sortClick && window.__sortClick('${safeCol}', event)" `
-        + `ondblclick="window.__sortToggle && window.__sortToggle('${safeCol}')" `
-        + `>${label || col}${icon}</span>`
-    },
     sortClass(col) {
     sortClass(col) {
       const s = this.sortState.find(x => x.column === col)
       const s = this.sortState.find(x => x.column === col)
       if (!s) return ''
       if (!s) return ''
@@ -43,45 +36,30 @@ export default {
       if (!s) return ''
       if (!s) return ''
       return s.order === 'asc' ? ' ↑' : ' ↓'
       return s.order === 'asc' ? ' ↑' : ' ↓'
     },
     },
-    onSortClick(col, event) {
-      if (event.shiftKey) {
-        this.shiftAppendSort(col)
-      } else {
-        this.setPrimarySort(col)
-      }
-      if (typeof this.loadList === 'function') this.loadList()
-    },
-    onSortToggle(col) {
+    /** 返回当前列在 sortState 中的排序序号(从1开始),未排序返回 null */
+    sortIndex(col) {
       const idx = this.sortState.findIndex(s => s.column === col)
       const idx = this.sortState.findIndex(s => s.column === col)
-      if (idx >= 0) {
-        this.sortState[idx].order = this.sortState[idx].order === 'asc' ? 'desc' : 'asc'
-      } else {
-        this.sortState = [{ column: col, order: 'asc' }]
-      }
-      if (typeof this.loadList === 'function') this.loadList()
+      return idx >= 0 ? idx + 1 : null
     },
     },
-    setPrimarySort(col) {
+    onSortClick(col) {
       const idx = this.sortState.findIndex(s => s.column === col)
       const idx = this.sortState.findIndex(s => s.column === col)
       if (idx >= 0) {
       if (idx >= 0) {
-        const item = this.sortState.splice(idx, 1)[0]
-        this.sortState.unshift(item)
+        // 已在排序中:cycle asc → desc → remove
+        if (this.sortState[idx].order === 'asc') {
+          this.sortState[idx].order = 'desc'
+        } else {
+          this.sortState.splice(idx, 1)
+        }
       } else {
       } else {
-        this.sortState = [{ column: col, order: 'asc' }]
-      }
-    },
-    shiftAppendSort(col) {
-      const idx = this.sortState.findIndex(s => s.column === col)
-      if (idx >= 0) {
-        this.sortState[idx].order = this.sortState[idx].order === 'asc' ? 'desc' : 'asc'
-      } else if (this.sortState.length < 3) {
+        // 新列:追加到排序末尾(多列排序)
         this.sortState.push({ column: col, order: 'asc' })
         this.sortState.push({ column: col, order: 'asc' })
       }
       }
+      if (typeof this.loadList === 'function') this.loadList()
     },
     },
     clearSort() {
     clearSort() {
       this.sortState = []
       this.sortState = []
       if (typeof this.loadList === 'function') this.loadList()
       if (typeof this.loadList === 'function') this.loadList()
     },
     },
-    /** 将当前 sortState 注入到请求参数中 */
     applySortToParams(params) {
     applySortToParams(params) {
       if (this.sortState.length > 0) {
       if (this.sortState.length > 0) {
         params.sort = this.sortState
         params.sort = this.sortState

+ 2 - 2
cfc-web/src/views/Users.vue

@@ -70,7 +70,7 @@
         <el-table-column prop="id" label="ID" width="80"></el-table-column>
         <el-table-column prop="id" label="ID" width="80"></el-table-column>
         <el-table-column prop="nickname" label="昵称" width="150">
         <el-table-column prop="nickname" label="昵称" width="150">
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('nickname', $event)" @dblclick.stop="onSortToggle('nickname')">昵称{{ sortIcon('nickname') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('nickname', $event)" @dblclick.stop="onSortToggle('nickname')">昵称<span v-if="sortIndex('nickname') !== null" class="sort-index" :class="sortClass('nickname') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('nickname') }}</span>{{ sortIcon('nickname') }}</span>
 
 
           </template></el-table-column>
           </template></el-table-column>
         <el-table-column prop="realName" label="真实姓名" width="120"></el-table-column>
         <el-table-column prop="realName" label="真实姓名" width="120"></el-table-column>
@@ -94,7 +94,7 @@
             {{ formatDate(scope.row.createdAt) }}
             {{ formatDate(scope.row.createdAt) }}
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('createdAt', $event)" @dblclick.stop="onSortToggle('createdAt')">创建时间{{ sortIcon('createdAt') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('createdAt', $event)" @dblclick.stop="onSortToggle('createdAt')">创建时间<span v-if="sortIndex('createdAt') !== null" class="sort-index" :class="sortClass('createdAt') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('createdAt') }}</span>{{ sortIcon('createdAt') }}</span>
 
 
           </template></el-table-column>
           </template></el-table-column>
         <el-table-column label="操作" width="200" fixed="right">
         <el-table-column label="操作" width="200" fixed="right">

+ 1 - 1
cfc-web/src/views/admin/ArticleManage.vue

@@ -113,7 +113,7 @@
         </el-table-column>
         </el-table-column>
         <el-table-column prop="viewCount" label="阅读" width="70">
         <el-table-column prop="viewCount" label="阅读" width="70">
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('viewCount', $event)" @dblclick.stop="onSortToggle('viewCount')">阅读{{ sortIcon('viewCount') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('viewCount', $event)" @dblclick.stop="onSortToggle('viewCount')">阅读<span v-if="sortIndex('viewCount') !== null" class="sort-index" :class="sortClass('viewCount') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('viewCount') }}</span>{{ sortIcon('viewCount') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
 
 

+ 1 - 1
cfc-web/src/views/admin/CouponManagement.vue

@@ -25,7 +25,7 @@
         <el-table-column prop="id" label="ID" width="70" />
         <el-table-column prop="id" label="ID" width="70" />
         <el-table-column prop="name" label="名称" min-width="140" show-overflow-tooltip>
         <el-table-column prop="name" label="名称" min-width="140" show-overflow-tooltip>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('name', $event)" @dblclick.stop="onSortToggle('name')">名称{{ sortIcon('name') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('name', $event)" @dblclick.stop="onSortToggle('name')">名称<span v-if="sortIndex('name') !== null" class="sort-index" :class="sortClass('name') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('name') }}</span>{{ sortIcon('name') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
 
 

+ 15 - 98
cfc-web/src/views/admin/Foods.vue

@@ -57,7 +57,7 @@
             <span style="font-weight: 500;">{{ row.name }}</span>
             <span style="font-weight: 500;">{{ row.name }}</span>
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('name',$event)" @dblclick.stop="onSortToggle('name')">名称{{ sortIcon('name') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('name',$event)" @dblclick.stop="onSortToggle('name')">名称<span v-if="sortIndex('name') !== null" class="sort-index" :class="sortClass('name') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('name') }}</span>{{ sortIcon('name') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
         <el-table-column prop="category" label="分类" width="120" align="center" :class-name="sortClass('category')">
         <el-table-column prop="category" label="分类" width="120" align="center" :class-name="sortClass('category')">
@@ -67,7 +67,7 @@
             </el-tag>
             </el-tag>
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('category',$event)" @dblclick.stop="onSortToggle('category')">分类{{ sortIcon('category') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('category',$event)" @dblclick.stop="onSortToggle('category')">分类<span v-if="sortIndex('category') !== null" class="sort-index" :class="sortClass('category') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('category') }}</span>{{ sortIcon('category') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
         <el-table-column label="热量" width="100" align="right" :class-name="sortClass('calories')">
         <el-table-column label="热量" width="100" align="right" :class-name="sortClass('calories')">
@@ -76,7 +76,7 @@
             <span class="num-unit">kcal</span>
             <span class="num-unit">kcal</span>
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('calories',$event)" @dblclick.stop="onSortToggle('calories')">热量{{ sortIcon('calories') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('calories',$event)" @dblclick.stop="onSortToggle('calories')">热量<span v-if="sortIndex('calories') !== null" class="sort-index" :class="sortClass('calories') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('calories') }}</span>{{ sortIcon('calories') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
         <el-table-column label="蛋白质" width="90" align="right" :class-name="sortClass('protein')">
         <el-table-column label="蛋白质" width="90" align="right" :class-name="sortClass('protein')">
@@ -85,7 +85,7 @@
             <span class="num-unit">g</span>
             <span class="num-unit">g</span>
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('protein',$event)" @dblclick.stop="onSortToggle('protein')">蛋白{{ sortIcon('protein') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('protein',$event)" @dblclick.stop="onSortToggle('protein')">蛋白<span v-if="sortIndex('protein') !== null" class="sort-index" :class="sortClass('protein') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('protein') }}</span>{{ sortIcon('protein') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
         <el-table-column label="脂肪" width="80" align="right" :class-name="sortClass('fat')">
         <el-table-column label="脂肪" width="80" align="right" :class-name="sortClass('fat')">
@@ -94,7 +94,7 @@
             <span class="num-unit">g</span>
             <span class="num-unit">g</span>
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('fat',$event)" @dblclick.stop="onSortToggle('fat')">脂肪{{ sortIcon('fat') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('fat',$event)" @dblclick.stop="onSortToggle('fat')">脂肪<span v-if="sortIndex('fat') !== null" class="sort-index" :class="sortClass('fat') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('fat') }}</span>{{ sortIcon('fat') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
         <el-table-column label="碳水" width="80" align="right" :class-name="sortClass('carbs')">
         <el-table-column label="碳水" width="80" align="right" :class-name="sortClass('carbs')">
@@ -103,7 +103,7 @@
             <span class="num-unit">g</span>
             <span class="num-unit">g</span>
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('carbs',$event)" @dblclick.stop="onSortToggle('carbs')">碳水{{ sortIcon('carbs') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('carbs',$event)" @dblclick.stop="onSortToggle('carbs')">碳水<span v-if="sortIndex('carbs') !== null" class="sort-index" :class="sortClass('carbs') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('carbs') }}</span>{{ sortIcon('carbs') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
         <el-table-column label="膳食纤维" width="90" align="right" :class-name="sortClass('fiber')">
         <el-table-column label="膳食纤维" width="90" align="right" :class-name="sortClass('fiber')">
@@ -112,7 +112,7 @@
             <span class="num-unit">g</span>
             <span class="num-unit">g</span>
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('fiber',$event)" @dblclick.stop="onSortToggle('fiber')">纤维{{ sortIcon('fiber') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('fiber',$event)" @dblclick.stop="onSortToggle('fiber')">纤维<span v-if="sortIndex('fiber') !== null" class="sort-index" :class="sortClass('fiber') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('fiber') }}</span>{{ sortIcon('fiber') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
         <el-table-column label="能量(kJ)" width="90" align="right" :class-name="sortClass('energyKj')">
         <el-table-column label="能量(kJ)" width="90" align="right" :class-name="sortClass('energyKj')">
@@ -120,7 +120,7 @@
             <span class="num-val">{{ row.energyKj != null ? row.energyKj : '-' }}</span>
             <span class="num-val">{{ row.energyKj != null ? row.energyKj : '-' }}</span>
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('energyKj',$event)" @dblclick.stop="onSortToggle('energyKj')">能量{{ sortIcon('energyKj') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('energyKj',$event)" @dblclick.stop="onSortToggle('energyKj')">能量<span v-if="sortIndex('energyKj') !== null" class="sort-index" :class="sortClass('energyKj') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('energyKj') }}</span>{{ sortIcon('energyKj') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
         <el-table-column label="胆固醇" width="90" align="right" :class-name="sortClass('cholesterol')">
         <el-table-column label="胆固醇" width="90" align="right" :class-name="sortClass('cholesterol')">
@@ -129,7 +129,7 @@
             <span v-else>-</span>
             <span v-else>-</span>
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('cholesterol',$event)" @dblclick.stop="onSortToggle('cholesterol')">胆固醇{{ sortIcon('cholesterol') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('cholesterol',$event)" @dblclick.stop="onSortToggle('cholesterol')">胆固醇<span v-if="sortIndex('cholesterol') !== null" class="sort-index" :class="sortClass('cholesterol') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('cholesterol') }}</span>{{ sortIcon('cholesterol') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
         <el-table-column prop="status" label="状态" width="80" align="center" :class-name="sortClass('status')">
         <el-table-column prop="status" label="状态" width="80" align="center" :class-name="sortClass('status')">
@@ -139,7 +139,7 @@
             </el-tag>
             </el-tag>
           </template>
           </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('status',$event)" @dblclick.stop="onSortToggle('status')">状态{{ sortIcon('status') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('status',$event)" @dblclick.stop="onSortToggle('status')">状态<span v-if="sortIndex('status') !== null" class="sort-index" :class="sortClass('status') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('status') }}</span>{{ sortIcon('status') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>
         <el-table-column label="操作" width="180" fixed="right" align="center">
         <el-table-column label="操作" width="180" fixed="right" align="center">
@@ -369,100 +369,17 @@ export default {
       this.sortState = []
       this.sortState = []
       this.loadList()
       this.loadList()
     },
     },
-    sortClass(col) {
-      const s = this.sortState.find(x => x.column === col)
-      if (!s) return ''
-      return s.order === 'asc' ? 'sort-asc' : 'sort-desc'
-    },
-    sortIcon(col) {
-      const s = this.sortState.find(x => x.column === col)
-      if (!s) return ''
-      return s.order === 'asc' ? ' ↑' : ' ↓'
-    },
-    onSortClick(col, event) {
-      if (event.shiftKey) {
-        this.shiftAppendSort(col)
-      } else {
-        this.setPrimarySort(col)
-      }
-      this.loadList()
-    },
-    onSortToggle(col) {
-      const idx = this.sortState.findIndex(s => s.column === col)
-      if (idx >= 0) {
-        this.sortState[idx].order = this.sortState[idx].order === 'asc' ? 'desc' : 'asc'
-      } else {
-        this.sortState = [{ column: col, order: 'asc' }]
-      }
-      this.loadList()
-    },
-    setPrimarySort(col) {
-      const idx = this.sortState.findIndex(s => s.column === col)
-      if (idx >= 0) {
-        const item = this.sortState.splice(idx, 1)[0]
-        this.sortState.unshift(item)
-      } else {
-        this.sortState = [{ column: col, order: 'asc' }]
-      }
-    },
-    shiftAppendSort(col) {
-      const idx = this.sortState.findIndex(s => s.column === col)
-      if (idx >= 0) {
-        this.sortState[idx].order = this.sortState[idx].order === 'asc' ? 'desc' : 'asc'
-      } else if (this.sortState.length < 3) {
-        this.sortState.push({ column: col, order: 'asc' })
-      }
-    },
-    clearSort() {
-      this.sortState = []
-      this.loadList()
-    },
-    sortClass(col) {
-      const s = this.sortState.find(x => x.column === col)
-      if (!s) return ''
-      return s.order === 'asc' ? 'sort-asc' : 'sort-desc'
-    },
-    sortIcon(col) {
-      const s = this.sortState.find(x => x.column === col)
-      if (!s) return ''
-      return s.order === 'asc' ? ' \u2191' : ' \u2193'
-    },
     onSortClick(col, event) {
     onSortClick(col, event) {
-      if (event.shiftKey) {
-        this.shiftAppendSort(col)
-      } else {
-        this.setPrimarySort(col)
-      }
-      this.loadList()
-    },
-    onSortToggle(col) {
       const idx = this.sortState.findIndex(s => s.column === col)
       const idx = this.sortState.findIndex(s => s.column === col)
       if (idx >= 0) {
       if (idx >= 0) {
-        this.sortState[idx].order = this.sortState[idx].order === 'asc' ? 'desc' : 'asc'
-      } else {
-        this.sortState = [{ column: col, order: 'asc' }]
-      }
-      this.loadList()
-    },
-    setPrimarySort(col) {
-      const idx = this.sortState.findIndex(s => s.column === col)
-      if (idx >= 0) {
-        const item = this.sortState.splice(idx, 1)[0]
-        this.sortState.unshift(item)
+        if (this.sortState[idx].order === 'asc') {
+          this.sortState[idx].order = 'desc'
+        } else {
+          this.sortState.splice(idx, 1)
+        }
       } else {
       } else {
-        this.sortState = [{ column: col, order: 'asc' }]
-      }
-    },
-    shiftAppendSort(col) {
-      const idx = this.sortState.findIndex(s => s.column === col)
-      if (idx >= 0) {
-        this.sortState[idx].order = this.sortState[idx].order === 'asc' ? 'desc' : 'asc'
-      } else if (this.sortState.length < 3) {
         this.sortState.push({ column: col, order: 'asc' })
         this.sortState.push({ column: col, order: 'asc' })
       }
       }
-    },
-    clearSort() {
-      this.sortState = []
       this.loadList()
       this.loadList()
     },
     },
     handleSizeChange(val) {
     handleSizeChange(val) {

+ 1 - 1
cfc-web/src/views/admin/OrderManage.vue

@@ -34,7 +34,7 @@
       <el-table :max-height="tableHeight" :data="list" v-loading="loading" border stripe>
       <el-table :max-height="tableHeight" :data="list" v-loading="loading" border stripe>
       <el-table-column prop="orderNo" label="订单号" width="180">
       <el-table-column prop="orderNo" label="订单号" width="180">
         <template slot="header">
         <template slot="header">
-          <span class="sort-header" @click.stop="onSortClick('orderNo', $event)" @dblclick.stop="onSortToggle('orderNo')">订单号{{ sortIcon('orderNo') }}</span>
+          <span class="sort-header" @click.stop="onSortClick('orderNo', $event)" @dblclick.stop="onSortToggle('orderNo')">订单号<span v-if="sortIndex('orderNo') !== null" class="sort-index" :class="sortClass('orderNo') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('orderNo') }}</span>{{ sortIcon('orderNo') }}</span>
         </template>
         </template>
       </el-table-column>
       </el-table-column>
 
 

+ 3 - 3
cfc-web/src/views/admin/ProductManage.vue

@@ -51,7 +51,7 @@
       </el-table-column>
       </el-table-column>
       <el-table-column prop="name" label="商品名称" min-width="150" show-overflow-tooltip>
       <el-table-column prop="name" label="商品名称" min-width="150" show-overflow-tooltip>
         <template slot="header">
         <template slot="header">
-          <span class="sort-header" @click.stop="onSortClick('name', $event)" @dblclick.stop="onSortToggle('name')">商品名称{{ sortIcon('name') }}</span>
+          <span class="sort-header" @click.stop="onSortClick('name', $event)" @dblclick.stop="onSortToggle('name')">商品名称<span v-if="sortIndex('name') !== null" class="sort-index" :class="sortClass('name') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('name') }}</span>{{ sortIcon('name') }}</span>
         </template>
         </template>
       </el-table-column>
       </el-table-column>
 
 
@@ -75,7 +75,7 @@
       </el-table-column>
       </el-table-column>
       <el-table-column prop="salesCount" label="销量" width="70">
       <el-table-column prop="salesCount" label="销量" width="70">
         <template slot="header">
         <template slot="header">
-          <span class="sort-header" @click.stop="onSortClick('salesCount', $event)" @dblclick.stop="onSortToggle('salesCount')">销量{{ sortIcon('salesCount') }}</span>
+          <span class="sort-header" @click.stop="onSortClick('salesCount', $event)" @dblclick.stop="onSortToggle('salesCount')">销量<span v-if="sortIndex('salesCount') !== null" class="sort-index" :class="sortClass('salesCount') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('salesCount') }}</span>{{ sortIcon('salesCount') }}</span>
         </template>
         </template>
       </el-table-column>
       </el-table-column>
 
 
@@ -100,7 +100,7 @@
           {{ formatTime(row.createdAt) }}
           {{ formatTime(row.createdAt) }}
         </template>
         </template>
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('createdAt', $event)" @dblclick.stop="onSortToggle('createdAt')">创建时间{{ sortIcon('createdAt') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('createdAt', $event)" @dblclick.stop="onSortToggle('createdAt')">创建时间<span v-if="sortIndex('createdAt') !== null" class="sort-index" :class="sortClass('createdAt') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('createdAt') }}</span>{{ sortIcon('createdAt') }}</span>
 
 
           </template></el-table-column>
           </template></el-table-column>
       <el-table-column label="操作" width="200" fixed="right">
       <el-table-column label="操作" width="200" fixed="right">

+ 3 - 3
cfc-web/src/views/admin/ProductPpointManage.vue

@@ -28,7 +28,7 @@
       </el-table-column>
       </el-table-column>
       <el-table-column prop="productName" label="商品名称" min-width="160" show-overflow-tooltip>
       <el-table-column prop="productName" label="商品名称" min-width="160" show-overflow-tooltip>
         <template slot="header">
         <template slot="header">
-          <span class="sort-header" @click.stop="onSortClick('productName', $event)" @dblclick.stop="onSortToggle('productName')">商品名称{{ sortIcon('productName') }}</span>
+          <span class="sort-header" @click.stop="onSortClick('productName', $event)" @dblclick.stop="onSortToggle('productName')">商品名称<span v-if="sortIndex('productName') !== null" class="sort-index" :class="sortClass('productName') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('productName') }}</span>{{ sortIcon('productName') }}</span>
         </template>
         </template>
       </el-table-column>
       </el-table-column>
       <el-table-column prop="price" label="售价(元)" width="90">
       <el-table-column prop="price" label="售价(元)" width="90">
@@ -43,7 +43,7 @@
       </el-table-column>
       </el-table-column>
       <el-table-column label="P点基点(bps)" width="120">
       <el-table-column label="P点基点(bps)" width="120">
         <template slot="header">
         <template slot="header">
-          <span class="sort-header" @click.stop="onSortClick('ppoint', $event)" @dblclick.stop="onSortToggle('ppoint')">P点基点(bps){{ sortIcon('ppoint') }}</span>
+          <span class="sort-header" @click.stop="onSortClick('ppoint', $event)" @dblclick.stop="onSortToggle('ppoint')">P点基点(bps)<span v-if="sortIndex('ppoint') !== null" class="sort-index" :class="sortClass('ppoint') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('ppoint') }}</span>{{ sortIcon('ppoint') }}</span>
         </template>
         </template>
         <template slot-scope="{ row }">
         <template slot-scope="{ row }">
           <span v-if="editId !== row.id">{{ row.ppoint != null ? row.ppoint + ' bps' : '-' }}</span>
           <span v-if="editId !== row.id">{{ row.ppoint != null ? row.ppoint + ' bps' : '-' }}</span>
@@ -60,7 +60,7 @@
       </el-table-column>
       </el-table-column>
       <el-table-column label="生效日期" width="100">
       <el-table-column label="生效日期" width="100">
         <template slot="header">
         <template slot="header">
-          <span class="sort-header" @click.stop="onSortClick('startDate', $event)" @dblclick.stop="onSortToggle('startDate')">生效日期{{ sortIcon('startDate') }}</span>
+          <span class="sort-header" @click.stop="onSortClick('startDate', $event)" @dblclick.stop="onSortToggle('startDate')">生效日期<span v-if="sortIndex('startDate') !== null" class="sort-index" :class="sortClass('startDate') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('startDate') }}</span>{{ sortIcon('startDate') }}</span>
         </template>
         </template>
         <template slot-scope="{ row }">
         <template slot-scope="{ row }">
           {{ row.startDate || '-' }}
           {{ row.startDate || '-' }}

+ 1 - 1
cfc-web/src/views/admin/Recipes.vue

@@ -36,7 +36,7 @@
         <el-table-column prop="id" label="ID" width="80" />
         <el-table-column prop="id" label="ID" width="80" />
         <el-table-column prop="name" label="名称">
         <el-table-column prop="name" label="名称">
           <template slot="header">
           <template slot="header">
-            <span class="sort-header" @click.stop="onSortClick('name', $event)" @dblclick.stop="onSortToggle('name')">名称{{ sortIcon('name') }}</span>
+            <span class="sort-header" @click.stop="onSortClick('name', $event)" @dblclick.stop="onSortToggle('name')">名称<span v-if="sortIndex('name') !== null" class="sort-index" :class="sortClass('name') === 'sort-asc' ? 'sort-asc-badge' : 'sort-desc-badge'">{{ sortIndex('name') }}</span>{{ sortIcon('name') }}</span>
           </template>
           </template>
         </el-table-column>
         </el-table-column>