diff --git a/config/env.ts b/config/env.ts index cdc046e..f2afab4 100644 --- a/config/env.ts +++ b/config/env.ts @@ -2,7 +2,7 @@ export const ENV_CONFIG = { // 开发环境 development: { - API_BASE_URL: 'http://127.0.0.1:9200/api', + API_BASE_URL: 'https://cms-api.websoft.top/api', APP_NAME: '时里院子市集', DEBUG: 'true', }, diff --git a/src/api/cms/cmsDesign/index.ts b/src/api/cms/cmsDesign/index.ts index e671736..aa71758 100644 --- a/src/api/cms/cmsDesign/index.ts +++ b/src/api/cms/cmsDesign/index.ts @@ -9,9 +9,7 @@ import type { CmsDesign, CmsDesignParam } from './model'; export async function pageCmsDesign(params: CmsDesignParam) { const res = await request.get>>( '/cms/cms-design/page', - { - params - } + params ); if (res.code === 0) { return res.data; @@ -25,9 +23,7 @@ export async function pageCmsDesign(params: CmsDesignParam) { export async function listCmsDesign(params?: CmsDesignParam) { const res = await request.get>( '/cms/cms-design', - { - params - } + params ); if (res.code === 0 && res.data) { return res.data; diff --git a/src/api/cms/cmsNavigation/model/index.ts b/src/api/cms/cmsNavigation/model/index.ts index 8262bff..421bbc7 100644 --- a/src/api/cms/cmsNavigation/model/index.ts +++ b/src/api/cms/cmsNavigation/model/index.ts @@ -1,6 +1,7 @@ import type {PageParam} from '@/api/index'; import type {CmsDesign} from "@/api/cms/cmsDesign/model"; import type {CmsModel} from "@/api/cms/cmsModel/model"; +import {CmsArticle} from "@/api/cms/cmsArticle/model"; /** * 网站导航记录表 @@ -100,6 +101,8 @@ export interface CmsNavigation { label?: string; // 值 value?: number; + // 文章列表 + articles?: CmsArticle[]; } /** diff --git a/src/api/cms/cmsWebsiteField/index.ts b/src/api/cms/cmsWebsiteField/index.ts index 7094a4c..a302056 100644 --- a/src/api/cms/cmsWebsiteField/index.ts +++ b/src/api/cms/cmsWebsiteField/index.ts @@ -120,9 +120,7 @@ export async function undeleteWebsiteField(id?: number) { export async function configWebsiteField(params?: CmsWebsiteFieldParam) { const res = await request.get>( '/cms/cms-website-field/config', - { - params - } + params ); if (res.code === 0 && res.data) { return res.data; diff --git a/src/api/cms/cmsWebsiteField/model/index.ts b/src/api/cms/cmsWebsiteField/model/index.ts index 36560d1..3a13b4a 100644 --- a/src/api/cms/cmsWebsiteField/model/index.ts +++ b/src/api/cms/cmsWebsiteField/model/index.ts @@ -48,6 +48,7 @@ export interface Config { loginBgImg?: string; address?: string; tel?: string; + workDay?: string; kefu2?: string; kefu1?: string; email?: string; diff --git a/src/api/system/file/index.ts b/src/api/system/file/index.ts index 8087554..18a06dd 100644 --- a/src/api/system/file/index.ts +++ b/src/api/system/file/index.ts @@ -21,7 +21,7 @@ export async function uploadOssByPath(filePath: string) { let stsExpired = Taro.getStorageSync('stsExpiredAt'); if (!sts || (stsExpired && dayjs().isBefore(dayjs(stsExpired)))) { // @ts-ignore - const {data: {data: {credentials}}} = await request.get(`https://server.gxwebsoft.com/api/oss/getSTSToken`) + const {data: {data: {credentials}}} = await request.get(`https://server.websoft.top/api/oss/getSTSToken`) Taro.setStorageSync('sts', credentials) Taro.setStorageSync('stsExpiredAt', credentials.expiration) sts = credentials @@ -66,7 +66,7 @@ export async function uploadFile() { const tempFilePath = res.tempFilePaths[0]; // 上传图片到OSS Taro.uploadFile({ - url: 'https://server.gxwebsoft.com/api/oss/upload', + url: 'https://server.websoft.top/api/oss/upload', filePath: tempFilePath, name: 'file', header: { diff --git a/src/app.config.ts b/src/app.config.ts index ce4ddaa..4414b4d 100644 --- a/src/app.config.ts +++ b/src/app.config.ts @@ -46,7 +46,8 @@ export default defineAppConfig({ 'orderDetail/index', 'goodsDetail/index', 'orderConfirm/index', - 'orderConfirmCart/index' + 'orderConfirmCart/index', + 'search/index' ] } ], diff --git a/src/cms/detail/index.tsx b/src/cms/detail/index.tsx index b0ef53a..f92c890 100644 --- a/src/cms/detail/index.tsx +++ b/src/cms/detail/index.tsx @@ -42,7 +42,7 @@ function Detail() {
{item?.title}
{item?.createTime}
- + diff --git a/src/components/PayRecord.tsx b/src/components/PayRecord.tsx index 5763bdf..d01b5cf 100644 --- a/src/components/PayRecord.tsx +++ b/src/components/PayRecord.tsx @@ -38,7 +38,7 @@ function PayRecord() { const reloadMore = async () => { setPage(page + 1) - reload(); + reload().then(); } useEffect(() => { diff --git a/src/pages/index/Header.tsx b/src/pages/index/Header.tsx index f2a4564..980c3e8 100644 --- a/src/pages/index/Header.tsx +++ b/src/pages/index/Header.tsx @@ -93,7 +93,7 @@ const Header = (props: any) => { success: function () { if (code) { Taro.request({ - url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone', + url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone', method: 'POST', data: { code, @@ -143,7 +143,7 @@ const Header = (props: any) => {
- + {/*{!props.stickyStatus && }*/}
{ success: function () { if (code) { Taro.request({ - url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone', + url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone', method: 'POST', data: { code, diff --git a/src/pages/index/MySearch.tsx b/src/pages/index/MySearch.tsx index 867982a..be1f641 100644 --- a/src/pages/index/MySearch.tsx +++ b/src/pages/index/MySearch.tsx @@ -2,7 +2,8 @@ import {Search} from '@nutui/icons-react-taro' import {Button, Input} from '@nutui/nutui-react-taro' import {useState} from "react"; import Taro from '@tarojs/taro'; -function MySearch(props) { + +function MySearch() { const [keywords, setKeywords] = useState('') const onKeywords = (keywords: string) => { @@ -10,14 +11,24 @@ function MySearch(props) { } const onQuery = () => { - if(!keywords){ + if(!keywords.trim()){ Taro.showToast({ title: '请输入关键字', icon: 'none' }); return false; } - props.done(keywords); + // 跳转到搜索页面 + Taro.navigateTo({ + url: `/shop/search/index?keywords=${encodeURIComponent(keywords.trim())}` + }); + } + + // 点击搜索框跳转到搜索页面 + const onInputFocus = () => { + Taro.navigateTo({ + url: '/shop/search/index' + }); } @@ -40,6 +51,7 @@ function MySearch(props) { value={keywords} onChange={onKeywords} onConfirm={onQuery} + onFocus={onInputFocus} style={{ padding: '9px 8px'}} />
= ({ onSearch, onReset }) => { if (searchParams.phone?.trim()) { filterParams.phone = searchParams.phone.trim(); } - if (searchParams.orderStatus !== undefined && searchParams.orderStatus !== '') { - filterParams.orderStatus = Number(searchParams.orderStatus); + if (searchParams.orderStatus !== undefined) { + filterParams.orderStatus = searchParams.orderStatus; } - if (searchParams.payStatus !== undefined && searchParams.payStatus !== '') { - filterParams.payStatus = Number(searchParams.payStatus); + if (searchParams.payStatus !== undefined) { + filterParams.payStatus = searchParams.payStatus; } - if (searchParams.payType !== undefined && searchParams.payType !== '') { - filterParams.payType = Number(searchParams.payType); + if (searchParams.payType !== undefined) { + filterParams.payType = searchParams.payType; } onSearch(filterParams); @@ -186,7 +183,7 @@ const OrderSearch: React.FC = ({ onSearch, onReset }) => { 订单状态 setSearchParams(prev => ({ ...prev, orderStatus: value }))} + onChange={(value) => setSearchParams(prev => ({ ...prev, orderStatus: Number(value) }))} > {orderStatusOptions.map((option) => ( @@ -205,7 +202,7 @@ const OrderSearch: React.FC = ({ onSearch, onReset }) => { 支付状态 setSearchParams(prev => ({ ...prev, payStatus: value }))} + onChange={(value) => setSearchParams(prev => ({ ...prev, payStatus: Number(value) }))} > {payStatusOptions.map((option) => ( @@ -224,7 +221,7 @@ const OrderSearch: React.FC = ({ onSearch, onReset }) => { 支付方式 setSearchParams(prev => ({ ...prev, payType: value }))} + onChange={(value) => setSearchParams(prev => ({ ...prev, payType: Number(value) }))} > {payTypeOptions.map((option) => ( diff --git a/src/pages/user/components/OrderIcon.tsx b/src/pages/user/components/OrderIcon.tsx index ff3bea1..9cc9a61 100644 --- a/src/pages/user/components/OrderIcon.tsx +++ b/src/pages/user/components/OrderIcon.tsx @@ -25,7 +25,7 @@ const OrderIcon = () => { success: function () { if (code) { Taro.request({ - url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone', + url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone', method: 'POST', data: { code, diff --git a/src/pages/user/components/UserCard.tsx b/src/pages/user/components/UserCard.tsx index 41bb0e7..2394f80 100644 --- a/src/pages/user/components/UserCard.tsx +++ b/src/pages/user/components/UserCard.tsx @@ -107,7 +107,7 @@ function UserCard() { success: function () { if (code) { Taro.request({ - url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone', + url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone', method: 'POST', data: { code, diff --git a/src/shop/search/components/GoodsItem.scss b/src/shop/search/components/GoodsItem.scss new file mode 100644 index 0000000..7d04fe0 --- /dev/null +++ b/src/shop/search/components/GoodsItem.scss @@ -0,0 +1,33 @@ +// 使用与首页相同的样式,主要依赖Tailwind CSS类名 +.buy-btn { + background: linear-gradient(to right, #1cd98a, #24ca94); + border-radius: 20px; + display: flex; + align-items: center; + justify-content: center; + position: relative; + overflow: hidden; + + .cart-icon { + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 40px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(0, 0, 0, 0.1); + border-radius: 20px 0 0 20px; + } +} + +.car-no { + font-weight: 500; + color: #333; + line-height: 1.4; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; +} diff --git a/src/shop/search/components/GoodsItem.tsx b/src/shop/search/components/GoodsItem.tsx new file mode 100644 index 0000000..e7e22e7 --- /dev/null +++ b/src/shop/search/components/GoodsItem.tsx @@ -0,0 +1,58 @@ +import { View } from '@tarojs/components' +import { Image } from '@nutui/nutui-react-taro' +import { Share } from '@nutui/icons-react-taro' +import Taro from '@tarojs/taro' +import { ShopGoods } from '@/api/shop/shopGoods/model' +import './GoodsItem.scss' + +interface GoodsItemProps { + goods: ShopGoods +} + +const GoodsItem = ({ goods }: GoodsItemProps) => { + // 跳转到商品详情 + const goToDetail = () => { + Taro.navigateTo({ + url: `/shop/goodsDetail/index?id=${goods.goodsId}` + }) + } + + return ( +
+ +
+
+
{goods.name || goods.goodsName}
+
+ {goods.comments || ''} + 已售 {goods.sales || 0} +
+
+
+ + {goods.price || '0.00'} +
+
+
+ +
+
购买 +
+
+
+
+
+
+ ) +} + +export default GoodsItem diff --git a/src/shop/search/index.config.ts b/src/shop/search/index.config.ts new file mode 100644 index 0000000..1473122 --- /dev/null +++ b/src/shop/search/index.config.ts @@ -0,0 +1,3 @@ +export default definePageConfig({ + navigationBarTitleText: '商品搜索' +}) diff --git a/src/shop/search/index.scss b/src/shop/search/index.scss new file mode 100644 index 0000000..30a45f4 --- /dev/null +++ b/src/shop/search/index.scss @@ -0,0 +1,103 @@ +.search-page { + min-height: 100vh; + background: #f5f5f5; + + // 搜索输入框样式 + .search-input-wrapper { + flex: 1; + display: flex; + align-items: center; + background: #f5f5f5; + border-radius: 20px; + padding: 0 12px; + + .search-icon { + color: #999; + margin-right: 8px; + } + + .search-input { + flex: 1; + border: none; + background: transparent; + font-size: 14px; + + input { + background: transparent !important; + } + } + } + + .search-btn { + padding: 0 16px; + height: 36px; + border-radius: 18px; + font-size: 14px; + } + + .search-content { + padding-top: calc(32px + env(safe-area-inset-top)); + + .search-history { + background: #fff; + margin-bottom: 8px; + + .history-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px; + border-bottom: 1px solid #f5f5f5; + + .history-title { + font-size: 16px; + font-weight: 500; + color: #333; + } + + .clear-btn { + font-size: 14px; + color: #999; + cursor: pointer; + } + } + + .history-list { + padding: 16px; + display: flex; + flex-wrap: wrap; + gap: 12px; + + .history-item { + padding: 8px 16px; + background: #f5f5f5; + border-radius: 16px; + color: #666; + cursor: pointer; + + &:active { + background: #e5e5e5; + } + } + } + } + + .search-results { + .result-header { + padding: 16px; + color: #666; + background: #fff; + border-bottom: 1px solid #f5f5f5; + margin-bottom: 8px; + } + + .loading-wrapper { + display: flex; + justify-content: center; + align-items: center; + padding: 40px 0; + background: #fff; + } + } + } +} diff --git a/src/shop/search/index.tsx b/src/shop/search/index.tsx new file mode 100644 index 0000000..b8a401d --- /dev/null +++ b/src/shop/search/index.tsx @@ -0,0 +1,237 @@ +import {useEffect, useState} from 'react' +import {useRouter} from '@tarojs/taro' +import Taro from '@tarojs/taro' +import {View} from '@tarojs/components' +import {Loading, Empty, InfiniteLoading, Input, Button} from '@nutui/nutui-react-taro' +import {Search} from '@nutui/icons-react-taro'; +import {ShopGoods} from '@/api/shop/shopGoods/model' +import {pageShopGoods} from '@/api/shop/shopGoods' +import GoodsItem from './components/GoodsItem' +import './index.scss' + +const SearchPage = () => { + const router = useRouter() + const [keywords, setKeywords] = useState('') + const [goodsList, setGoodsList] = useState([]) + const [loading, setLoading] = useState(false) + const [page, setPage] = useState(1) + const [hasMore, setHasMore] = useState(true) + const [total, setTotal] = useState(0) + const [searchHistory, setSearchHistory] = useState([]) + + // 从路由参数获取搜索关键词 + useEffect(() => { + const {keywords: routeKeywords} = router.params || {} + if (routeKeywords) { + setKeywords(decodeURIComponent(routeKeywords)) + handleSearch(decodeURIComponent(routeKeywords), 1).then() + } + + // 加载搜索历史 + loadSearchHistory() + }, []) + + // 加载搜索历史 + const loadSearchHistory = () => { + try { + const history = Taro.getStorageSync('search_history') || [] + setSearchHistory(history) + } catch (error) { + console.error('加载搜索历史失败:', error) + } + } + + // 保存搜索历史 + const saveSearchHistory = (keyword: string) => { + try { + let history = Taro.getStorageSync('search_history') || [] + // 去重并添加到开头 + history = history.filter(item => item !== keyword) + history.unshift(keyword) + // 只保留最近10条 + history = history.slice(0, 10) + Taro.setStorageSync('search_history', history) + setSearchHistory(history) + } catch (error) { + console.error('保存搜索历史失败:', error) + } + } + + const handleKeywords = (keywords) => { + setKeywords(keywords) + handleSearch(keywords).then() + } + + // 搜索商品 + const handleSearch = async (searchKeywords: string, pageNum: number = 1) => { + if (!searchKeywords.trim()) { + Taro.showToast({ + title: '请输入搜索关键词', + icon: 'none' + }) + return + } + + setLoading(true) + + try { + const params = { + keywords: searchKeywords.trim(), + page: pageNum, + size: 10, + isShow: 1 // 只搜索上架商品 + } + + const result = await pageShopGoods(params) + + if (pageNum === 1) { + setGoodsList(result?.list || []) + setTotal(result?.count || 0) + // 保存搜索历史 + saveSearchHistory(searchKeywords.trim()) + } else { + setGoodsList(prev => [...prev, ...(result?.list || [])]) + } + + setHasMore((result?.list?.length || 0) >= 10) + setPage(pageNum) + + } catch (error) { + console.error('搜索失败:', error) + Taro.showToast({ + title: '搜索失败,请重试', + icon: 'none' + }) + } finally { + setLoading(false) + } + } + + // 加载更多 + const loadMore = () => { + if (!loading && hasMore && keywords.trim()) { + handleSearch(keywords, page + 1).then() + } + } + + // 点击历史搜索 + const onHistoryClick = (keyword: string) => { + setKeywords(keyword) + setPage(1) + handleSearch(keyword, 1) + } + + // 清空搜索历史 + const clearHistory = () => { + Taro.showModal({ + title: '提示', + content: '确定要清空搜索历史吗?', + success: (res) => { + if (res.confirm) { + try { + Taro.removeStorageSync('search_history') + setSearchHistory([]) + } catch (error) { + console.error('清空搜索历史失败:', error) + } + } + } + }) + } + + return ( + +
+
+ + handleSearch(keywords)} + style={{padding: '9px 8px'}} + /> +
+ +
+
+
+ {/**/} + + {/* 搜索内容 */} + + {/* 搜索历史 */} + {!keywords && searchHistory.length > 0 && ( + + + 搜索历史 + 清空 + + + {searchHistory.map((item, index) => ( + onHistoryClick(item)} + > + {item} + + ))} + + + )} + + {/* 搜索结果 */} + {keywords && ( + + {/* 结果统计 */} + + 找到 {total} 件相关商品 + + + {/* 商品列表 */} + {loading && page === 1 ? ( + + 搜索中... + + ) : goodsList.length > 0 ? ( +
+
+ + {goodsList.map((item) => ( + + ))} + +
+
+ ) : ( + + )} +
+ )} +
+
+ ) +} + +export default SearchPage diff --git a/src/user/about/index.tsx b/src/user/about/index.tsx index b179eba..fec73d9 100644 --- a/src/user/about/index.tsx +++ b/src/user/about/index.tsx @@ -1,5 +1,5 @@ import {useEffect, useState} from "react"; -import {CmsArticle} from "@/api/cms/cmsArticle/model"; +import Taro from '@tarojs/taro'; import {listCmsArticle} from "@/api/cms/cmsArticle"; import {Avatar, Cell, Divider} from '@nutui/nutui-react-taro' import {ArrowRight} from '@nutui/icons-react-taro' @@ -7,59 +7,57 @@ import {CmsNavigation} from "@/api/cms/cmsNavigation/model"; import {listCmsNavigation} from "@/api/cms/cmsNavigation"; // 显示html富文本 import {View, RichText} from '@tarojs/components' +import {listCmsDesign} from "@/api/cms/cmsDesign"; +import {CmsDesign} from "@/api/cms/cmsDesign/model"; +import {type Config} from "@/api/cms/cmsWebsiteField/model"; +import {configWebsiteField} from "@/api/cms/cmsWebsiteField"; const Helper = () => { - const [list, setList] = useState([]) const [nav, setNav] = useState() + const [design, setDesign] = useState() const [category, setCategory] = useState([]) + const [config, setConfig] = useState() const reload = async () => { const navs = await listCmsNavigation({model: 'page', parentId: 0}); if (navs.length > 0) { const nav = navs[0]; setNav(nav); + // 查询页面信息 + const design = await listCmsDesign({categoryId: nav.navigationId}) + setDesign(design[0]) // 查询子栏目 const category = await listCmsNavigation({parentId: nav.navigationId}) + category.map(async (item, index) => { + category[index].articles = await listCmsArticle({categoryId: item.navigationId}); + }) setCategory(category) + // 查询字段 + const configInfo = await configWebsiteField({}) + setConfig(configInfo) } - - listCmsArticle({model: 'page'}).then(res => { - setList(res) - }).catch(error => { - console.error("Failed to fetch goods detail:", error); - }) } useEffect(() => { reload().then() }, []); - if (list.length == 0) { - return ( -
- - 暂无数据 - -
- ) - } - return (
{nav && ( - {nav?.comments} + {design?.comments} + nodes={design?.content || '关于我们的简单描述'}/> )} @@ -74,22 +72,21 @@ const Helper = () => { description={( <> - - {item.categoryName} - - - - {item.categoryName} - - + {item.articles?.map((child, _) => ( + + Taro.navigateTo({url: `/cms/detail/index?id=${child.articleId}`})}>{child.title} + + + ))} )} > ))} - 服务热线:0771-88888888 - 工作日:9:00-18:00 + 服务热线:{config?.tel} + 工作日:{config?.workDay}
); diff --git a/src/user/help/index.tsx b/src/user/help/index.tsx index 9789766..e276f9a 100644 --- a/src/user/help/index.tsx +++ b/src/user/help/index.tsx @@ -30,7 +30,7 @@ const Helper = () => { return ( <> - + {navigation && (