diff --git a/.cursor/mcp.json b/.cursor/mcp.json
new file mode 100644
index 0000000..4bc667d
--- /dev/null
+++ b/.cursor/mcp.json
@@ -0,0 +1,8 @@
+{
+ "mcpServers": {
+ "tdesign-mcp-server": {
+ "command": "npx",
+ "args": ["-y", "tdesign-mcp-server@latest"]
+ }
+ }
+}
\ No newline at end of file
diff --git a/backend/application/api/controller/Catalog.php b/backend/application/api/controller/Catalog.php
index 89d7281..5e8b0a6 100644
--- a/backend/application/api/controller/Catalog.php
+++ b/backend/application/api/controller/Catalog.php
@@ -4,9 +4,7 @@ namespace app\api\controller;
use app\common\controller\Api;
use app\common\service\CategoryService;
-use fast\Tree;
use think\exception\HttpResponseException;
-use think\Validate;
class Catalog extends Api
{
@@ -16,16 +14,16 @@ class Catalog extends Api
/**
* 分类列表
*
- * @ApiMethod (POST)
- * @param string $desc 需求描述
- * @param array $images 图片数组
- * @param array $files 文件数组
- * @param string $contact 联系方式
+ * @ApiMethod (GET)
+ * @param string $type 栏目类型,banner 时返回首页轮播(name、image、description)
*/
public function index()
{
try {
- $params = $this->request->get();
+ $type = (string)$this->request->get('type', '');
+ if ($type === 'banner') {
+ $this->success('', CategoryService::getBannerList());
+ }
$cateList = CategoryService::getOptions();
$res = [
['text' => '全部', 'key' => 0]
diff --git a/backend/application/common/service/CategoryService.php b/backend/application/common/service/CategoryService.php
index b593509..04d7613 100644
--- a/backend/application/common/service/CategoryService.php
+++ b/backend/application/common/service/CategoryService.php
@@ -29,6 +29,28 @@ class CategoryService
return $list;
}
+ /**
+ * 首页轮播:分类类型 banner,仅正常状态,按权重从高到低
+ * @return array
+ */
+ public static function getBannerList()
+ {
+ $list = self::getList(['type' => 'banner', 'status' => 'normal'], 0, 'weigh desc,id desc');
+ $rows = [];
+ foreach ($list as $item) {
+ $image = (string)($item['image'] ?? '');
+ if ($image === '') {
+ continue;
+ }
+ $rows[] = [
+ 'name' => (string)($item['name'] ?? ''),
+ 'image' => cdnurl($image, true),
+ 'description' => (string)($item['description'] ?? ''),
+ ];
+ }
+ return $rows;
+ }
+
public static function transformTree($data)
{
return array_map(function ($item) {
diff --git a/frontend/miniapp/pages/goods/details/index.wxml b/frontend/miniapp/pages/goods/details/index.wxml
index 32e171c..e6f4568 100644
--- a/frontend/miniapp/pages/goods/details/index.wxml
+++ b/frontend/miniapp/pages/goods/details/index.wxml
@@ -4,8 +4,8 @@
-
-
+
+
起
diff --git a/frontend/miniapp/pages/home/home.js b/frontend/miniapp/pages/home/home.js
index 23d828d..7ac0719 100644
--- a/frontend/miniapp/pages/home/home.js
+++ b/frontend/miniapp/pages/home/home.js
@@ -1,4 +1,4 @@
-import { fetchHome, fetchConfig } from '../../services/home/home';
+import { fetchConfig, fetchHomeBanners } from '../../services/home/home';
import { fetchPerson } from '../../services/usercenter/fetchPerson';
import { withPromoter, promoterQuery } from '../../utils/promoter';
@@ -25,7 +25,16 @@ Page({
img1: '',
img2: '',
img3: '',
- tabList: [],
+ bannerList: [], // 首页轮播,项含 value/title/subtitle
+ bannerCurrent: 0, // 当前轮播下标
+ currentBanner: {}, // 当前轮播的标题数据
+ bannerNavigation: {
+ type: 'dots',
+ minShowNum: 2,
+ },
+ bannerImageProps: {
+ mode: 'aspectFill',
+ },
},
demandListPagination: {
@@ -81,23 +90,35 @@ Page({
});
},
- loadHomePage() {
- wx.stopPullDownRefresh();
+ async loadHomePage() {
this.setData({
- pageLoading: true
+ pageLoading: true,
});
- fetchConfig().then(
- (res) => {
- console.log(res);
- if (res.code == 1) {
- let resData = res.data;
- this.setData({
- pageLoading: false,
- tabList: resData.developTypes
- });
- }
+ try {
+ const [configRes, bannerRes] = await Promise.all([fetchConfig(), fetchHomeBanners()]);
+ const next = { pageLoading: false };
+ if (configRes.code === 1) {
+ next.tabList = configRes.data.developTypes || [];
}
- );
+ if (bannerRes.code === 1) {
+ const bannerList = (bannerRes.data || []).map((item) => ({
+ value: item.image || '',
+ ariaLabel: item.name || '',
+ title: item.name || '',
+ subtitle: item.description || '',
+ }));
+ next.bannerList = bannerList;
+ next.bannerCurrent = 0;
+ next.currentBanner = bannerList[0] || {};
+ }
+ this.setData(next);
+ } catch (err) {
+ console.error('loadHomePage failed:', err);
+ this.setData({ pageLoading: false });
+ wx.showToast({ title: '网络异常,请重试', icon: 'none' });
+ } finally {
+ wx.stopPullDownRefresh();
+ }
},
toSubscribe() {
@@ -134,6 +155,17 @@ Page({
});
},
+ onBannerChange(e) {
+ const current = Number((e.detail && e.detail.current) || 0);
+ if (current === this.data.bannerCurrent) {
+ return;
+ }
+ this.setData({
+ bannerCurrent: current,
+ currentBanner: this.data.bannerList[current] || {},
+ });
+ },
+
navToActivityDetail({
detail
}) {
diff --git a/frontend/miniapp/pages/home/home.json b/frontend/miniapp/pages/home/home.json
index f9a281a..6a168ed 100644
--- a/frontend/miniapp/pages/home/home.json
+++ b/frontend/miniapp/pages/home/home.json
@@ -15,8 +15,6 @@
"t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel",
"goods-list": "/components/goods-list/index",
"load-more": "/components/load-more/index",
- "t-grid": "tdesign-miniprogram/grid/grid",
- "t-grid-item": "tdesign-miniprogram/grid-item/grid-item",
"t-cell": "tdesign-miniprogram/cell/cell",
"t-cell-group": "tdesign-miniprogram/cell-group/cell-group",
"t-button": "tdesign-miniprogram/button/button",
diff --git a/frontend/miniapp/pages/home/home.wxml b/frontend/miniapp/pages/home/home.wxml
index b1df012..4e161a4 100644
--- a/frontend/miniapp/pages/home/home.wxml
+++ b/frontend/miniapp/pages/home/home.wxml
@@ -12,17 +12,24 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ {{currentBanner.title}}
+ {{currentBanner.subtitle}}
+
+
diff --git a/frontend/miniapp/pages/home/home.wxss b/frontend/miniapp/pages/home/home.wxss
index aefe73d..af14185 100644
--- a/frontend/miniapp/pages/home/home.wxss
+++ b/frontend/miniapp/pages/home/home.wxss
@@ -97,9 +97,52 @@ page {
margin-bottom: 24rpx;
}
-/* 语言入口宫格 */
+/* 首页轮播:高度对齐原两行编程语言宫格(单项 192rpx × 2 + 卡片上下内边距 32rpx) */
.entry-card {
- padding: 16rpx 8rpx;
+ padding: 0;
+}
+
+.entry-swiper {
+ position: relative;
+ height: 416rpx;
+ --td-swiper-radius: var(--radius-lg);
+ --td-swiper-nav-dot-color: rgba(255, 255, 255, 0.55);
+ --td-swiper-nav-dot-active-color: #ffffff;
+}
+
+.entry-swiper__caption {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 2;
+ padding: 48rpx 24rpx 24rpx;
+ background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.62) 100%);
+ pointer-events: none;
+}
+
+.entry-swiper__title {
+ font-size: 32rpx;
+ font-weight: 600;
+ line-height: 44rpx;
+ color: #ffffff;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
+.entry-swiper__title + .entry-swiper__subtitle {
+ margin-top: 12rpx;
+}
+
+.entry-swiper__subtitle {
+ font-size: 24rpx;
+ line-height: 34rpx;
+ color: rgba(255, 255, 255, 0.9);
+ overflow: hidden;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
}
/* 平台保障 */
diff --git a/frontend/miniapp/services/home/home.js b/frontend/miniapp/services/home/home.js
index e479a7a..acc3aa8 100644
--- a/frontend/miniapp/services/home/home.js
+++ b/frontend/miniapp/services/home/home.js
@@ -57,6 +57,11 @@ export function fetchConfig() {
return wx.$util.request(wx.$api.CommonGetMiniConfig, {}, 'GET');
}
+/** 获取首页轮播(分类类型 banner) */
+export function fetchHomeBanners() {
+ return wx.$util.request(wx.$api.CatalogList, { type: 'banner' }, 'GET');
+}
+
// 与后端 site.platform_commission_ratio 默认值一致,接口失败时兜底
const DEFAULT_COMMISSION_RATIO = 0.1;
let commissionRatioCache = null;