diff --git a/application/admin/view/fc/category/index.html b/application/admin/view/fc/category/index.html
index 73428b5..7beb1a2 100644
--- a/application/admin/view/fc/category/index.html
+++ b/application/admin/view/fc/category/index.html
@@ -85,6 +85,13 @@
.fc-img-wrap .fc-img-zoom img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fc-img-wrap:hover .fc-img-zoom { opacity: 1; transform: translateX(-50%) scale(1); }
+ /* 快捷筛选按钮组 */
+ .fc-quick-filters { display: inline-flex; vertical-align: middle; margin-left: 8px; border-radius: 8px; overflow: hidden; border: 1px solid #d9f5e6; background: #ffffff; box-shadow: 0 1px 3px rgba(0,0,0,0.03); }
+ .fc-quick-filters .btn { border: none !important; border-radius: 0 !important; margin: 0 !important; padding: 6px 12px; font-size: 12.5px; font-weight: 600; color: #475569; background: #ffffff; transition: all 0.15s ease; }
+ .fc-quick-filters .btn + .btn { border-left: 1px solid #eef7f2 !important; }
+ .fc-quick-filters .btn:hover { background: #f2fef7; color: #00a854; }
+ .fc-quick-filters .btn.active { background: linear-gradient(135deg, #00e070, #00c860) !important; color: #04301e !important; box-shadow: inset 0 1px 2px rgba(0,0,0,0.08); }
+
/* 分页与信息区 */
.fixed-table-pagination .pagination-detail, .fixed-table-pagination .page-list { color: #64748b; }
.fixed-table-pagination .pagination > li > a { border-radius: 8px !important; margin: 0 2px; border: 1px solid #e2e8f0; }
@@ -108,10 +115,12 @@
添加分类
{:__('Edit')}
{:__('Delete')}
-
- 金刚区已推荐:{$homeCount|default='8'} / 8 个
-
- 只看金刚区
+
一级大类';
}
- return '' + (value || ('#' + row.pid)) + '';
+ return '' + (row.parent_name || ('#' + row.pid)) + '';
}
},
- // 2.6 分类类型(决定发布页是否显示产地规格字段)
+ // 2.6 分类类型(决定发布页是否显示产地规格字段,支持下拉筛选)
{
field: 'kind',
title: '类型',
- operate: false,
align: 'center',
width: '100px',
+ searchList: {'farm': '农产品', 'general': '通用信息'},
formatter: function (value, row, index) {
if (value === 'farm') {
return '农产品';
@@ -221,8 +221,17 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'backend/format'], fu
// 为表格绑定事件
Table.api.bindevent(table);
- // 快捷筛选:只看首页金刚区推荐分类
- $(document).on("click", ".btn-filter-home", function () {
+ /**
+ * 快捷层级与状态筛选(全部/一级大类/二级品类/首页金刚区推荐)
+ * @param {Object} filterObj 过滤参数键值对
+ * @param {Object} opObj 操作符参数键值对
+ * @param {HTMLElement} activeBtn 触发按钮
+ */
+ function applyQuickFilter(filterObj, opObj, activeBtn) {
+ $('.fc-quick-filters .btn').removeClass('active');
+ if (activeBtn) {
+ $(activeBtn).addClass('active');
+ }
var options = table.bootstrapTable('getOptions');
var queryParams = options.queryParams;
options.pageNumber = 1;
@@ -230,13 +239,42 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'backend/format'], fu
var p = typeof queryParams === 'function' ? queryParams(params) : params;
var filter = p.filter ? JSON.parse(p.filter) : {};
var op = p.op ? JSON.parse(p.op) : {};
- filter.is_home = 1;
- op.is_home = '=';
+
+ // 清理快捷筛选旧字段,避免状态叠加冲突
+ delete filter.pid;
+ delete op.pid;
+ delete filter.is_home;
+ delete op.is_home;
+
+ // 合并新条件
+ $.extend(filter, filterObj);
+ $.extend(op, opObj);
+
p.filter = JSON.stringify(filter);
p.op = JSON.stringify(op);
return p;
};
table.bootstrapTable('refresh', {});
+ }
+
+ // 全部
+ $(document).on("click", ".btn-filter-all", function () {
+ applyQuickFilter({}, {}, this);
+ });
+
+ // 仅看一级大类 (pid = 0)
+ $(document).on("click", ".btn-filter-top", function () {
+ applyQuickFilter({pid: 0}, {pid: '='}, this);
+ });
+
+ // 仅看二级品类 (pid > 0)
+ $(document).on("click", ".btn-filter-sub", function () {
+ applyQuickFilter({pid: 0}, {pid: '>'}, this);
+ });
+
+ // 快捷筛选:只看首页金刚区推荐分类 (is_home = 1)
+ $(document).on("click", ".btn-filter-home", function () {
+ applyQuickFilter({is_home: 1}, {is_home: '='}, this);
});
},
diff --git a/uniapp/common/config/index.js b/uniapp/common/config/index.js
index 1ecd04b..e8ad2bd 100644
--- a/uniapp/common/config/index.js
+++ b/uniapp/common/config/index.js
@@ -49,7 +49,7 @@ const ENV = IS_PROD ? 'production' : 'development'
// 各环境后端域名(dev=运行 / prod=发行)
const HOSTS = {
dev: 'https://ff5e582.r9.cpolar.cn', // 本地后端(phpstudy 虚拟域名与端口 9980)
- prod: 'https://fenleixinxi.gzyakj.com.cn', // 远程正式后端
+ prod: 'https://shanjianxiaocang.com', // 远程正式后端
}
// 接口统一前缀
const API_PREFIX = '/api'
diff --git a/uniapp/pages/category/index.vue b/uniapp/pages/category/index.vue
index aa2d2be..7db6080 100644
--- a/uniapp/pages/category/index.vue
+++ b/uniapp/pages/category/index.vue
@@ -26,64 +26,110 @@
-
+
-
+
- {{ currentCategory ? currentCategory.name : '精选' }}品类
- 查看全部 ›
+
+ {{ categorySectionTitle }}
+
+ {{ currentSubCategory.name }}
+ ✕
+
+
+
+
+
+
+
+ ×
+
+
-
+
+ ✓
全部
-
+
+ ✓
{{ sub.name }}
+
+
+ 未找到“{{ subKeyword }}”相关品类
+ 清空搜索
+
@@ -110,8 +156,23 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- 正在加载中...
- — 没有更多信息了 —
+
+
+ 正在为您寻找好物…
+
+
+ — 已呈现全部同城信息 —
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ {{ keyword ? '未找到「' + keyword + '」相关信息' : (currentSubCategory ? '暂无「' + currentSubCategory.name + '」相关发布' : '该品类下暂无发布信息') }}
+
+ 抢先发布此分类,让同城人脉第一眼发现
+
+
+
+
+
@@ -248,6 +322,8 @@ import { groupAreaTree } from '@/common/utils/area.js'
// 与首页共享的区域选择缓存(两端区域筛选状态互通)
const STORAGE_KEY_SELECTED_AREA = 'fc_user_selected_area'
+// 分类数据快照缓存(实现 0ms 秒开无白屏)
+const STORAGE_KEY_CATEGORIES = 'fc_cached_categories_v2'
/**
* 安全读取本地缓存
@@ -282,6 +358,10 @@ export default {
navBarHeight: 44,
capsulePadding: 0,
keyword: '',
+ // 二级品类过滤搜索关键词
+ subKeyword: '',
+ // 图片加载失败映射表(防止宫格出现浅灰空块,支持降级为精美微插画)
+ failedSubImgIds: {},
categories: [],
currentCategory: null,
currentSubCategory: null,
@@ -310,6 +390,12 @@ export default {
total: 0,
hasMore: true,
loading: false,
+ // 页面首次初始化加载骨架状态
+ isInitialLoading: true,
+ // 分类切换平滑过渡状态(防止旧列表瞬间销毁导致的猛烈闪屏抖动)
+ isSwitching: false,
+ // 下拉刷新触发状态
+ isRefreshing: false,
// 请求序号:切换分类/排序/搜索时丢弃过期响应,避免「点了筛选但列表没变」
reqSeq: 0,
lat: null,
@@ -321,8 +407,18 @@ export default {
* 输入框占位文案,动态根据当前选中一级/二级分类切换
*/
searchPlaceholder() {
- const name = (this.currentSubCategory && this.currentSubCategory.name) || (this.currentCategory ? this.currentCategory.name : '农产品')
- return '在“' + name + '”中搜索…'
+ const name = (this.currentSubCategory && this.currentSubCategory.name) || (this.currentCategory ? this.currentCategory.name : '全部分类')
+ return '搜索“' + name + '”信息…'
+ },
+ /**
+ * 二级品类区域标题(例如:“招聘品类”、“水果品类”、“精选品类”)
+ * 消除冗长复杂的“专区品类”字样,提升右上角区域呼吸感
+ * @returns {string} 优化后的分类标题
+ */
+ categorySectionTitle() {
+ if (!this.currentCategory || !this.currentCategory.name) return '精选品类'
+ const raw = this.currentCategory.name.trim()
+ return raw.replace(/专区$/, '') + '品类'
},
/**
* 当前一级分类下的二级分类列表
@@ -331,6 +427,18 @@ export default {
if (!this.currentCategory || !Array.isArray(this.currentCategory.children)) return []
return this.currentCategory.children
},
+ /**
+ * 经过二级分类搜索关键词过滤后的展示品类列表
+ * @returns {Array} 过滤后的二级分类数组
+ */
+ displaySubCategories() {
+ const list = this.currentSubCategories
+ if (!this.subKeyword || !this.subKeyword.trim()) {
+ return list
+ }
+ const kw = this.subKeyword.trim().toLowerCase()
+ return list.filter((item) => item && item.name && item.name.toLowerCase().includes(kw))
+ },
/**
* 区域筛选按钮文案(市 > 省 > 全国)
*/
@@ -377,6 +485,43 @@ export default {
iconUrl,
/** 暴露给模板:分类图标解析 */
categoryIconUrl,
+ /**
+ * 解析二级分类图标(含加载失败自动降级与预设行业插画兜底,彻底解决空白浅灰块)
+ * @param {Object} sub 二级分类对象
+ * @returns {string} 可靠的图片或图标真实地址
+ */
+ catSubThumb(sub) {
+ if (!sub) return catIcon(this.currentCategory)
+ if (this.failedSubImgIds && this.failedSubImgIds[sub.id]) {
+ return this.fallbackSubIcon(sub)
+ }
+ return catIcon(sub)
+ },
+ /**
+ * 根据分类名称回退到包内最贴合的高清矢量微插画
+ * @param {Object} sub 二级分类对象
+ * @returns {string} 兜底矢量图标地址
+ */
+ fallbackSubIcon(sub) {
+ const name = (sub && sub.name) || ''
+ if (/技工|普工|制造|工厂/i.test(name)) return iconUrl('cat-job')
+ if (/餐饮|服务|厨师|服务员/i.test(name)) return iconUrl('cat-service')
+ if (/保洁|家政|清洁/i.test(name)) return iconUrl('cat-clean')
+ if (/教育|培训|老师|辅导/i.test(name)) return iconUrl('cat-education')
+ if (/司机|出行|货运|代驾/i.test(name)) return iconUrl('cat-car')
+ if (/兼职|短工/i.test(name)) return iconUrl('cat-job')
+ return catIcon(this.currentCategory)
+ },
+ /**
+ * 二级分类图片加载失败容错处理
+ * @param {Object} sub 二级分类对象
+ * @returns {void}
+ */
+ handleSubImgError(sub) {
+ if (!sub || !sub.id) return
+ if (!this.failedSubImgIds) this.failedSubImgIds = {}
+ this.$set(this.failedSubImgIds, sub.id, true)
+ },
/**
* 初始化设备导航栏与胶囊避让度量
*/
@@ -434,57 +579,88 @@ export default {
} catch (e) {}
},
/**
- * 拉取全部分类数据(支持默认选中一级或二级分类)
+ * 拉取全部分类数据(快照缓存秒开 + 后台静默对齐)
* @param {string|number} defaultCatId 默认选中的分类 ID
+ * @returns {Promise}
*/
async fetchCategories(defaultCatId) {
+ // 1. 优先读取本地持久化快照,0ms 立即挂载大类与二级品类
+ const cached = safeGetStorage(STORAGE_KEY_CATEGORIES, null)
+ if (Array.isArray(cached) && cached.length) {
+ this.applyCategoriesTree(cached, defaultCatId, !this.list.length)
+ }
try {
const cats = await homeApi.categories()
- this.categories = Array.isArray(cats) ? cats : []
- if (this.categories.length) {
- let targetParent = null
- let targetSub = null
- if (defaultCatId) {
- targetParent = this.categories.find((c) => String(c.id) === String(defaultCatId)) || null
- if (!targetParent) {
- for (const p of this.categories) {
- const foundSub = (p.children || []).find((s) => String(s.id) === String(defaultCatId))
- if (foundSub) {
- targetParent = p
- targetSub = foundSub
- break
- }
- }
- }
- }
- this.currentCategory = targetParent || this.categories[0]
- this.currentSubCategory = targetSub || null
- this.page = 1
- this.list = []
- this.hasMore = true
- this.fetchPosts()
+ const list = Array.isArray(cats) ? cats : []
+ if (list.length) {
+ safeSetStorage(STORAGE_KEY_CATEGORIES, list)
+ this.applyCategoriesTree(list, defaultCatId, true)
}
} catch (e) {
- uni.showToast({ title: '分类加载失败', icon: 'none' })
+ if (!this.categories || !this.categories.length) {
+ uni.showToast({ title: '分类加载失败', icon: 'none' })
+ }
+ } finally {
+ this.isInitialLoading = false
}
},
/**
- * 切换当前选中的左侧一级大类
+ * 统一解析并挂载分类树结构
+ * @param {Array} cats 分类原始数据列表
+ * @param {string|number} defaultCatId 默认选中的分类ID
+ * @param {boolean} shouldFetchPosts 是否自动触发信息流拉取
+ * @returns {void}
+ */
+ applyCategoriesTree(cats, defaultCatId, shouldFetchPosts = true) {
+ this.categories = cats
+ if (!this.categories.length) return
+ let targetParent = null
+ let targetSub = null
+ if (defaultCatId) {
+ targetParent = this.categories.find((c) => String(c.id) === String(defaultCatId)) || null
+ if (!targetParent) {
+ for (const p of this.categories) {
+ const foundSub = (p.children || []).find((s) => String(s.id) === String(defaultCatId))
+ if (foundSub) {
+ targetParent = p
+ targetSub = foundSub
+ break
+ }
+ }
+ }
+ }
+ if (this.currentCategory) {
+ const exist = this.categories.find((c) => c.id === this.currentCategory.id)
+ this.currentCategory = exist || this.categories[0]
+ } else {
+ this.currentCategory = targetParent || this.categories[0]
+ this.currentSubCategory = targetSub || null
+ }
+ if (shouldFetchPosts) {
+ this.fetchPosts(false)
+ }
+ },
+ /**
+ * 切换当前选中的左侧一级大类(平滑过渡防闪烁)
* @param {Object} cat 选中的一级分类对象
+ * @returns {void}
*/
selectCategory(cat) {
if (!cat) return
if (this.currentCategory && this.currentCategory.id === cat.id && !this.currentSubCategory) return
this.currentCategory = cat
this.currentSubCategory = null
+ this.subKeyword = '' // 切换一级大类时重置二级品类搜索
this.page = 1
- this.list = []
this.hasMore = true
- this.fetchPosts()
+ // 开启平滑过渡,不先置空旧列表,杜绝视口高度剧烈塌陷与白屏闪烁
+ this.isSwitching = true
+ this.fetchPosts(false)
},
/**
* 切换右侧二级分类(如:花菜、白菜、紫甘蓝、青甘蓝、青菜等)
* @param {Object|null} sub 二级分类对象(null代表当前大类全部)
+ * @returns {void}
*/
selectSubCategory(sub) {
const nextId = sub ? Number(sub.id) : 0
@@ -492,13 +668,14 @@ export default {
if (nextId === curId) return
this.currentSubCategory = sub || null
this.page = 1
- this.list = []
this.hasMore = true
- this.fetchPosts()
+ this.isSwitching = true
+ this.fetchPosts(false)
},
/**
* 切换排序规则(价格项:首次点击升序,再次点击升降序来回切换)
* @param {string} s 排序值 new|hot|nearby|price
+ * @returns {void}
*/
changeSort(s) {
if (s === 'price') {
@@ -512,9 +689,9 @@ export default {
}
this.sort = s
this.page = 1
- this.list = []
this.hasMore = true
- this.fetchPosts()
+ this.isSwitching = true
+ this.fetchPosts(false)
// 「附近」依赖坐标:无坐标时补取一次定位(成功后自动重排)
if (s === 'nearby' && (!this.lat || !this.lng)) {
uni.showToast({ title: '正在获取定位…', icon: 'none' })
@@ -688,12 +865,34 @@ export default {
})
},
/**
- * 获取当前分类下的信息列表(支持关键字在当前页面直接检索)
+ * 下拉刷新:重新获取分类与当前列表数据(支持下拉动画指示)
+ * @returns {Promise}
*/
- async fetchPosts() {
+ async onPullDownRefresh() {
+ this.isRefreshing = true
+ this.page = 1
+ try {
+ await Promise.all([
+ this.fetchCategories(this.currentCategory ? this.currentCategory.id : null),
+ this.fetchPosts(false)
+ ])
+ } finally {
+ this.isRefreshing = false
+ uni.stopPullDownRefresh()
+ }
+ },
+ /**
+ * 获取当前分类下的信息列表(支持关键字在当前页面直接检索)
+ * @param {boolean} isLoadMore 是否为触底加载下一页数据
+ * @returns {Promise}
+ */
+ async fetchPosts(isLoadMore = false) {
if (!this.currentCategory) return
const seq = ++this.reqSeq
this.loading = true
+ if (!isLoadMore) {
+ this.isSwitching = true
+ }
try {
const params = {
categoryId: this.currentCategory.id,
@@ -724,16 +923,22 @@ export default {
if (seq !== this.reqSeq) return
uni.showToast({ title: '加载信息失败', icon: 'none' })
} finally {
- if (seq === this.reqSeq) this.loading = false
+ if (seq === this.reqSeq) {
+ this.loading = false
+ this.isSwitching = false
+ this.isInitialLoading = false
+ this.isRefreshing = false
+ }
}
},
/**
* 触底加载下一页数据
+ * @returns {void}
*/
loadMore() {
if (this.hasMore && !this.loading) {
this.page += 1
- this.fetchPosts()
+ this.fetchPosts(true)
}
},
/**
@@ -904,6 +1109,22 @@ export default {
transform: scale(1.06);
}
}
+ &--skel {
+ pointer-events: none;
+ }
+}
+.cat-sidebar__skel-icon {
+ width: 34rpx;
+ height: 34rpx;
+ border-radius: 8rpx;
+ flex-shrink: 0;
+ background: #edf2f0;
+}
+.cat-sidebar__skel-name {
+ width: 100rpx;
+ height: 24rpx;
+ border-radius: 6rpx;
+ background: #edf2f0;
}
.cat-sidebar__bar {
position: absolute;
@@ -955,16 +1176,123 @@ export default {
display: flex;
align-items: center;
justify-content: space-between;
- padding: 0 6rpx 14rpx;
+ padding: 0 4rpx 14rpx;
+ gap: 12rpx;
+}
+.cat-subcard__head-left {
+ display: flex;
+ align-items: center;
+ gap: 10rpx;
+ min-width: 0;
+ flex: 1;
}
.cat-subcard__title {
font-size: 26rpx;
font-weight: 700;
color: #1e293b;
+ white-space: nowrap;
}
-.cat-subcard__reset {
+/* 当前选中的二级品类微胶囊标签 */
+.cat-subcard__active-pill {
+ display: inline-flex;
+ align-items: center;
+ gap: 6rpx;
+ background: #ecfdf5;
+ border: 1rpx solid #a7f3d0;
+ padding: 2rpx 12rpx;
+ border-radius: 999rpx;
+ max-width: 170rpx;
+ cursor: pointer;
+ transition: opacity 0.15s ease;
+ &:active {
+ opacity: 0.8;
+ }
+}
+.cat-subcard__active-pill-txt {
+ font-size: 21rpx;
+ color: #00a854;
+ font-weight: 600;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.cat-subcard__active-pill-close {
+ font-size: 18rpx;
+ color: #00a854;
+ opacity: 0.75;
+ line-height: 1;
+}
+/* 右上角二级品类微搜索条 */
+.cat-subcard__search {
+ display: flex;
+ align-items: center;
+ background: #f4fbf7;
+ border: 1rpx solid #d1fae5;
+ border-radius: 999rpx;
+ height: 52rpx;
+ padding: 0 14rpx;
+ box-sizing: border-box;
+ width: 200rpx;
+ flex-shrink: 0;
+ transition: all 0.2s ease;
+ &:focus-within {
+ background: #ffffff;
+ border-color: #00d26a;
+ box-shadow: 0 0 0 2rpx rgba(0, 210, 106, 0.15);
+ }
+}
+.cat-subcard__search-icon {
+ width: 24rpx;
+ height: 24rpx;
+ flex-shrink: 0;
+ opacity: 0.6;
+}
+.cat-subcard__search-input {
+ flex: 1;
+ height: 100%;
+ font-size: 21rpx;
+ color: #1e293b;
+ padding: 0 6rpx;
+ min-width: 0;
+}
+.cat-subcard__search-ph {
+ font-size: 21rpx;
+ color: #94a3b8;
+}
+.cat-subcard__search-clear {
+ width: 28rpx;
+ height: 28rpx;
+ border-radius: 50%;
+ background: #cbd5e1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+}
+.cat-subcard__search-clear-txt {
+ font-size: 19rpx;
+ color: #ffffff;
+ line-height: 1;
+ margin-top: -2rpx;
+}
+.cat-subgrid-empty {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 36rpx 16rpx;
+ gap: 12rpx;
+}
+.cat-subgrid-empty__txt {
+ font-size: 23rpx;
+ color: #94a3b8;
+}
+.cat-subgrid-empty__clear {
font-size: 22rpx;
color: #00a854;
+ background: #ecfdf5;
+ padding: 6rpx 20rpx;
+ border-radius: 999rpx;
font-weight: 600;
}
/* 二级品类宫格:≤9 个自适应高度不滚动;>9 个锁 3 行高度(474rpx)区域内上下滚动 */
@@ -980,13 +1308,17 @@ export default {
display: flex;
flex-direction: column;
align-items: center;
- padding: 8rpx 6rpx 16rpx;
+ padding: 10rpx 6rpx 14rpx;
box-sizing: border-box;
+ position: relative;
+ transition: all 0.15s ease;
+
&--active {
.cat-subgrid__thumb {
border-color: #00d26a;
background: #ecfdf5;
- box-shadow: 0 4rpx 12rpx rgba(0, 210, 106, 0.22);
+ box-shadow: 0 6rpx 16rpx rgba(0, 210, 106, 0.26);
+ transform: scale(1.03);
}
.cat-subgrid__name {
color: #00a854;
@@ -995,29 +1327,53 @@ export default {
}
}
.cat-subgrid__thumb {
- width: 96rpx;
- height: 96rpx;
- border-radius: 24rpx;
+ width: 98rpx;
+ height: 98rpx;
+ border-radius: 22rpx;
background: #f8fafc;
- border: 2rpx solid transparent;
+ border: 2.5rpx solid transparent;
display: flex;
align-items: center;
justify-content: center;
- padding: 8rpx;
box-sizing: border-box;
- transition: all 0.15s ease;
+ position: relative;
+ overflow: hidden;
+ transition: all 0.18s ease;
}
.cat-subgrid__img {
width: 100%;
height: 100%;
- border-radius: 16rpx;
+ display: block;
+}
+/* 选中态右上角微质感小圆勾 */
+.cat-subgrid__badge {
+ position: absolute;
+ right: 4rpx;
+ top: 4rpx;
+ width: 26rpx;
+ height: 26rpx;
+ border-radius: 50%;
+ background: #00d26a;
+ color: #ffffff;
+ font-size: 18rpx;
+ font-weight: 800;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ line-height: 1;
+ box-shadow: 0 2rpx 6rpx rgba(0, 210, 106, 0.4);
+ z-index: 2;
}
.cat-subgrid__name {
- margin-top: 8rpx;
+ margin-top: 10rpx;
font-size: 23rpx;
color: #334155;
text-align: center;
line-height: 1.25;
+ max-width: 100%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
/* 排序切换:轻巧微胶囊风格(价格项带升/降序双三角,右侧为区域筛选) */
@@ -1025,26 +1381,26 @@ export default {
display: flex;
align-items: center;
background: #ffffff;
- border-radius: $fc-radius;
- padding: 6rpx 10rpx;
+ border-radius: 20rpx;
+ padding: 8rpx 12rpx;
margin-bottom: 14rpx;
- box-shadow: 0 2rpx 8rpx rgba(4, 48, 30, 0.04);
+ box-shadow: 0 2rpx 10rpx rgba(4, 48, 30, 0.04);
}
.cat-sort__item {
cursor: pointer;
display: inline-flex;
align-items: center;
flex-shrink: 0;
- font-size: 23rpx;
- color: $fc-text-secondary;
- padding: 8rpx 10rpx;
+ font-size: 24rpx;
+ color: #64748b;
+ padding: 8rpx 14rpx;
border-radius: 999rpx;
transition: all 0.15s ease;
&--active {
- color: $fc-primary-text;
+ color: #00a854;
font-weight: 700;
- background: $fc-primary-lighter;
+ background: #ecfdf5;
}
}
/* 价格排序双三角指示器(未选中灰、选中主题绿) */
@@ -1085,6 +1441,11 @@ export default {
background: #f2fef7;
border: 1rpx solid rgba(0, 168, 84, 0.2);
border-radius: 999rpx;
+ cursor: pointer;
+ transition: opacity 0.15s ease;
+ &:active {
+ opacity: 0.8;
+ }
}
.cat-sort__area-icon {
width: 24rpx;
@@ -1096,7 +1457,7 @@ export default {
font-size: 22rpx;
color: #00a854;
font-weight: 600;
- max-width: 96rpx;
+ max-width: 120rpx;
}
.cat-sort__area-arrow {
font-size: 18rpx;
@@ -1104,37 +1465,200 @@ export default {
margin-left: 2rpx;
}
-/* 信息流列表 */
+/* 骨架屏微光流卡片 */
+.cat-skeleton-wrap {
+ display: flex;
+ flex-direction: column;
+ gap: 14rpx;
+ margin-top: 4rpx;
+}
+.cat-skeleton-card {
+ background: #ffffff;
+ border-radius: 20rpx;
+ padding: 16rpx;
+ display: flex;
+ gap: 16rpx;
+ box-shadow: 0 2rpx 8rpx rgba(4, 48, 30, 0.03);
+}
+.cat-skeleton-thumb {
+ width: 140rpx;
+ height: 140rpx;
+ border-radius: 16rpx;
+ flex-shrink: 0;
+ background: #edf3f0;
+}
+.cat-skeleton-info {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ padding: 4rpx 0;
+}
+.cat-skeleton-line {
+ height: 26rpx;
+ border-radius: 8rpx;
+ background: #edf3f0;
+ &--title {
+ width: 85%;
+ }
+ &--sub {
+ width: 55%;
+ height: 22rpx;
+ }
+}
+.cat-skeleton-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+.cat-skeleton-pill {
+ width: 90rpx;
+ height: 28rpx;
+ border-radius: 8rpx;
+ background: #edf3f0;
+}
+.cat-skeleton-price {
+ width: 110rpx;
+ height: 32rpx;
+ border-radius: 8rpx;
+ background: #edf3f0;
+}
+
+/* 呼吸微光动效 */
+.pulse-shimmer {
+ animation: pulseShimmer 1.4s ease-in-out infinite;
+}
+@keyframes pulseShimmer {
+ 0% {
+ opacity: 0.55;
+ background: #edf5f0;
+ }
+ 50% {
+ opacity: 1;
+ background: #d8eee1;
+ }
+ 100% {
+ opacity: 0.55;
+ background: #edf5f0;
+ }
+}
+
+/* 信息流列表:支持平滑遮罩切换防闪烁 */
.cat-list {
display: flex;
flex-direction: column;
-}
-.cat-loading,
-.cat-nomore {
- text-align: center;
- padding: 24rpx 0;
- font-size: 22rpx;
- color: $fc-text-placeholder;
+ transition: opacity 0.18s ease;
+
+ &--switching {
+ opacity: 0.55;
+ pointer-events: none;
+ }
}
-/* 空状态卡片 */
-.cat-empty-wrap {
- padding: 60rpx 0;
+/* 底部加载中指示条 */
+.cat-loading-bar {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 24rpx 0;
+ gap: 12rpx;
+}
+.cat-loading-spinner {
+ width: 28rpx;
+ height: 28rpx;
+ border: 3rpx solid #d1fae5;
+ border-top-color: #00d26a;
+ border-radius: 50%;
+ animation: catSpin 0.7s linear infinite;
+}
+@keyframes catSpin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+.cat-loading-txt {
+ font-size: 22rpx;
+ color: #64748b;
+}
+
+/* 触底提示条 */
+.cat-nomore-bar {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 28rpx 0;
+}
+.cat-nomore-txt {
+ font-size: 22rpx;
+ color: #94a3b8;
+ letter-spacing: 0.5rpx;
+}
+
+/* 紧凑微质感空状态卡片:首屏完整呈现,双引导操作 */
+.cat-empty-card {
+ background: #ffffff;
+ border-radius: 20rpx;
+ padding: 44rpx 20rpx 40rpx;
+ margin-top: 4rpx;
display: flex;
flex-direction: column;
align-items: center;
+ box-shadow: 0 2rpx 10rpx rgba(4, 48, 30, 0.04);
}
-.cat-empty-btn {
- margin-top: 30rpx;
- height: 68rpx;
- line-height: 68rpx;
- padding: 0 44rpx;
- background: $fc-gradient-primary;
- color: $fc-primary-ink;
+.cat-empty-card__icon {
+ width: 90rpx;
+ height: 90rpx;
+ margin-bottom: 14rpx;
+ opacity: 0.85;
+}
+.cat-empty-card__title {
font-size: 26rpx;
font-weight: 700;
- border-radius: 34rpx;
- box-shadow: 0 6rpx 18rpx rgba(0, 224, 112, 0.4);
+ color: #1e293b;
+ text-align: center;
+ line-height: 1.4;
+ max-width: 92%;
+}
+.cat-empty-card__desc {
+ margin-top: 8rpx;
+ font-size: 22rpx;
+ color: #94a3b8;
+ text-align: center;
+}
+.cat-empty-card__actions {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 16rpx;
+ margin-top: 26rpx;
+ flex-wrap: wrap;
+}
+.cat-empty-card__btn {
+ height: 64rpx;
+ line-height: 64rpx;
+ padding: 0 32rpx;
+ border-radius: 999rpx;
+ font-size: 24rpx;
+ font-weight: 600;
+ margin: 0;
+ border: none;
+ &::after {
+ border: none;
+ }
+ &--primary {
+ background: $fc-gradient-primary;
+ color: $fc-primary-ink;
+ box-shadow: 0 4rpx 14rpx rgba(0, 224, 112, 0.32);
+ }
+ &--sub {
+ background: #f1f5f9;
+ color: #475569;
+ border: 1rpx solid #e2e8f0;
+ }
+ &:active {
+ transform: scale(0.97);
+ opacity: 0.9;
+ }
}
.cat-content__space {
diff --git a/支付/pub_key.pem b/支付/pub_key.pem
deleted file mode 100644
index a1c834c..0000000
--- a/支付/pub_key.pem
+++ /dev/null
@@ -1,9 +0,0 @@
------BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7QW1+UaVd76VUmnEWZ8Z
-pkUFQcK3QElxwKhb8fuY6i+DZR/i6MNI9GEW2N/4qWa/WRHHx9jwOas8ORyp1f8/
-CgY1aGhC9h/m9B7IJHGb9zJXxQnkJOLaOYk8g5p2wGG1THVLNryy/8KKRwCdZJ/P
-gy5MB3hteK/5rp1/HMnVMdHrCHgt9L+diyNGb7FW6d2RT5vM2+jRrdbpiFwIuQYT
-+uGMQyE9qKdnAlTvqr4J/T0dtdBd6vidEktEDb+UnPsufa5LWk2MbF66diw6TE8w
-lcsX7EvSJEd1tVBHn6MOeHoEs1iqfKI557fCTlLitGk4SszlKusR0OmbrEVhBigV
-uQIDAQAB
------END PUBLIC KEY-----