Browse Source
- 新增文章详情页面组件,用于显示文章内容 - 优化购物车页面样式,增加空购物车状态的透明背景 - 添加多个购物相关 API 接口,包括优惠券、订单等 - 更新环境配置,修改 API 基础 URL - 调整发现页面布局,增加文章详情入口master
4 changed files with 381 additions and 0 deletions
@ -0,0 +1,101 @@ |
|||
import request from '@/utils/request'; |
|||
import type { ApiResult, PageResult } from '@/api/index'; |
|||
import type { ShopArticle, ShopArticleParam } from './model'; |
|||
|
|||
/** |
|||
* 分页查询商品文章 |
|||
*/ |
|||
export async function pageShopArticle(params: ShopArticleParam) { |
|||
const res = await request.get<ApiResult<PageResult<ShopArticle>>>( |
|||
'/shop/shop-article/page', |
|||
params |
|||
); |
|||
if (res.code === 0) { |
|||
return res.data; |
|||
} |
|||
return Promise.reject(new Error(res.message)); |
|||
} |
|||
|
|||
/** |
|||
* 查询商品文章列表 |
|||
*/ |
|||
export async function listShopArticle(params?: ShopArticleParam) { |
|||
const res = await request.get<ApiResult<ShopArticle[]>>( |
|||
'/shop/shop-article', |
|||
params |
|||
); |
|||
if (res.code === 0 && res.data) { |
|||
return res.data; |
|||
} |
|||
return Promise.reject(new Error(res.message)); |
|||
} |
|||
|
|||
/** |
|||
* 添加商品文章 |
|||
*/ |
|||
export async function addShopArticle(data: ShopArticle) { |
|||
const res = await request.post<ApiResult<unknown>>( |
|||
'/shop/shop-article', |
|||
data |
|||
); |
|||
if (res.code === 0) { |
|||
return res.message; |
|||
} |
|||
return Promise.reject(new Error(res.message)); |
|||
} |
|||
|
|||
/** |
|||
* 修改商品文章 |
|||
*/ |
|||
export async function updateShopArticle(data: ShopArticle) { |
|||
const res = await request.put<ApiResult<unknown>>( |
|||
'/shop/shop-article', |
|||
data |
|||
); |
|||
if (res.code === 0) { |
|||
return res.message; |
|||
} |
|||
return Promise.reject(new Error(res.message)); |
|||
} |
|||
|
|||
/** |
|||
* 删除商品文章 |
|||
*/ |
|||
export async function removeShopArticle(id?: number) { |
|||
const res = await request.del<ApiResult<unknown>>( |
|||
'/shop/shop-article/' + id |
|||
); |
|||
if (res.code === 0) { |
|||
return res.message; |
|||
} |
|||
return Promise.reject(new Error(res.message)); |
|||
} |
|||
|
|||
/** |
|||
* 批量删除商品文章 |
|||
*/ |
|||
export async function removeBatchShopArticle(data: (number | undefined)[]) { |
|||
const res = await request.del<ApiResult<unknown>>( |
|||
'/shop/shop-article/batch', |
|||
{ |
|||
data |
|||
} |
|||
); |
|||
if (res.code === 0) { |
|||
return res.message; |
|||
} |
|||
return Promise.reject(new Error(res.message)); |
|||
} |
|||
|
|||
/** |
|||
* 根据id查询商品文章 |
|||
*/ |
|||
export async function getShopArticle(id: number) { |
|||
const res = await request.get<ApiResult<ShopArticle>>( |
|||
'/shop/shop-article/' + id |
|||
); |
|||
if (res.code === 0 && res.data) { |
|||
return res.data; |
|||
} |
|||
return Promise.reject(new Error(res.message)); |
|||
} |
@ -0,0 +1,125 @@ |
|||
import type { PageParam } from '@/api/index'; |
|||
|
|||
/** |
|||
* 商品文章 |
|||
*/ |
|||
export interface ShopArticle { |
|||
// 文章ID
|
|||
articleId?: number; |
|||
// 文章标题
|
|||
title?: string; |
|||
// 文章类型 0常规 1视频
|
|||
type?: number; |
|||
// 模型
|
|||
model?: string; |
|||
// 详情页模板
|
|||
detail?: string; |
|||
// 文章分类ID
|
|||
categoryId?: number; |
|||
// 上级id, 0是顶级
|
|||
parentId?: number; |
|||
// 话题
|
|||
topic?: string; |
|||
// 标签
|
|||
tags?: string; |
|||
// 封面图
|
|||
image?: string; |
|||
// 封面图宽
|
|||
imageWidth?: number; |
|||
// 封面图高
|
|||
imageHeight?: number; |
|||
// 付费金额
|
|||
price?: string; |
|||
// 开始时间
|
|||
startTime?: string; |
|||
// 结束时间
|
|||
endTime?: string; |
|||
// 来源
|
|||
source?: string; |
|||
// 产品概述
|
|||
overview?: string; |
|||
// 虚拟阅读量(仅用作展示)
|
|||
virtualViews?: number; |
|||
// 实际阅读量
|
|||
actualViews?: number; |
|||
// 评分
|
|||
rate?: string; |
|||
// 列表显示方式(10小图展示 20大图展示)
|
|||
showType?: number; |
|||
// 访问密码
|
|||
password?: string; |
|||
// 可见类型 0所有人 1登录可见 2密码可见
|
|||
permission?: number; |
|||
// 发布来源客户端 (APP、H5、小程序等)
|
|||
platform?: string; |
|||
// 文章附件
|
|||
files?: string; |
|||
// 视频地址
|
|||
video?: string; |
|||
// 接受的文件类型
|
|||
accept?: string; |
|||
// 经度
|
|||
longitude?: string; |
|||
// 纬度
|
|||
latitude?: string; |
|||
// 所在省份
|
|||
province?: string; |
|||
// 所在城市
|
|||
city?: string; |
|||
// 所在辖区
|
|||
region?: string; |
|||
// 街道地址
|
|||
address?: string; |
|||
// 点赞数
|
|||
likes?: number; |
|||
// 评论数
|
|||
commentNumbers?: number; |
|||
// 提醒谁看
|
|||
toUsers?: string; |
|||
// 作者
|
|||
author?: string; |
|||
// 推荐
|
|||
recommend?: number; |
|||
// 报名人数
|
|||
bmUsers?: number; |
|||
// 用户ID
|
|||
userId?: number; |
|||
// 商户ID
|
|||
merchantId?: number; |
|||
// 项目ID
|
|||
projectId?: number; |
|||
// 语言
|
|||
lang?: string; |
|||
// 关联默认语言的文章ID
|
|||
langArticleId?: number; |
|||
// 是否自动翻译
|
|||
translation?: string; |
|||
// 编辑器类型 0 Markdown编辑器 1 富文本编辑器
|
|||
editor?: string; |
|||
// pdf文件地址
|
|||
pdfUrl?: string; |
|||
// 版本号
|
|||
version?: number; |
|||
// 排序(数字越小越靠前)
|
|||
sortNumber?: number; |
|||
// 备注
|
|||
comments?: string; |
|||
// 状态, 0已发布, 1待审核 2已驳回 3违规内容
|
|||
status?: number; |
|||
// 是否删除, 0否, 1是
|
|||
deleted?: number; |
|||
// 租户id
|
|||
tenantId?: number; |
|||
// 创建时间
|
|||
createTime?: string; |
|||
// 修改时间
|
|||
updateTime?: string; |
|||
} |
|||
|
|||
/** |
|||
* 商品文章搜索条件 |
|||
*/ |
|||
export interface ShopArticleParam extends PageParam { |
|||
articleId?: number; |
|||
keywords?: string; |
|||
} |
@ -0,0 +1,4 @@ |
|||
export default definePageConfig({ |
|||
navigationBarTitleText: '商品文章管理', |
|||
navigationBarTextStyle: 'black' |
|||
}) |
@ -0,0 +1,151 @@ |
|||
import {useState} from "react"; |
|||
import Taro, {useDidShow} from '@tarojs/taro' |
|||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Divider} from '@nutui/nutui-react-taro' |
|||
import {Dongdong, ArrowRight, CheckNormal, Checked} from '@nutui/icons-react-taro' |
|||
import {View} from '@tarojs/components' |
|||
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model"; |
|||
import {listShopUserAddress, removeShopUserAddress, updateShopUserAddress} from "@/api/shop/shopUserAddress"; |
|||
|
|||
const Address = () => { |
|||
const [list, setList] = useState<ShopUserAddress[]>([]) |
|||
const [address, setAddress] = useState<ShopUserAddress>() |
|||
|
|||
const reload = () => { |
|||
listShopUserAddress({ |
|||
userId: Taro.getStorageSync('UserId') |
|||
}) |
|||
.then(data => { |
|||
setList(data || []) |
|||
// 默认地址
|
|||
setAddress(data.find(item => item.isDefault)) |
|||
}) |
|||
.catch(() => { |
|||
Taro.showToast({ |
|||
title: '获取地址失败', |
|||
icon: 'error' |
|||
}); |
|||
}) |
|||
} |
|||
|
|||
const onDefault = async (item: ShopUserAddress) => { |
|||
if (address) { |
|||
await updateShopUserAddress({ |
|||
...address, |
|||
isDefault: false |
|||
}) |
|||
} |
|||
await updateShopUserAddress({ |
|||
id: item.id, |
|||
isDefault: true |
|||
}) |
|||
Taro.showToast({ |
|||
title: '设置成功', |
|||
icon: 'success' |
|||
}); |
|||
reload(); |
|||
} |
|||
|
|||
const onDel = async (id?: number) => { |
|||
await removeShopUserAddress(id) |
|||
Taro.showToast({ |
|||
title: '删除成功', |
|||
icon: 'success' |
|||
}); |
|||
reload(); |
|||
} |
|||
|
|||
const selectAddress = async (item: ShopUserAddress) => { |
|||
if (address) { |
|||
await updateShopUserAddress({ |
|||
...address, |
|||
isDefault: false |
|||
}) |
|||
} |
|||
await updateShopUserAddress({ |
|||
id: item.id, |
|||
isDefault: true |
|||
}) |
|||
setTimeout(() => { |
|||
Taro.navigateBack() |
|||
},500) |
|||
} |
|||
|
|||
useDidShow(() => { |
|||
reload() |
|||
}); |
|||
|
|||
if (list.length == 0) { |
|||
return ( |
|||
<ConfigProvider> |
|||
<div className={'h-full flex flex-col justify-center items-center'} style={{ |
|||
height: 'calc(100vh - 300px)', |
|||
}}> |
|||
<Empty |
|||
style={{ |
|||
backgroundColor: 'transparent' |
|||
}} |
|||
description="您还没有地址哦" |
|||
/> |
|||
<Space> |
|||
<Button onClick={() => Taro.navigateTo({url: '/user/address/add'})}>新增地址</Button> |
|||
<Button type="success" fill="dashed" |
|||
onClick={() => Taro.navigateTo({url: '/user/address/wxAddress'})}>获取微信地址</Button> |
|||
</Space> |
|||
</div> |
|||
</ConfigProvider> |
|||
) |
|||
} |
|||
|
|||
return ( |
|||
<> |
|||
<CellGroup> |
|||
<Cell |
|||
onClick={() => Taro.navigateTo({url: '/user/address/wxAddress'})} |
|||
> |
|||
<div className={'flex justify-between items-center w-full'}> |
|||
<div className={'flex items-center gap-3'}> |
|||
<Dongdong className={'text-green-600'}/> |
|||
<div>获取微信地址</div> |
|||
</div> |
|||
<ArrowRight className={'text-gray-400'}/> |
|||
</div> |
|||
</Cell> |
|||
</CellGroup> |
|||
{list.map((item, _) => ( |
|||
<Cell.Group> |
|||
<Cell className={'flex flex-col gap-1'} onClick={() => selectAddress(item)}> |
|||
<View> |
|||
<View className={'font-medium text-sm'}>{item.name} {item.phone}</View> |
|||
</View> |
|||
<View className={'text-xs'}> |
|||
{item.province} {item.city} {item.region} {item.address} |
|||
</View> |
|||
</Cell> |
|||
<Cell |
|||
align="center" |
|||
title={ |
|||
<View className={'flex items-center gap-1'} onClick={() => onDefault(item)}> |
|||
{item.isDefault ? <Checked className={'text-green-600'} size={16}/> : <CheckNormal size={16}/>} |
|||
<View className={'text-gray-400'}>默认地址</View> |
|||
</View> |
|||
} |
|||
extra={ |
|||
<> |
|||
<View className={'text-gray-400'} onClick={() => onDel(item.id)}> |
|||
删除 |
|||
</View> |
|||
<Divider direction={'vertical'}/> |
|||
<View className={'text-gray-400'} |
|||
onClick={() => Taro.navigateTo({url: '/user/address/add?id=' + item.id})}> |
|||
修改 |
|||
</View> |
|||
</> |
|||
} |
|||
/> |
|||
</Cell.Group> |
|||
))} |
|||
</> |
|||
); |
|||
}; |
|||
|
|||
export default Address; |
Loading…
Reference in new issue