Commit b16a77521aec28a5bbdf37030edd3d845ed03773

Authored by “wangming”
1 parent 7f7044c5

修复所有确认工资条接口的XML注释,解决Swagger显示问题

- 将remarks中的```json代码块改为<code>标签(XML注释中不能使用```)
- 为所有缺少注释的接口添加了完整的summary和remarks
- 统一了所有9个工资服务确认接口的注释格式
- 包含示例请求、参数说明、注意事项等完整信息

修复的接口:
1. LqSalaryService (健康师)
2. LqTechTeacherSalaryService (科技部老师)
3. LqAssistantSalaryService (店助)
4. LqStoreManagerSalaryService (店长)
5. LqDirectorSalaryService (主任)
6. LqMajorProjectTeacherSalaryService (大项目老师)
7. LqMajorProjectDirectorSalaryService (大项目主管)
8. LqTechGeneralManagerSalaryService (科技部总经理)
9. LqBusinessUnitManagerSalaryService (事业部总经理)
antis-ncc-admin/src/views/statisticsList/form9.vue
... ... @@ -359,14 +359,16 @@
359 359 <el-card class="dashboard-card" shadow="hover">
360 360 <div slot="header" class="card-title">
361 361 <span><i class="el-icon-user"></i> 团队效能矩阵</span>
362   - <el-button-group style="float: right">
363   - <el-button size="mini" :type="coachRankType === 'billing' ? 'primary' : ''"
364   - @click="coachRankType = 'billing'">开单榜</el-button>
365   - <el-button size="mini" :type="coachRankType === 'consume' ? 'primary' : ''"
366   - @click="coachRankType = 'consume'">消耗榜</el-button>
367   - <el-button size="mini" :type="coachRankType === 'refund' ? 'primary' : ''"
368   - @click="coachRankType = 'refund'">客情警告</el-button>
369   - </el-button-group>
  362 + <div class="card-title-actions">
  363 + <el-button-group class="modern-button-group">
  364 + <el-button size="mini" :class="coachRankType === 'billing' ? 'active' : ''"
  365 + @click="coachRankType = 'billing'">开单榜</el-button>
  366 + <el-button size="mini" :class="coachRankType === 'consume' ? 'active' : ''"
  367 + @click="coachRankType = 'consume'">消耗榜</el-button>
  368 + <el-button size="mini" :class="coachRankType === 'refund' ? 'active' : ''"
  369 + @click="coachRankType = 'refund'">客情警告</el-button>
  370 + </el-button-group>
  371 + </div>
370 372 </div>
371 373 <el-table :data="coachRanking" size="mini" style="width: 100%">
372 374 <el-table-column type="index" label="排名" width="50"></el-table-column>
... ... @@ -1964,7 +1966,7 @@ export default {
1964 1966 <style lang="scss" scoped>
1965 1967 .leadership-cockpit {
1966 1968 padding: 16px;
1967   - background-color: #f5f7fa;
  1969 + background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 50%, #f0f4f8 100%);
1968 1970 min-height: 100vh;
1969 1971 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
1970 1972  
... ... @@ -1973,10 +1975,23 @@ export default {
1973 1975 justify-content: space-between;
1974 1976 align-items: center;
1975 1977 margin-bottom: 20px;
1976   - background: #fff;
  1978 + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
1977 1979 padding: 12px 20px;
1978   - border-radius: 8px;
1979   - box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
  1980 + border-radius: 12px;
  1981 + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04);
  1982 + border: 1px solid rgba(64, 158, 255, 0.1);
  1983 + position: relative;
  1984 + overflow: hidden;
  1985 +
  1986 + &::before {
  1987 + content: '';
  1988 + position: absolute;
  1989 + top: 0;
  1990 + left: 0;
  1991 + right: 0;
  1992 + height: 3px;
  1993 + background: linear-gradient(90deg, #409EFF 0%, #66b1ff 50%, #409EFF 100%);
  1994 + }
1980 1995  
1981 1996 .page-title {
1982 1997 margin: 0;
... ... @@ -2011,73 +2026,104 @@ export default {
2011 2026 }
2012 2027  
2013 2028 .kpi-card {
2014   - background: #fff;
  2029 + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
2015 2030 padding: 20px 10px;
2016   - border-radius: 8px;
  2031 + border-radius: 12px;
2017 2032 display: flex;
2018 2033 align-items: center;
2019 2034 position: relative;
2020 2035 overflow: hidden;
2021 2036 height: 100px;
2022   - box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.04);
2023   - transition: transform 0.3s;
  2037 + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04);
  2038 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
2024 2039 cursor: pointer;
  2040 + border: 1px solid rgba(64, 158, 255, 0.08);
  2041 +
  2042 + &::after {
  2043 + content: '';
  2044 + position: absolute;
  2045 + top: 0;
  2046 + left: 0;
  2047 + right: 0;
  2048 + height: 2px;
  2049 + background: linear-gradient(90deg, transparent 0%, rgba(64, 158, 255, 0.3) 50%, transparent 100%);
  2050 + opacity: 0;
  2051 + transition: opacity 0.3s;
  2052 + }
2025 2053  
2026 2054 &:hover {
2027 2055 transform: translateY(-4px);
  2056 + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.08);
  2057 + border-color: rgba(64, 158, 255, 0.2);
  2058 +
  2059 + &::after {
  2060 + opacity: 1;
  2061 + }
2028 2062 }
2029 2063  
2030 2064 &.primary {
2031 2065 border-left: 4px solid #409EFF;
  2066 + background: linear-gradient(135deg, #ffffff 0%, rgba(64, 158, 255, 0.03) 100%);
2032 2067  
2033 2068 .kpi-icon {
2034 2069 color: #409EFF;
2035   - background: rgba(64, 158, 255, 0.1);
  2070 + background: linear-gradient(135deg, rgba(64, 158, 255, 0.15) 0%, rgba(64, 158, 255, 0.08) 100%);
  2071 + box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
2036 2072 }
2037 2073 }
2038 2074  
2039 2075 &.success {
2040 2076 border-left: 4px solid #67C23A;
  2077 + background: linear-gradient(135deg, #ffffff 0%, rgba(103, 194, 58, 0.03) 100%);
2041 2078  
2042 2079 .kpi-icon {
2043 2080 color: #67C23A;
2044   - background: rgba(103, 194, 58, 0.1);
  2081 + background: linear-gradient(135deg, rgba(103, 194, 58, 0.15) 0%, rgba(103, 194, 58, 0.08) 100%);
  2082 + box-shadow: 0 2px 8px rgba(103, 194, 58, 0.2);
2045 2083 }
2046 2084 }
2047 2085  
2048 2086 &.warning {
2049 2087 border-left: 4px solid #E6A23C;
  2088 + background: linear-gradient(135deg, #ffffff 0%, rgba(230, 162, 60, 0.03) 100%);
2050 2089  
2051 2090 .kpi-icon {
2052 2091 color: #E6A23C;
2053   - background: rgba(230, 162, 60, 0.1);
  2092 + background: linear-gradient(135deg, rgba(230, 162, 60, 0.15) 0%, rgba(230, 162, 60, 0.08) 100%);
  2093 + box-shadow: 0 2px 8px rgba(230, 162, 60, 0.2);
2054 2094 }
2055 2095 }
2056 2096  
2057 2097 &.info {
2058 2098 border-left: 4px solid #909399;
  2099 + background: linear-gradient(135deg, #ffffff 0%, rgba(144, 147, 153, 0.03) 100%);
2059 2100  
2060 2101 .kpi-icon {
2061 2102 color: #909399;
2062   - background: rgba(144, 147, 153, 0.1);
  2103 + background: linear-gradient(135deg, rgba(144, 147, 153, 0.15) 0%, rgba(144, 147, 153, 0.08) 100%);
  2104 + box-shadow: 0 2px 8px rgba(144, 147, 153, 0.2);
2063 2105 }
2064 2106 }
2065 2107  
2066 2108 &.danger {
2067 2109 border-left: 4px solid #F56C6C;
  2110 + background: linear-gradient(135deg, #ffffff 0%, rgba(245, 108, 108, 0.03) 100%);
2068 2111  
2069 2112 .kpi-icon {
2070 2113 color: #F56C6C;
2071   - background: rgba(245, 108, 108, 0.1);
  2114 + background: linear-gradient(135deg, rgba(245, 108, 108, 0.15) 0%, rgba(245, 108, 108, 0.08) 100%);
  2115 + box-shadow: 0 2px 8px rgba(245, 108, 108, 0.2);
2072 2116 }
2073 2117 }
2074 2118  
2075 2119 &.error {
2076 2120 border-left: 4px solid #f5222d;
  2121 + background: linear-gradient(135deg, #ffffff 0%, rgba(245, 34, 45, 0.03) 100%);
2077 2122  
2078 2123 .kpi-icon {
2079 2124 color: #f5222d;
2080   - background: rgba(245, 34, 45, 0.1);
  2125 + background: linear-gradient(135deg, rgba(245, 34, 45, 0.15) 0%, rgba(245, 34, 45, 0.08) 100%);
  2126 + box-shadow: 0 2px 8px rgba(245, 34, 45, 0.2);
2081 2127 }
2082 2128 }
2083 2129  
... ... @@ -2122,23 +2168,116 @@ export default {
2122 2168  
2123 2169 /* Dashboard Cards */
2124 2170 .dashboard-card {
2125   - border: none;
2126   - border-radius: 8px;
  2171 + border: 1px solid rgba(64, 158, 255, 0.1);
  2172 + border-radius: 12px;
2127 2173 margin-bottom: 16px;
  2174 + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  2175 + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04);
  2176 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2177 + overflow: hidden;
2128 2178  
2129   - &::v-deep .el-card__header {
2130   - padding: 12px 20px;
2131   - border-bottom: 1px solid #f0f2f5;
  2179 + &:hover {
  2180 + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.08);
  2181 + transform: translateY(-2px);
  2182 + border-color: rgba(64, 158, 255, 0.2);
2132 2183 }
2133 2184  
  2185 + &::v-deep .el-card__header {
  2186 + padding: 12px 20px;
  2187 + border-bottom: 1px solid rgba(64, 158, 255, 0.1);
  2188 + background: linear-gradient(135deg, rgba(64, 158, 255, 0.05) 0%, rgba(64, 158, 255, 0.02) 100%);
  2189 + min-height: 48px;
  2190 + display: flex;
  2191 + align-items: center;
  2192 + }
  2193 +
2134 2194 .card-title {
2135 2195 font-size: 15px;
2136 2196 font-weight: 600;
2137 2197 color: #303133;
  2198 + display: flex;
  2199 + align-items: center;
  2200 + justify-content: space-between;
  2201 + width: 100%;
  2202 +
  2203 + > span {
  2204 + display: flex;
  2205 + align-items: center;
  2206 + }
2138 2207  
2139 2208 i {
2140 2209 color: #409EFF;
2141 2210 margin-right: 8px;
  2211 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2212 + }
  2213 +
  2214 + .card-title-actions {
  2215 + display: flex;
  2216 + align-items: center;
  2217 + margin-left: auto;
  2218 + }
  2219 + }
  2220 +
  2221 + &:hover .card-title i {
  2222 + transform: scale(1.1) rotate(5deg);
  2223 + }
  2224 +
  2225 + // 现代化按钮组样式
  2226 + &::v-deep .modern-button-group {
  2227 + border-radius: 8px;
  2228 + overflow: hidden;
  2229 + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  2230 + border: 1px solid rgba(64, 158, 255, 0.2);
  2231 + background: #ffffff;
  2232 +
  2233 + .el-button {
  2234 + border: none;
  2235 + border-radius: 0;
  2236 + margin: 0;
  2237 + padding: 6px 16px;
  2238 + font-size: 12px;
  2239 + font-weight: 500;
  2240 + color: #606266;
  2241 + background: #ffffff;
  2242 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2243 + position: relative;
  2244 +
  2245 + &:not(:last-child) {
  2246 + border-right: 1px solid rgba(64, 158, 255, 0.15);
  2247 + }
  2248 +
  2249 + &:hover {
  2250 + color: #409EFF;
  2251 + background: linear-gradient(135deg, rgba(64, 158, 255, 0.08) 0%, rgba(64, 158, 255, 0.05) 100%);
  2252 + transform: translateY(-1px);
  2253 + }
  2254 +
  2255 + &.active {
  2256 + color: #ffffff;
  2257 + background: linear-gradient(135deg, #409EFF 0%, #66b1ff 100%);
  2258 + box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
  2259 + font-weight: 600;
  2260 +
  2261 + &::after {
  2262 + content: '';
  2263 + position: absolute;
  2264 + bottom: 0;
  2265 + left: 0;
  2266 + right: 0;
  2267 + height: 2px;
  2268 + background: linear-gradient(90deg, #ffffff 0%, rgba(255, 255, 255, 0.8) 100%);
  2269 + }
  2270 + }
  2271 +
  2272 + &:first-child {
  2273 + border-top-left-radius: 8px;
  2274 + border-bottom-left-radius: 8px;
  2275 + }
  2276 +
  2277 + &:last-child {
  2278 + border-top-right-radius: 8px;
  2279 + border-bottom-right-radius: 8px;
  2280 + }
2142 2281 }
2143 2282 }
2144 2283 }
... ... @@ -2181,19 +2320,38 @@ export default {
2181 2320 }
2182 2321  
2183 2322 .member-stat-item {
2184   - background: #f5f7fa;
2185   - border-radius: 8px;
  2323 + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  2324 + border-radius: 12px;
2186 2325 padding: 16px 8px;
2187 2326 display: flex;
2188 2327 flex-direction: column;
2189   - transition: all 0.3s ease;
2190   - border: none;
2191   - box-shadow: none;
  2328 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2329 + border: 1px solid rgba(64, 158, 255, 0.1);
  2330 + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
2192 2331 height: 160px;
  2332 + position: relative;
  2333 + overflow: hidden;
  2334 +
  2335 + &::before {
  2336 + content: '';
  2337 + position: absolute;
  2338 + top: 0;
  2339 + left: 0;
  2340 + right: 0;
  2341 + height: 2px;
  2342 + background: linear-gradient(90deg, transparent 0%, rgba(64, 158, 255, 0.3) 50%, transparent 100%);
  2343 + opacity: 0;
  2344 + transition: opacity 0.3s;
  2345 + }
2193 2346  
2194 2347 &:hover {
2195   - box-shadow: 0 8px 20px rgba(31, 45, 61, 0.12);
  2348 + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.08);
2196 2349 transform: translateY(-2px);
  2350 + border-color: rgba(64, 158, 255, 0.2);
  2351 +
  2352 + &::before {
  2353 + opacity: 1;
  2354 + }
2197 2355 }
2198 2356  
2199 2357 .stat-main {
... ... @@ -2215,23 +2373,35 @@ export default {
2215 2373 }
2216 2374  
2217 2375 &.stat-item-1 .stat-icon {
2218   - background: rgba(64, 158, 255, 0.1);
  2376 + background: linear-gradient(135deg, rgba(64, 158, 255, 0.15) 0%, rgba(64, 158, 255, 0.08) 100%);
2219 2377 color: #409EFF;
  2378 + box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
  2379 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
2220 2380 }
2221 2381  
2222 2382 &.stat-item-2 .stat-icon {
2223   - background: rgba(103, 194, 58, 0.1);
  2383 + background: linear-gradient(135deg, rgba(103, 194, 58, 0.15) 0%, rgba(103, 194, 58, 0.08) 100%);
2224 2384 color: #67C23A;
  2385 + box-shadow: 0 2px 8px rgba(103, 194, 58, 0.2);
  2386 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
2225 2387 }
2226 2388  
2227 2389 &.stat-item-3 .stat-icon {
2228   - background: rgba(230, 162, 60, 0.1);
  2390 + background: linear-gradient(135deg, rgba(230, 162, 60, 0.15) 0%, rgba(230, 162, 60, 0.08) 100%);
2229 2391 color: #E6A23C;
  2392 + box-shadow: 0 2px 8px rgba(230, 162, 60, 0.2);
  2393 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
2230 2394 }
2231 2395  
2232 2396 &.stat-item-4 .stat-icon {
2233   - background: rgba(245, 108, 108, 0.1);
  2397 + background: linear-gradient(135deg, rgba(245, 108, 108, 0.15) 0%, rgba(245, 108, 108, 0.08) 100%);
2234 2398 color: #F56C6C;
  2399 + box-shadow: 0 2px 8px rgba(245, 108, 108, 0.2);
  2400 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2401 + }
  2402 +
  2403 + &:hover .stat-icon {
  2404 + transform: scale(1.05) rotate(5deg);
2235 2405 }
2236 2406  
2237 2407 .stat-content {
... ... @@ -2265,13 +2435,22 @@ export default {
2265 2435  
2266 2436 .stat-tag {
2267 2437 display: block;
2268   - background: #fff;
  2438 + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
2269 2439 border-radius: 12px;
2270 2440 padding: 6px 10px;
2271 2441 font-size: 12px;
2272 2442 font-weight: 500;
2273 2443 color: #303133;
2274 2444 overflow: hidden;
  2445 + border: 1px solid rgba(64, 158, 255, 0.08);
  2446 + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
  2447 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2448 +
  2449 + &:hover {
  2450 + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  2451 + transform: translateY(-1px);
  2452 + border-color: rgba(64, 158, 255, 0.15);
  2453 + }
2275 2454 }
2276 2455  
2277 2456 .stat-tag-inner {
... ... @@ -2352,8 +2531,10 @@ export default {
2352 2531 flex-direction: column;
2353 2532 gap: 12px;
2354 2533 padding: 12px;
2355   - background: #f5f7fa;
2356   - border-radius: 6px;
  2534 + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  2535 + border-radius: 12px;
  2536 + border: 1px solid rgba(64, 158, 255, 0.1);
  2537 + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
2357 2538 }
2358 2539  
2359 2540 .legend-item {
... ... @@ -2361,12 +2542,17 @@ export default {
2361 2542 align-items: center;
2362 2543 gap: 10px;
2363 2544 padding: 8px;
2364   - background: white;
2365   - border-radius: 4px;
2366   - transition: all 0.3s ease;
  2545 + background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  2546 + border-radius: 8px;
  2547 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2548 + border: 1px solid rgba(64, 158, 255, 0.08);
  2549 + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
2367 2550  
2368 2551 &:hover {
2369   - background: #f0f2f5;
  2552 + background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
  2553 + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  2554 + transform: translateX(4px);
  2555 + border-color: rgba(64, 158, 255, 0.2);
2370 2556 }
2371 2557 }
2372 2558  
... ... @@ -2432,23 +2618,136 @@ export default {
2432 2618 display: flex;
2433 2619 flex-direction: column;
2434 2620 overflow: hidden;
2435   - padding: 20px;
  2621 + padding: 16px 20px 12px 20px;
  2622 + min-height: 0;
2436 2623 }
2437 2624  
2438 2625 .rank-list {
2439 2626 flex: 1;
2440 2627 overflow-y: auto;
2441 2628 max-height: 100%;
  2629 + min-height: 0;
  2630 + padding-right: 4px;
  2631 +
  2632 + &::-webkit-scrollbar {
  2633 + width: 6px;
  2634 + }
  2635 +
  2636 + &::-webkit-scrollbar-track {
  2637 + background: rgba(240, 242, 245, 0.5);
  2638 + border-radius: 3px;
  2639 + }
  2640 +
  2641 + &::-webkit-scrollbar-thumb {
  2642 + background: linear-gradient(135deg, #c0c4cc 0%, #909399 100%);
  2643 + border-radius: 3px;
  2644 + transition: background 0.3s;
  2645 +
  2646 + &:hover {
  2647 + background: linear-gradient(135deg, #909399 0%, #606266 100%);
  2648 + }
  2649 + }
2442 2650 }
2443 2651  
2444 2652 &::v-deep .el-table {
2445 2653 flex: 1;
2446 2654 overflow: hidden;
  2655 + border-radius: 8px;
  2656 + border: 1px solid rgba(64, 158, 255, 0.1);
  2657 + }
  2658 +
  2659 + &::v-deep .el-table__header {
  2660 + th {
  2661 + background: linear-gradient(135deg, rgba(64, 158, 255, 0.08) 0%, rgba(64, 158, 255, 0.05) 100%);
  2662 + color: #303133;
  2663 + font-weight: 600;
  2664 + border-bottom: 1px dotted rgba(64, 158, 255, 0.15);
  2665 + padding: 12px 0;
  2666 + height: 48px;
  2667 + }
  2668 + }
  2669 +
  2670 + &::v-deep .el-table__body {
  2671 + tr {
  2672 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2673 +
  2674 + &:hover {
  2675 + background: linear-gradient(90deg, rgba(64, 158, 255, 0.05) 0%, rgba(64, 158, 255, 0.02) 100%) !important;
  2676 + transform: translateX(4px);
  2677 + }
  2678 + }
  2679 +
  2680 + td {
  2681 + border-bottom: 1px dotted rgba(64, 158, 255, 0.15);
  2682 + padding: 8px 0;
  2683 +
  2684 + &:first-child {
  2685 + .cell {
  2686 + display: flex;
  2687 + align-items: center;
  2688 + justify-content: center;
  2689 +
  2690 + span {
  2691 + display: inline-flex;
  2692 + align-items: center;
  2693 + justify-content: center;
  2694 + width: 20px;
  2695 + height: 20px;
  2696 + border-radius: 4px;
  2697 + background: linear-gradient(135deg, #909399 0%, #606266 100%);
  2698 + color: #fff;
  2699 + font-size: 11px;
  2700 + font-weight: 600;
  2701 + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
  2702 + }
  2703 + }
  2704 + }
  2705 + }
  2706 + }
  2707 +
  2708 + &::v-deep .el-table__row {
  2709 + &:last-child td {
  2710 + border-bottom: none;
  2711 + }
  2712 +
  2713 + // 前三名特殊样式
  2714 + &:nth-child(1) td:first-child .cell span {
  2715 + background: linear-gradient(135deg, #F56C6C 0%, #ff8080 100%);
  2716 + box-shadow: 0 1px 6px rgba(245, 108, 108, 0.3);
  2717 + }
  2718 +
  2719 + &:nth-child(2) td:first-child .cell span {
  2720 + background: linear-gradient(135deg, #E6A23C 0%, #f0b45a 100%);
  2721 + box-shadow: 0 1px 6px rgba(230, 162, 60, 0.3);
  2722 + }
  2723 +
  2724 + &:nth-child(3) td:first-child .cell span {
  2725 + background: linear-gradient(135deg, #409EFF 0%, #66b1ff 100%);
  2726 + box-shadow: 0 1px 6px rgba(64, 158, 255, 0.3);
  2727 + }
2447 2728 }
2448 2729  
2449 2730 &::v-deep .el-table__body-wrapper {
2450 2731 max-height: calc(100% - 40px);
2451 2732 overflow-y: auto;
  2733 +
  2734 + &::-webkit-scrollbar {
  2735 + width: 6px;
  2736 + }
  2737 +
  2738 + &::-webkit-scrollbar-track {
  2739 + background: rgba(240, 242, 245, 0.5);
  2740 + border-radius: 3px;
  2741 + }
  2742 +
  2743 + &::-webkit-scrollbar-thumb {
  2744 + background: linear-gradient(135deg, #c0c4cc 0%, #909399 100%);
  2745 + border-radius: 3px;
  2746 +
  2747 + &:hover {
  2748 + background: linear-gradient(135deg, #909399 0%, #606266 100%);
  2749 + }
  2750 + }
2452 2751 }
2453 2752 }
2454 2753 }
... ... @@ -2459,7 +2758,18 @@ export default {
2459 2758 display: flex;
2460 2759 align-items: center;
2461 2760 padding: 12px 0;
2462   - border-bottom: 1px dotted #EBEEF5;
  2761 + border-bottom: 1px dotted rgba(64, 158, 255, 0.15);
  2762 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2763 + border-radius: 4px;
  2764 + margin: 0;
  2765 +
  2766 + &:hover {
  2767 + background: linear-gradient(90deg, rgba(64, 158, 255, 0.05) 0%, rgba(64, 158, 255, 0.02) 100%);
  2768 + transform: translateX(4px);
  2769 + border-bottom-color: rgba(64, 158, 255, 0.3);
  2770 + padding-left: 4px;
  2771 + padding-right: 4px;
  2772 + }
2463 2773  
2464 2774 &:last-child {
2465 2775 border-bottom: none;
... ... @@ -2469,37 +2779,58 @@ export default {
2469 2779 width: 20px;
2470 2780 height: 20px;
2471 2781 border-radius: 4px;
2472   - background: #909399;
  2782 + background: linear-gradient(135deg, #909399 0%, #606266 100%);
2473 2783 color: #fff;
2474   - font-size: 12px;
  2784 + font-size: 11px;
  2785 + font-weight: 600;
2475 2786 display: flex;
2476 2787 align-items: center;
2477 2788 justify-content: center;
2478   - margin-right: 12px;
  2789 + margin-right: 10px;
  2790 + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
  2791 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2792 + flex-shrink: 0;
2479 2793  
2480 2794 &.top1 {
2481   - background: #F56C6C;
  2795 + background: linear-gradient(135deg, #F56C6C 0%, #ff8080 100%);
  2796 + box-shadow: 0 1px 6px rgba(245, 108, 108, 0.3);
2482 2797 }
2483 2798  
2484 2799 &.top2 {
2485   - background: #E6A23C;
  2800 + background: linear-gradient(135deg, #E6A23C 0%, #f0b45a 100%);
  2801 + box-shadow: 0 1px 6px rgba(230, 162, 60, 0.3);
2486 2802 }
2487 2803  
2488 2804 &.top3 {
2489   - background: #409EFF;
  2805 + background: linear-gradient(135deg, #409EFF 0%, #66b1ff 100%);
  2806 + box-shadow: 0 1px 6px rgba(64, 158, 255, 0.3);
2490 2807 }
2491 2808 }
2492 2809  
  2810 + &:hover .rank-no {
  2811 + transform: scale(1.05) rotate(3deg);
  2812 + }
  2813 +
2493 2814 .rank-name {
2494 2815 flex: 1;
2495 2816 color: #606266;
2496 2817 font-size: 14px;
  2818 + transition: color 0.3s;
  2819 + }
  2820 +
  2821 + &:hover .rank-name {
  2822 + color: #303133;
  2823 + font-weight: 500;
2497 2824 }
2498 2825  
2499 2826 .rank-val {
2500 2827 font-weight: 600;
2501 2828 color: #303133;
2502 2829 font-size: 14px;
  2830 + background: linear-gradient(135deg, #303133 0%, #606266 100%);
  2831 + -webkit-background-clip: text;
  2832 + -webkit-text-fill-color: transparent;
  2833 + background-clip: text;
2503 2834 }
2504 2835 }
2505 2836 }
... ... @@ -2522,12 +2853,66 @@ export default {
2522 2853 }
2523 2854 }
2524 2855  
  2856 + /* Insight Row */
  2857 + .insight-row {
  2858 + .dashboard-card {
  2859 + height: 400px;
  2860 + display: flex;
  2861 + flex-direction: column;
  2862 +
  2863 + &::v-deep .el-card__body {
  2864 + flex: 1;
  2865 + display: flex;
  2866 + flex-direction: column;
  2867 + overflow: hidden;
  2868 + min-height: 0;
  2869 + padding: 16px 20px 12px 20px;
  2870 + }
  2871 +
  2872 + .item-rank {
  2873 + flex: 1;
  2874 + overflow-y: auto;
  2875 + min-height: 0;
  2876 + padding-right: 4px;
  2877 +
  2878 + &::-webkit-scrollbar {
  2879 + width: 6px;
  2880 + }
  2881 +
  2882 + &::-webkit-scrollbar-track {
  2883 + background: rgba(240, 242, 245, 0.5);
  2884 + border-radius: 3px;
  2885 + }
  2886 +
  2887 + &::-webkit-scrollbar-thumb {
  2888 + background: linear-gradient(135deg, #c0c4cc 0%, #909399 100%);
  2889 + border-radius: 3px;
  2890 + transition: background 0.3s;
  2891 +
  2892 + &:hover {
  2893 + background: linear-gradient(135deg, #909399 0%, #606266 100%);
  2894 + }
  2895 + }
  2896 + }
  2897 + }
  2898 + }
  2899 +
2525 2900 /* Item Rank */
2526 2901 .item-rank {
2527 2902 .item-rank-row {
2528 2903 display: flex;
2529 2904 align-items: center;
2530   - margin-bottom: 12px;
  2905 + margin-bottom: 5px;
  2906 + padding: 3px 8px;
  2907 + border-radius: 6px;
  2908 + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  2909 + border: 1px solid transparent;
  2910 +
  2911 + &:hover {
  2912 + background: linear-gradient(90deg, rgba(64, 158, 255, 0.05) 0%, rgba(64, 158, 255, 0.02) 100%);
  2913 + transform: translateX(4px);
  2914 + border-color: rgba(64, 158, 255, 0.15);
  2915 + }
2531 2916  
2532 2917 .item-index {
2533 2918 font-weight: bold;
... ... @@ -2536,6 +2921,11 @@ export default {
2536 2921 font-style: italic;
2537 2922 flex-shrink: 0;
2538 2923 width: 20px;
  2924 + transition: color 0.3s;
  2925 + }
  2926 +
  2927 + &:hover .item-index {
  2928 + color: #909399;
2539 2929 }
2540 2930  
2541 2931 .item-name {
... ... @@ -2549,6 +2939,12 @@ export default {
2549 2939 overflow: hidden;
2550 2940 text-overflow: ellipsis;
2551 2941 white-space: nowrap;
  2942 + transition: color 0.3s;
  2943 + }
  2944 +
  2945 + &:hover .item-name {
  2946 + color: #303133;
  2947 + font-weight: 500;
2552 2948 }
2553 2949  
2554 2950 &::v-deep .el-progress {
... ... @@ -2557,7 +2953,13 @@ export default {
2557 2953 }
2558 2954  
2559 2955 &::v-deep .el-progress-bar__outer {
2560   - background-color: #F2F6FC;
  2956 + background: linear-gradient(90deg, #F2F6FC 0%, #E4E7ED 100%);
  2957 + border-radius: 10px;
  2958 + overflow: hidden;
  2959 + }
  2960 +
  2961 + &::v-deep .el-progress-bar__inner {
  2962 + border-radius: 10px;
2561 2963 }
2562 2964  
2563 2965 .item-count {
... ... @@ -2568,6 +2970,10 @@ export default {
2568 2970 white-space: nowrap;
2569 2971 min-width: 60px;
2570 2972 text-align: right;
  2973 + background: linear-gradient(135deg, #303133 0%, #606266 100%);
  2974 + -webkit-background-clip: text;
  2975 + -webkit-text-fill-color: transparent;
  2976 + background-clip: text;
2571 2977 }
2572 2978 }
2573 2979 }
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKhxx/LqKhxxExportOutput.cs
... ... @@ -35,11 +35,6 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx
35 35 public string xb { get; set; }
36 36  
37 37 /// <summary>
38   - /// 客户目前归属名称
39   - /// </summary>
40   - public string khmqgsName { get; set; }
41   -
42   - /// <summary>
43 38 /// 归属门店名称
44 39 /// </summary>
45 40 public string gsmdName { get; set; }
... ... @@ -55,19 +50,24 @@ namespace NCC.Extend.Entitys.Dto.LqKhxx
55 50 public string khlxName { get; set; }
56 51  
57 52 /// <summary>
58   - /// 客户阶段
  53 + /// 主健康师名称
  54 + /// </summary>
  55 + public string mainHealthUserName { get; set; }
  56 +
  57 + /// <summary>
  58 + /// 副健康师名称
59 59 /// </summary>
60   - public string khjd { get; set; }
  60 + public string subHealthUserName { get; set; }
61 61  
62 62 /// <summary>
63   - /// 客户消费
  63 + /// 拓客人员名称
64 64 /// </summary>
65   - public string khxf { get; set; }
  65 + public string expandUserName { get; set; }
66 66  
67 67 /// <summary>
68   - /// 消费频次
  68 + /// 消费等级名称(D、C、B、A、A+、A++)
69 69 /// </summary>
70   - public string xfpc { get; set; }
  70 + public string consumeLevelName { get; set; }
71 71  
72 72 /// <summary>
73 73 /// 推荐人
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqKhxxService.cs
... ... @@ -796,8 +796,86 @@ namespace NCC.Extend.LqKhxx
796 796 }
797 797 }
798 798  
  799 + // 批量查询主健康师信息
  800 + var mainHealthUserIds = customerList
  801 + .Where(c => !string.IsNullOrEmpty(c.MainHealthUser))
  802 + .Select(c => c.MainHealthUser)
  803 + .Distinct()
  804 + .Where(id => !string.IsNullOrEmpty(id))
  805 + .ToList();
  806 + var mainHealthUserDict = new Dictionary<string, string>();
  807 + if (mainHealthUserIds != null && mainHealthUserIds.Any())
  808 + {
  809 + var mainHealthUsers = await _db.Queryable<UserEntity>()
  810 + .Where(u => mainHealthUserIds.Contains(u.Id) && !string.IsNullOrEmpty(u.Id))
  811 + .Select(u => new { u.Id, u.RealName })
  812 + .ToListAsync();
  813 + if (mainHealthUsers != null && mainHealthUsers.Any())
  814 + {
  815 + foreach (var user in mainHealthUsers)
  816 + {
  817 + if (!string.IsNullOrEmpty(user.Id) && !mainHealthUserDict.ContainsKey(user.Id))
  818 + {
  819 + mainHealthUserDict[user.Id] = user.RealName ?? "";
  820 + }
  821 + }
  822 + }
  823 + }
  824 +
  825 + // 批量查询副健康师信息
  826 + var subHealthUserIds = customerList
  827 + .Where(c => !string.IsNullOrEmpty(c.SubHealthUser))
  828 + .Select(c => c.SubHealthUser)
  829 + .Distinct()
  830 + .Where(id => !string.IsNullOrEmpty(id))
  831 + .ToList();
  832 + var subHealthUserDict = new Dictionary<string, string>();
  833 + if (subHealthUserIds != null && subHealthUserIds.Any())
  834 + {
  835 + var subHealthUsers = await _db.Queryable<UserEntity>()
  836 + .Where(u => subHealthUserIds.Contains(u.Id) && !string.IsNullOrEmpty(u.Id))
  837 + .Select(u => new { u.Id, u.RealName })
  838 + .ToListAsync();
  839 + if (subHealthUsers != null && subHealthUsers.Any())
  840 + {
  841 + foreach (var user in subHealthUsers)
  842 + {
  843 + if (!string.IsNullOrEmpty(user.Id) && !subHealthUserDict.ContainsKey(user.Id))
  844 + {
  845 + subHealthUserDict[user.Id] = user.RealName ?? "";
  846 + }
  847 + }
  848 + }
  849 + }
  850 +
  851 + // 批量查询拓客人员信息
  852 + var expandUserIds = customerList
  853 + .Where(c => !string.IsNullOrEmpty(c.ExpandUser))
  854 + .Select(c => c.ExpandUser)
  855 + .Distinct()
  856 + .Where(id => !string.IsNullOrEmpty(id))
  857 + .ToList();
  858 + var expandUserDict = new Dictionary<string, string>();
  859 + if (expandUserIds != null && expandUserIds.Any())
  860 + {
  861 + var expandUsers = await _db.Queryable<UserEntity>()
  862 + .Where(u => expandUserIds.Contains(u.Id) && !string.IsNullOrEmpty(u.Id))
  863 + .Select(u => new { u.Id, u.RealName })
  864 + .ToListAsync();
  865 + if (expandUsers != null && expandUsers.Any())
  866 + {
  867 + foreach (var user in expandUsers)
  868 + {
  869 + if (!string.IsNullOrEmpty(user.Id) && !expandUserDict.ContainsKey(user.Id))
  870 + {
  871 + expandUserDict[user.Id] = user.RealName ?? "";
  872 + }
  873 + }
  874 + }
  875 + }
  876 +
799 877 // 转换为导出DTO
800   - var queryResult = customerList.Select(kh => new
  878 + var exportData = customerList.Select(kh => new LqKhxxExportOutput
801 879 {
802 880 id = kh.Id,
803 881 khmc = kh.Khmc,
... ... @@ -806,10 +884,11 @@ namespace NCC.Extend.LqKhxx
806 884 xb = kh.Xb,
807 885 gsmdName = (!string.IsNullOrEmpty(kh.Gsmd) && storeDict.ContainsKey(kh.Gsmd)) ? (storeDict[kh.Gsmd].Dm ?? "") : "",
808 886 zcsj = kh.Zcsj,
809   - khlx = kh.Khlx,
810   - khjd = kh.Khjd,
811   - khxf = kh.Khxf,
812   - xfpc = kh.Xfpc,
  887 + khlxName = GetMemberTypeName(kh.Khlx),
  888 + mainHealthUserName = (!string.IsNullOrEmpty(kh.MainHealthUser) && mainHealthUserDict.ContainsKey(kh.MainHealthUser)) ? mainHealthUserDict[kh.MainHealthUser] : "",
  889 + subHealthUserName = (!string.IsNullOrEmpty(kh.SubHealthUser) && subHealthUserDict.ContainsKey(kh.SubHealthUser)) ? subHealthUserDict[kh.SubHealthUser] : "",
  890 + expandUserName = (!string.IsNullOrEmpty(kh.ExpandUser) && expandUserDict.ContainsKey(kh.ExpandUser)) ? expandUserDict[kh.ExpandUser] : "",
  891 + consumeLevelName = GetConsumeLevelNameFromLevel(kh.ConsumeLevel),
813 892 tjrName = (!string.IsNullOrEmpty(kh.Tjr) && tjrDict.ContainsKey(kh.Tjr)) ? tjrDict[kh.Tjr] : "",
814 893 jdqd = kh.Jdqd,
815 894 lxdz = kh.Lxdz,
... ... @@ -820,40 +899,7 @@ namespace NCC.Extend.LqKhxx
820 899 visitDays = kh.VisitDays,
821 900 sleepDays = kh.SleepDays,
822 901 totalBillingAmount = kh.TotalBillingAmount,
823   - remainingRightsAmount = kh.RemainingRightsAmount,
824   - // 门店归属信息,用于计算客户目前归属名称
825   - syb = (!string.IsNullOrEmpty(kh.Gsmd) && storeDict.ContainsKey(kh.Gsmd)) ? (storeDict[kh.Gsmd].Syb ?? "") : "",
826   - jyb = (!string.IsNullOrEmpty(kh.Gsmd) && storeDict.ContainsKey(kh.Gsmd)) ? (storeDict[kh.Gsmd].Jyb ?? "") : "",
827   - kjb = (!string.IsNullOrEmpty(kh.Gsmd) && storeDict.ContainsKey(kh.Gsmd)) ? (storeDict[kh.Gsmd].Kjb ?? "") : "",
828   - dxmb = (!string.IsNullOrEmpty(kh.Gsmd) && storeDict.ContainsKey(kh.Gsmd)) ? (storeDict[kh.Gsmd].Dxmb ?? "") : ""
829   - }).ToList();
830   -
831   - // 转换为导出DTO,并计算客户类型名称和客户目前归属名称
832   - var exportData = queryResult.Select(item => new LqKhxxExportOutput
833   - {
834   - id = item.id,
835   - khmc = item.khmc,
836   - sjh = item.sjh,
837   - dah = item.dah,
838   - xb = item.xb,
839   - gsmdName = item.gsmdName,
840   - zcsj = item.zcsj,
841   - khlxName = GetMemberTypeName(item.khlx),
842   - khjd = item.khjd,
843   - khxf = item.khxf,
844   - xfpc = item.xfpc,
845   - tjrName = item.tjrName,
846   - jdqd = item.jdqd,
847   - lxdz = item.lxdz,
848   - bz = item.bz,
849   - yanglsr = item.yanglsr,
850   - firstVisitTime = item.firstVisitTime,
851   - lastVisitTime = item.lastVisitTime,
852   - visitDays = item.visitDays,
853   - sleepDays = item.sleepDays,
854   - totalBillingAmount = item.totalBillingAmount,
855   - remainingRightsAmount = item.remainingRightsAmount,
856   - khmqgsName = GetCustomerBelongName(item.syb, item.jyb, item.kjb, item.dxmb)
  902 + remainingRightsAmount = kh.RemainingRightsAmount
857 903 }).ToList();
858 904  
859 905 // 获取客户类型名称的辅助方法
... ... @@ -867,15 +913,12 @@ namespace NCC.Extend.LqKhxx
867 913 return "无";
868 914 }
869 915  
870   - // 获取客户目前归属名称的辅助方法
871   - string GetCustomerBelongName(string syb, string jyb, string kjb, string dxmb)
  916 + // 根据消费等级编号获取消费等级名称
  917 + string GetConsumeLevelNameFromLevel(int level)
872 918 {
873   - var belongList = new List<string>();
874   - if (!string.IsNullOrEmpty(syb)) belongList.Add("事业部");
875   - if (!string.IsNullOrEmpty(jyb)) belongList.Add("教育部");
876   - if (!string.IsNullOrEmpty(kjb)) belongList.Add("科技部");
877   - if (!string.IsNullOrEmpty(dxmb)) belongList.Add("大项目部");
878   - return belongList.Count > 0 ? string.Join("、", belongList) : "无";
  919 + return MemberInfoUpdateConfig.ConsumeLevelNames.ContainsKey(level)
  920 + ? MemberInfoUpdateConfig.ConsumeLevelNames[level]
  921 + : "D";
879 922 }
880 923  
881 924 // 定义导出字段映射
... ... @@ -886,13 +929,13 @@ namespace NCC.Extend.LqKhxx
886 929 new ParamsModel { value = "手机号", field = "sjh" },
887 930 new ParamsModel { value = "档案号", field = "dah" },
888 931 new ParamsModel { value = "性别", field = "xb" },
889   - new ParamsModel { value = "客户目前归属名称", field = "khmqgsName" },
890 932 new ParamsModel { value = "归属门店名称", field = "gsmdName" },
891 933 new ParamsModel { value = "注册时间", field = "zcsj" },
892   - new ParamsModel { value = "客户类型名称", field = "khlxName" },
893   - new ParamsModel { value = "客户阶段", field = "khjd" },
894   - new ParamsModel { value = "客户消费", field = "khxf" },
895   - new ParamsModel { value = "消费频次", field = "xfpc" },
  934 + new ParamsModel { value = "客户类型", field = "khlxName" },
  935 + new ParamsModel { value = "主健康师", field = "mainHealthUserName" },
  936 + new ParamsModel { value = "副健康师", field = "subHealthUserName" },
  937 + new ParamsModel { value = "拓客人员", field = "expandUserName" },
  938 + new ParamsModel { value = "消费等级", field = "consumeLevelName" },
896 939 new ParamsModel { value = "推荐人", field = "tjrName" },
897 940 new ParamsModel { value = "进店渠道", field = "jdqd" },
898 941 new ParamsModel { value = "联系地址", field = "lxdz" },
... ...