Browse Source

修复已知问题

master
科技小王子 2 weeks ago
parent
commit
5dd0e97e3c
  1. 2
      config/env.ts
  2. 4
      src/api/cms/cmsDesign/index.ts
  3. 3
      src/api/cms/cmsNavigation/model/index.ts
  4. 2
      src/api/cms/cmsWebsiteField/index.ts
  5. 1
      src/api/cms/cmsWebsiteField/model/index.ts
  6. 4
      src/api/system/file/index.ts
  7. 3
      src/app.config.ts
  8. 2
      src/cms/detail/index.tsx
  9. 2
      src/components/PayRecord.tsx
  10. 4
      src/pages/index/Header.tsx
  11. 2
      src/pages/index/Login.tsx
  12. 18
      src/pages/index/MySearch.tsx
  13. 23
      src/pages/order/components/OrderSearch.tsx
  14. 2
      src/pages/user/components/OrderIcon.tsx
  15. 2
      src/pages/user/components/UserCard.tsx
  16. 33
      src/shop/search/components/GoodsItem.scss
  17. 58
      src/shop/search/components/GoodsItem.tsx
  18. 3
      src/shop/search/index.config.ts
  19. 103
      src/shop/search/index.scss
  20. 237
      src/shop/search/index.tsx
  21. 53
      src/user/about/index.tsx
  22. 2
      src/user/help/index.tsx
  23. 2
      src/user/profile/profile.tsx
  24. 11
      start-claude.sh

2
config/env.ts

@ -2,7 +2,7 @@
export const ENV_CONFIG = { export const ENV_CONFIG = {
// 开发环境 // 开发环境
development: { development: {
API_BASE_URL: 'http://127.0.0.1:9200/api',
API_BASE_URL: 'https://cms-api.websoft.top/api',
APP_NAME: '时里院子市集', APP_NAME: '时里院子市集',
DEBUG: 'true', DEBUG: 'true',
}, },

4
src/api/cms/cmsDesign/index.ts

@ -9,9 +9,7 @@ import type { CmsDesign, CmsDesignParam } from './model';
export async function pageCmsDesign(params: CmsDesignParam) { export async function pageCmsDesign(params: CmsDesignParam) {
const res = await request.get<ApiResult<PageResult<CmsDesign>>>( const res = await request.get<ApiResult<PageResult<CmsDesign>>>(
'/cms/cms-design/page', '/cms/cms-design/page',
{
params params
}
); );
if (res.code === 0) { if (res.code === 0) {
return res.data; return res.data;
@ -25,9 +23,7 @@ export async function pageCmsDesign(params: CmsDesignParam) {
export async function listCmsDesign(params?: CmsDesignParam) { export async function listCmsDesign(params?: CmsDesignParam) {
const res = await request.get<ApiResult<CmsDesign[]>>( const res = await request.get<ApiResult<CmsDesign[]>>(
'/cms/cms-design', '/cms/cms-design',
{
params params
}
); );
if (res.code === 0 && res.data) { if (res.code === 0 && res.data) {
return res.data; return res.data;

3
src/api/cms/cmsNavigation/model/index.ts

@ -1,6 +1,7 @@
import type {PageParam} from '@/api/index'; import type {PageParam} from '@/api/index';
import type {CmsDesign} from "@/api/cms/cmsDesign/model"; import type {CmsDesign} from "@/api/cms/cmsDesign/model";
import type {CmsModel} from "@/api/cms/cmsModel/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; label?: string;
// 值 // 值
value?: number; value?: number;
// 文章列表
articles?: CmsArticle[];
} }
/** /**

2
src/api/cms/cmsWebsiteField/index.ts

@ -120,9 +120,7 @@ export async function undeleteWebsiteField(id?: number) {
export async function configWebsiteField(params?: CmsWebsiteFieldParam) { export async function configWebsiteField(params?: CmsWebsiteFieldParam) {
const res = await request.get<ApiResult<Config>>( const res = await request.get<ApiResult<Config>>(
'/cms/cms-website-field/config', '/cms/cms-website-field/config',
{
params params
}
); );
if (res.code === 0 && res.data) { if (res.code === 0 && res.data) {
return res.data; return res.data;

1
src/api/cms/cmsWebsiteField/model/index.ts

@ -48,6 +48,7 @@ export interface Config {
loginBgImg?: string; loginBgImg?: string;
address?: string; address?: string;
tel?: string; tel?: string;
workDay?: string;
kefu2?: string; kefu2?: string;
kefu1?: string; kefu1?: string;
email?: string; email?: string;

4
src/api/system/file/index.ts

@ -21,7 +21,7 @@ export async function uploadOssByPath(filePath: string) {
let stsExpired = Taro.getStorageSync('stsExpiredAt'); let stsExpired = Taro.getStorageSync('stsExpiredAt');
if (!sts || (stsExpired && dayjs().isBefore(dayjs(stsExpired)))) { if (!sts || (stsExpired && dayjs().isBefore(dayjs(stsExpired)))) {
// @ts-ignore // @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('sts', credentials)
Taro.setStorageSync('stsExpiredAt', credentials.expiration) Taro.setStorageSync('stsExpiredAt', credentials.expiration)
sts = credentials sts = credentials
@ -66,7 +66,7 @@ export async function uploadFile() {
const tempFilePath = res.tempFilePaths[0]; const tempFilePath = res.tempFilePaths[0];
// 上传图片到OSS // 上传图片到OSS
Taro.uploadFile({ Taro.uploadFile({
url: 'https://server.gxwebsoft.com/api/oss/upload',
url: 'https://server.websoft.top/api/oss/upload',
filePath: tempFilePath, filePath: tempFilePath,
name: 'file', name: 'file',
header: { header: {

3
src/app.config.ts

@ -46,7 +46,8 @@ export default defineAppConfig({
'orderDetail/index', 'orderDetail/index',
'goodsDetail/index', 'goodsDetail/index',
'orderConfirm/index', 'orderConfirm/index',
'orderConfirmCart/index'
'orderConfirmCart/index',
'search/index'
] ]
} }
], ],

2
src/cms/detail/index.tsx

@ -42,7 +42,7 @@ function Detail() {
<div className={'bg-white'}> <div className={'bg-white'}>
<div className={'p-4 font-bold text-lg'}>{item?.title}</div> <div className={'p-4 font-bold text-lg'}>{item?.title}</div>
<div className={'text-gray-400 text-sm px-4 '}>{item?.createTime}</div> <div className={'text-gray-400 text-sm px-4 '}>{item?.createTime}</div>
<View className={'content px-3'}>
<View className={'content p-4'}>
<RichText nodes={item?.content}/> <RichText nodes={item?.content}/>
</View> </View>
<Line height={44}/> <Line height={44}/>

2
src/components/PayRecord.tsx

@ -38,7 +38,7 @@ function PayRecord() {
const reloadMore = async () => { const reloadMore = async () => {
setPage(page + 1) setPage(page + 1)
reload();
reload().then();
} }
useEffect(() => { useEffect(() => {

4
src/pages/index/Header.tsx

@ -93,7 +93,7 @@ const Header = (props: any) => {
success: function () { success: function () {
if (code) { if (code) {
Taro.request({ Taro.request({
url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone',
url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone',
method: 'POST', method: 'POST',
data: { data: {
code, code,
@ -143,7 +143,7 @@ const Header = (props: any) => {
<div className={'fixed top-0 header-bg'} style={{ <div className={'fixed top-0 header-bg'} style={{
height: !props.stickyStatus ? '180px' : '148px', height: !props.stickyStatus ? '180px' : '148px',
}}> }}>
<MySearch done={reload}/>
<MySearch/>
{/*{!props.stickyStatus && <MySearch done={reload}/>}*/} {/*{!props.stickyStatus && <MySearch done={reload}/>}*/}
</div> </div>
<NavBar <NavBar

2
src/pages/index/Login.tsx

@ -16,7 +16,7 @@ const Login = (props:any) => {
success: function () { success: function () {
if (code) { if (code) {
Taro.request({ Taro.request({
url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone',
url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone',
method: 'POST', method: 'POST',
data: { data: {
code, code,

18
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 {Button, Input} from '@nutui/nutui-react-taro'
import {useState} from "react"; import {useState} from "react";
import Taro from '@tarojs/taro'; import Taro from '@tarojs/taro';
function MySearch(props) {
function MySearch() {
const [keywords, setKeywords] = useState<string>('') const [keywords, setKeywords] = useState<string>('')
const onKeywords = (keywords: string) => { const onKeywords = (keywords: string) => {
@ -10,14 +11,24 @@ function MySearch(props) {
} }
const onQuery = () => { const onQuery = () => {
if(!keywords){
if(!keywords.trim()){
Taro.showToast({ Taro.showToast({
title: '请输入关键字', title: '请输入关键字',
icon: 'none' icon: 'none'
}); });
return false; 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} value={keywords}
onChange={onKeywords} onChange={onKeywords}
onConfirm={onQuery} onConfirm={onQuery}
onFocus={onInputFocus}
style={{ padding: '9px 8px'}} style={{ padding: '9px 8px'}}
/> />
<div <div

23
src/pages/order/components/OrderSearch.tsx

@ -7,13 +7,10 @@ import {
Cell, Cell,
CellGroup, CellGroup,
Radio, Radio,
Space,
DatePicker,
Picker
Space
} from '@nutui/nutui-react-taro'; } from '@nutui/nutui-react-taro';
import { Search, Filter, Close } from '@nutui/icons-react-taro'; import { Search, Filter, Close } from '@nutui/icons-react-taro';
import { ShopOrderParam } from '@/api/shop/shopOrder/model'; import { ShopOrderParam } from '@/api/shop/shopOrder/model';
import dayjs from 'dayjs';
import './OrderSearch.scss'; import './OrderSearch.scss';
interface OrderSearchProps { interface OrderSearchProps {
@ -94,14 +91,14 @@ const OrderSearch: React.FC<OrderSearchProps> = ({ onSearch, onReset }) => {
if (searchParams.phone?.trim()) { if (searchParams.phone?.trim()) {
filterParams.phone = 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); onSearch(filterParams);
@ -186,7 +183,7 @@ const OrderSearch: React.FC<OrderSearchProps> = ({ onSearch, onReset }) => {
<View className="text-sm text-gray-600 mb-2"></View> <View className="text-sm text-gray-600 mb-2"></View>
<Radio.Group <Radio.Group
value={searchParams.orderStatus} value={searchParams.orderStatus}
onChange={(value) => setSearchParams(prev => ({ ...prev, orderStatus: value }))}
onChange={(value) => setSearchParams(prev => ({ ...prev, orderStatus: Number(value) }))}
> >
<View className="grid grid-cols-2 gap-2"> <View className="grid grid-cols-2 gap-2">
{orderStatusOptions.map((option) => ( {orderStatusOptions.map((option) => (
@ -205,7 +202,7 @@ const OrderSearch: React.FC<OrderSearchProps> = ({ onSearch, onReset }) => {
<View className="text-sm text-gray-600 mb-2"></View> <View className="text-sm text-gray-600 mb-2"></View>
<Radio.Group <Radio.Group
value={searchParams.payStatus} value={searchParams.payStatus}
onChange={(value) => setSearchParams(prev => ({ ...prev, payStatus: value }))}
onChange={(value) => setSearchParams(prev => ({ ...prev, payStatus: Number(value) }))}
> >
<View className="flex flex-wrap gap-2"> <View className="flex flex-wrap gap-2">
{payStatusOptions.map((option) => ( {payStatusOptions.map((option) => (
@ -224,7 +221,7 @@ const OrderSearch: React.FC<OrderSearchProps> = ({ onSearch, onReset }) => {
<View className="text-sm text-gray-600 mb-2"></View> <View className="text-sm text-gray-600 mb-2"></View>
<Radio.Group <Radio.Group
value={searchParams.payType} value={searchParams.payType}
onChange={(value) => setSearchParams(prev => ({ ...prev, payType: value }))}
onChange={(value) => setSearchParams(prev => ({ ...prev, payType: Number(value) }))}
> >
<View className="grid grid-cols-2 gap-2"> <View className="grid grid-cols-2 gap-2">
{payTypeOptions.map((option) => ( {payTypeOptions.map((option) => (

2
src/pages/user/components/OrderIcon.tsx

@ -25,7 +25,7 @@ const OrderIcon = () => {
success: function () { success: function () {
if (code) { if (code) {
Taro.request({ Taro.request({
url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone',
url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone',
method: 'POST', method: 'POST',
data: { data: {
code, code,

2
src/pages/user/components/UserCard.tsx

@ -107,7 +107,7 @@ function UserCard() {
success: function () { success: function () {
if (code) { if (code) {
Taro.request({ Taro.request({
url: 'https://server.gxwebsoft.com/api/wx-login/loginByMpWxPhone',
url: 'https://server.websoft.top/api/wx-login/loginByMpWxPhone',
method: 'POST', method: 'POST',
data: { data: {
code, code,

33
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;
}

58
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 (
<div className={'flex flex-col rounded-lg bg-white shadow-sm w-full mb-5'}>
<Image
src={goods.image || ''}
mode={'aspectFit'}
lazyLoad={false}
radius="10px 10px 0 0"
height="180"
onClick={goToDetail}
/>
<div className={'flex flex-col p-2 rounded-lg'}>
<div>
<div className={'car-no text-sm'}>{goods.name || goods.goodsName}</div>
<div className={'flex justify-between text-xs py-1'}>
<span className={'text-orange-500'}>{goods.comments || ''}</span>
<span className={'text-gray-400'}> {goods.sales || 0}</span>
</div>
<div className={'flex justify-between items-center py-2'}>
<div className={'flex text-red-500 text-xl items-baseline'}>
<span className={'text-xs'}></span>
<span className={'font-bold text-2xl'}>{goods.price || '0.00'}</span>
</div>
<div className={'buy-btn'}>
<div className={'cart-icon'}>
<Share size={20} className={'mx-4 mt-2'}
onClick={goToDetail}/>
</div>
<div className={'text-white pl-4 pr-5'}
onClick={goToDetail}>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default GoodsItem

3
src/shop/search/index.config.ts

@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: '商品搜索'
})

103
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;
}
}
}
}

237
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<string>('')
const [goodsList, setGoodsList] = useState<ShopGoods[]>([])
const [loading, setLoading] = useState(false)
const [page, setPage] = useState(1)
const [hasMore, setHasMore] = useState(true)
const [total, setTotal] = useState(0)
const [searchHistory, setSearchHistory] = useState<string[]>([])
// 从路由参数获取搜索关键词
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 (
<View className="search-page pt-3">
<div className={'px-2'}>
<div
style={{
display: 'flex',
alignItems: 'center',
background: '#ffffff',
padding: '0 5px',
borderRadius: '20px',
marginTop: '5px',
}}
>
<Search size={18} className={'ml-2 text-gray-400'}/>
<Input
placeholder="搜索商品"
value={keywords}
onChange={handleKeywords}
onConfirm={() => handleSearch(keywords)}
style={{padding: '9px 8px'}}
/>
<div
className={'flex items-center'}
>
<Button type="success" style={{background: 'linear-gradient(to bottom, #1cd98a, #24ca94)'}}
onClick={() => handleSearch(keywords)}>
</Button>
</div>
</div>
</div>
{/*<SearchBar style={{height: `${statusBarHeight}px`}} shape="round" placeholder="搜索商品" onChange={setKeywords} onSearch={handleSearch}/>*/}
{/* 搜索内容 */}
<View className="search-content">
{/* 搜索历史 */}
{!keywords && searchHistory.length > 0 && (
<View className="search-history">
<View className="history-header">
<View className="text-sm"></View>
<View className={'text-gray-400'} onClick={clearHistory}></View>
</View>
<View className="history-list">
{searchHistory.map((item, index) => (
<View
key={index}
className="history-item"
onClick={() => onHistoryClick(item)}
>
{item}
</View>
))}
</View>
</View>
)}
{/* 搜索结果 */}
{keywords && (
<View className="search-results">
{/* 结果统计 */}
<View className="result-header">
{total}
</View>
{/* 商品列表 */}
{loading && page === 1 ? (
<View className="loading-wrapper">
<Loading>...</Loading>
</View>
) : goodsList.length > 0 ? (
<div className={'py-3'}>
<div className={'flex flex-col justify-between items-center rounded-lg px-2'}>
<InfiniteLoading
hasMore={hasMore}
// @ts-ignore
onLoadMore={loadMore}
loadingText="加载中..."
loadMoreText="没有更多了"
>
{goodsList.map((item) => (
<GoodsItem key={item.goodsId} goods={item}/>
))}
</InfiniteLoading>
</div>
</div>
) : (
<Empty description="暂无相关商品"/>
)}
</View>
)}
</View>
</View>
)
}
export default SearchPage

53
src/user/about/index.tsx

@ -1,5 +1,5 @@
import {useEffect, useState} from "react"; import {useEffect, useState} from "react";
import {CmsArticle} from "@/api/cms/cmsArticle/model";
import Taro from '@tarojs/taro';
import {listCmsArticle} from "@/api/cms/cmsArticle"; import {listCmsArticle} from "@/api/cms/cmsArticle";
import {Avatar, Cell, Divider} from '@nutui/nutui-react-taro' import {Avatar, Cell, Divider} from '@nutui/nutui-react-taro'
import {ArrowRight} from '@nutui/icons-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"; import {listCmsNavigation} from "@/api/cms/cmsNavigation";
// 显示html富文本 // 显示html富文本
import {View, RichText} from '@tarojs/components' 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 Helper = () => {
const [list, setList] = useState<CmsArticle[]>([])
const [nav, setNav] = useState<CmsNavigation>() const [nav, setNav] = useState<CmsNavigation>()
const [design, setDesign] = useState<CmsDesign>()
const [category, setCategory] = useState<CmsNavigation[]>([]) const [category, setCategory] = useState<CmsNavigation[]>([])
const [config, setConfig] = useState<Config>()
const reload = async () => { const reload = async () => {
const navs = await listCmsNavigation({model: 'page', parentId: 0}); const navs = await listCmsNavigation({model: 'page', parentId: 0});
if (navs.length > 0) { if (navs.length > 0) {
const nav = navs[0]; const nav = navs[0];
setNav(nav); setNav(nav);
// 查询页面信息
const design = await listCmsDesign({categoryId: nav.navigationId})
setDesign(design[0])
// 查询子栏目 // 查询子栏目
const category = await listCmsNavigation({parentId: nav.navigationId}) const category = await listCmsNavigation({parentId: nav.navigationId})
category.map(async (item, index) => {
category[index].articles = await listCmsArticle({categoryId: item.navigationId});
})
setCategory(category) 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(() => { useEffect(() => {
reload().then() reload().then()
}, []); }, []);
if (list.length == 0) {
return (
<div className={'text-center'}>
<View className={'text-gray-500'}>
</View>
</div>
)
}
return ( return (
<div className={'px-3'}> <div className={'px-3'}>
<Cell> <Cell>
{nav && ( {nav && (
<View className={'flex flex-col justify-center items-center w-full'}> <View className={'flex flex-col justify-center items-center w-full'}>
<Avatar <Avatar
src={nav?.icon}
src={design?.photo}
size={'100'} size={'100'}
/> />
<View className={'font-bold text-sm'}> <View className={'font-bold text-sm'}>
{nav?.comments}
{design?.comments}
</View> </View>
<View className={'text-left py-3 text-gray-600'}> <View className={'text-left py-3 text-gray-600'}>
<RichText <RichText
nodes={'时里院子市集是一家B2C模式的会员电商平台,以健康安全食品,中国国家地理标志产品,药食同源产品等为主线,愿景是守护5亿家庭餐桌健康;选品原则是健康,好吃,方便,实惠。通过严格的筛选供货商,从选品、采购发货、仓储物流产品检测、售前售后等各环节严格把控,提升用户满意度。平台采取透明公开化,以持续为用户提供物美价廉的好产品为准准则,为用户创造价值为唯一宗旨,倡导终身用户,终身服务的经营理念。'}/>
nodes={design?.content || '关于我们的简单描述'}/>
</View> </View>
</View> </View>
)} )}
@ -74,22 +72,21 @@ const Helper = () => {
description={( description={(
<> <>
<Divider/> <Divider/>
{item.articles?.map((child, _) => (
<View className={'item flex justify-between items-center my-2'}> <View className={'item flex justify-between items-center my-2'}>
<View>{item.categoryName}</View>
<ArrowRight size={16} className={'text-gray-400'}/>
</View>
<View className={'item flex justify-between items-center my-2'}>
<View>{item.categoryName}</View>
<View
onClick={() => Taro.navigateTo({url: `/cms/detail/index?id=${child.articleId}`})}>{child.title}</View>
<ArrowRight size={16} className={'text-gray-400'}/> <ArrowRight size={16} className={'text-gray-400'}/>
</View> </View>
))}
</> </>
)} )}
> >
</Cell> </Cell>
))} ))}
<Cell className={'flex flex-col'}> <Cell className={'flex flex-col'}>
<span>线0771-88888888</span>
<span>9:00-18:00</span>
<span>线{config?.tel}</span>
<span>{config?.workDay}</span>
</Cell> </Cell>
</div> </div>
); );

2
src/user/help/index.tsx

@ -30,7 +30,7 @@ const Helper = () => {
return ( return (
<> <>
<SearchBar shape="round" maxLength={5} className={'mt-2'} />
<SearchBar shape="round" className={'mt-2'} />
{navigation && ( {navigation && (
<Image <Image
src={navigation.icon} src={navigation.icon}

2
src/user/profile/profile.tsx

@ -73,7 +73,7 @@ function Profile() {
avatar: `${detail.avatarUrl}`, avatar: `${detail.avatarUrl}`,
}) })
Taro.uploadFile({ Taro.uploadFile({
url: 'https://server.gxwebsoft.com/api/oss/upload',
url: 'https://server.websoft.top/api/oss/upload',
filePath: detail.avatarUrl, filePath: detail.avatarUrl,
name: 'file', name: 'file',
header: { header: {

11
start-claude.sh

@ -0,0 +1,11 @@
#!/bin/bash
# 设置代理(根据你的 Clash Verge 配置)
export http_proxy=http://127.0.0.1:7897
export https_proxy=http://127.0.0.1:7897
# 启动 Claude Code
echo "🚀 启动 Claude Code..."
echo "📡 使用代理: $http_proxy"
npx @anthropic-ai/claude-code
Loading…
Cancel
Save