diff --git a/dist.zip b/dist.zip new file mode 100644 index 0000000..bd86060 Binary files /dev/null and b/dist.zip differ diff --git a/src/api/glt/gltTicketTemplate/index.ts b/src/api/glt/gltTicketTemplate/index.ts new file mode 100644 index 0000000..3f3b380 --- /dev/null +++ b/src/api/glt/gltTicketTemplate/index.ts @@ -0,0 +1,105 @@ +import request from '@/utils/request'; +import type { ApiResult, PageResult } from '@/api'; +import type { GltTicketTemplate, GltTicketTemplateParam } from './model'; + +/** + * 分页查询水票 + */ +export async function pageGltTicketTemplate(params: GltTicketTemplateParam) { + const res = await request.get>>( + '/glt/glt-ticket-template/page', + { + params + } + ); + if (res.code === 0) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 查询水票列表 + */ +export async function listGltTicketTemplate(params?: GltTicketTemplateParam) { + const res = await request.get>( + '/glt/glt-ticket-template', + { + params + } + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 添加水票 + */ +export async function addGltTicketTemplate(data: GltTicketTemplate) { + const res = await request.post>( + '/glt/glt-ticket-template', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 修改水票 + */ +export async function updateGltTicketTemplate(data: GltTicketTemplate) { + const res = await request.put>( + '/glt/glt-ticket-template', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 删除水票 + */ +export async function removeGltTicketTemplate(id?: number) { + const res = await request.del>( + '/glt/glt-ticket-template/' + id + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 批量删除水票 + */ +export async function removeBatchGltTicketTemplate(data: (number | undefined)[]) { + const res = await request.del>( + '/glt/glt-ticket-template/batch', + { + data + } + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 根据id查询水票 + */ +export async function getGltTicketTemplate(id: number) { + const res = await request.get>( + '/glt/glt-ticket-template/' + id + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} diff --git a/src/api/glt/gltTicketTemplate/model/index.ts b/src/api/glt/gltTicketTemplate/model/index.ts new file mode 100644 index 0000000..0e18f2a --- /dev/null +++ b/src/api/glt/gltTicketTemplate/model/index.ts @@ -0,0 +1,55 @@ +import type { PageParam } from '@/api'; + +/** + * 水票 + */ +export interface GltTicketTemplate { + // + id?: number; + // 关联商品ID + goodsId?: number; + // 名称 + name?: string; + // 启用 + enabled?: boolean; + // 单位名称 + unitName?: string; + // 最小购买数量 + minBuyQty?: number; + // 起始发送数量 + startSendQty?: number; + // 买赠:买1送4 => gift_multiplier=4 + giftMultiplier?: number; + // 是否把购买量也计入套票总量(默认仅计入赠送量) + includeBuyQty?: boolean; + // 每期释放数量(默认每月释放10) + monthlyReleaseQty?: number; + // 总共释放多少期(若配置>0,则按期数平均分摊) + releasePeriods?: number; + // 首期释放时机:0=支付成功当刻;1=下个月同日 + firstReleaseMode?: number; + // 用户ID + userId?: number; + // 排序(数字越小越靠前) + sortNumber?: number; + // 备注 + comments?: string; + // 状态, 0正常, 1冻结 + status?: number; + // 是否删除, 0否, 1是 + deleted?: number; + // 租户id + tenantId?: number; + // 创建时间 + createTime?: string; + // 修改时间 + updateTime?: string; +} + +/** + * 水票搜索条件 + */ +export interface GltTicketTemplateParam extends PageParam { + id?: number; + keywords?: string; +} diff --git a/src/api/glt/gltUserTicket/index.ts b/src/api/glt/gltUserTicket/index.ts new file mode 100644 index 0000000..d338780 --- /dev/null +++ b/src/api/glt/gltUserTicket/index.ts @@ -0,0 +1,105 @@ +import request from '@/utils/request'; +import type { ApiResult, PageResult } from '@/api'; +import type { GltUserTicket, GltUserTicketParam } from './model'; + +/** + * 分页查询我的水票 + */ +export async function pageGltUserTicket(params: GltUserTicketParam) { + const res = await request.get>>( + '/glt/glt-user-ticket/page', + { + params + } + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 查询我的水票列表 + */ +export async function listGltUserTicket(params?: GltUserTicketParam) { + const res = await request.get>( + '/glt/glt-user-ticket', + { + params + } + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 添加我的水票 + */ +export async function addGltUserTicket(data: GltUserTicket) { + const res = await request.post>( + '/glt/glt-user-ticket', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 修改我的水票 + */ +export async function updateGltUserTicket(data: GltUserTicket) { + const res = await request.put>( + '/glt/glt-user-ticket', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 删除我的水票 + */ +export async function removeGltUserTicket(id?: number) { + const res = await request.del>( + '/glt/glt-user-ticket/' + id + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 批量删除我的水票 + */ +export async function removeBatchGltUserTicket(data: (number | undefined)[]) { + const res = await request.del>( + '/glt/glt-user-ticket/batch', + { + data + } + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 根据id查询我的水票 + */ +export async function getGltUserTicket(id: number) { + const res = await request.get>( + '/glt/glt-user-ticket/' + id + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} diff --git a/src/api/glt/gltUserTicket/model/index.ts b/src/api/glt/gltUserTicket/model/index.ts new file mode 100644 index 0000000..7de0b48 --- /dev/null +++ b/src/api/glt/gltUserTicket/model/index.ts @@ -0,0 +1,66 @@ +import type { PageParam } from '@/api'; + +/** + * 我的水票 + */ +export interface GltUserTicket { + // + id?: number; + // 模板ID + templateId?: number; + // 模板名称 + templateName?: string; + // 商品ID + goodsId?: number; + // 订单ID + orderId?: number; + // 订单编号 + orderNo?: string; + // 订单商品ID + orderGoodsId?: number; + // 总数量 + totalQty?: number; + // 可用数量 + availableQty?: number; + // 冻结数量 + frozenQty?: number; + // 已使用数量 + usedQty?: number; + // 已释放数量 + releasedQty?: number; + // 用户ID + userId?: number; + // 用户昵称 + nickname?: string; + // 用户头像 + avatar?: string; + // 用户手机号 + phone?: string; + // 排序(数字越小越靠前) + sortNumber?: number; + // 备注 + comments?: string; + // 状态, 0正常, 1冻结 + status?: number; + // 是否删除, 0否, 1是 + deleted?: number; + // 租户id + tenantId?: number; + // 创建时间 + createTime?: string; + // 修改时间 + updateTime?: string; +} + +/** + * 我的水票搜索条件 + */ +export interface GltUserTicketParam extends PageParam { + id?: number; + templateId?: number; + userId?: number; + phone?: string; + keywords?: string; + // 状态过滤:0正常,1冻结 + status?: number; +} diff --git a/src/api/glt/gltUserTicketLog/index.ts b/src/api/glt/gltUserTicketLog/index.ts new file mode 100644 index 0000000..9541f23 --- /dev/null +++ b/src/api/glt/gltUserTicketLog/index.ts @@ -0,0 +1,105 @@ +import request from '@/utils/request'; +import type { ApiResult, PageResult } from '@/api'; +import type { GltUserTicketLog, GltUserTicketLogParam } from './model'; + +/** + * 分页查询消费日志 + */ +export async function pageGltUserTicketLog(params: GltUserTicketLogParam) { + const res = await request.get>>( + '/glt/glt-user-ticket-log/page', + { + params + } + ); + if (res.code === 0) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 查询消费日志列表 + */ +export async function listGltUserTicketLog(params?: GltUserTicketLogParam) { + const res = await request.get>( + '/glt/glt-user-ticket-log', + { + params + } + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 添加消费日志 + */ +export async function addGltUserTicketLog(data: GltUserTicketLog) { + const res = await request.post>( + '/glt/glt-user-ticket-log', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 修改消费日志 + */ +export async function updateGltUserTicketLog(data: GltUserTicketLog) { + const res = await request.put>( + '/glt/glt-user-ticket-log', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 删除消费日志 + */ +export async function removeGltUserTicketLog(id?: number) { + const res = await request.del>( + '/glt/glt-user-ticket-log/' + id + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 批量删除消费日志 + */ +export async function removeBatchGltUserTicketLog(data: (number | undefined)[]) { + const res = await request.del>( + '/glt/glt-user-ticket-log/batch', + { + data + } + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 根据id查询消费日志 + */ +export async function getGltUserTicketLog(id: number) { + const res = await request.get>( + '/glt/glt-user-ticket-log/' + id + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} diff --git a/src/api/glt/gltUserTicketLog/model/index.ts b/src/api/glt/gltUserTicketLog/model/index.ts new file mode 100644 index 0000000..e41e9ea --- /dev/null +++ b/src/api/glt/gltUserTicketLog/model/index.ts @@ -0,0 +1,53 @@ +import type { PageParam } from '@/api'; + +/** + * 消费日志 + */ +export interface GltUserTicketLog { + // + id?: number; + // 用户水票ID + userTicketId?: number; + // 变更类型 + changeType?: number; + // 可更改 + changeAvailable?: number; + // 更改冻结状态 + changeFrozen?: number; + // 已使用更改 + changeUsed?: number; + // 可用后 + availableAfter?: number; + // 冻结后 + frozenAfter?: number; + // 使用后 + usedAfter?: number; + // 订单ID + orderId?: number; + // 订单编号 + orderNo?: string; + // 用户ID + userId?: number; + // 排序(数字越小越靠前) + sortNumber?: number; + // 备注 + comments?: string; + // 状态, 0正常, 1冻结 + status?: number; + // 是否删除, 0否, 1是 + deleted?: number; + // 租户id + tenantId?: number; + // 创建时间 + createTime?: string; + // 修改时间 + updateTime?: string; +} + +/** + * 消费日志搜索条件 + */ +export interface GltUserTicketLogParam extends PageParam { + id?: number; + keywords?: string; +} diff --git a/src/api/glt/gltUserTicketRelease/index.ts b/src/api/glt/gltUserTicketRelease/index.ts new file mode 100644 index 0000000..40b5e7d --- /dev/null +++ b/src/api/glt/gltUserTicketRelease/index.ts @@ -0,0 +1,105 @@ +import request from '@/utils/request'; +import type { ApiResult, PageResult } from '@/api'; +import type { GltUserTicketRelease, GltUserTicketReleaseParam } from './model'; + +/** + * 分页查询水票释放 + */ +export async function pageGltUserTicketRelease(params: GltUserTicketReleaseParam) { + const res = await request.get>>( + '/glt/glt-user-ticket-release/page', + { + params + } + ); + if (res.code === 0) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 查询水票释放列表 + */ +export async function listGltUserTicketRelease(params?: GltUserTicketReleaseParam) { + const res = await request.get>( + '/glt/glt-user-ticket-release', + { + params + } + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 添加水票释放 + */ +export async function addGltUserTicketRelease(data: GltUserTicketRelease) { + const res = await request.post>( + '/glt/glt-user-ticket-release', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 修改水票释放 + */ +export async function updateGltUserTicketRelease(data: GltUserTicketRelease) { + const res = await request.put>( + '/glt/glt-user-ticket-release', + data + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 删除水票释放 + */ +export async function removeGltUserTicketRelease(id?: number) { + const res = await request.del>( + '/glt/glt-user-ticket-release/' + id + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 批量删除水票释放 + */ +export async function removeBatchGltUserTicketRelease(data: (number | undefined)[]) { + const res = await request.del>( + '/glt/glt-user-ticket-release/batch', + { + data + } + ); + if (res.code === 0) { + return res.message; + } + return Promise.reject(new Error(res.message)); +} + +/** + * 根据id查询水票释放 + */ +export async function getGltUserTicketRelease(id: number) { + const res = await request.get>( + '/glt/glt-user-ticket-release/' + id + ); + if (res.code === 0 && res.data) { + return res.data; + } + return Promise.reject(new Error(res.message)); +} diff --git a/src/api/glt/gltUserTicketRelease/model/index.ts b/src/api/glt/gltUserTicketRelease/model/index.ts new file mode 100644 index 0000000..14cf1cd --- /dev/null +++ b/src/api/glt/gltUserTicketRelease/model/index.ts @@ -0,0 +1,38 @@ +import type { PageParam } from '@/api'; + +/** + * 水票释放 + */ +export interface GltUserTicketRelease { + // + id?: string; + // 水票ID + userTicketId?: string; + // 用户ID + userId?: number; + // 周期编号 + periodNo?: number; + // 释放数量 + releaseQty?: number; + // 释放时间 + releaseTime?: string; + // 状态 + status?: number; + // 是否删除, 0否, 1是 + deleted?: number; + // 租户id + tenantId?: number; + // 创建时间 + createTime?: string; + // 修改时间 + updateTime?: string; +} + +/** + * 水票释放搜索条件 + */ +export interface GltUserTicketReleaseParam extends PageParam { + id?: number; + userId?: number; + keywords?: string; +} diff --git a/src/app.config.ts b/src/app.config.ts index 67a1f2b..c8c3250 100644 --- a/src/app.config.ts +++ b/src/app.config.ts @@ -53,10 +53,12 @@ export default { "wallet/wallet", "coupon/index", "points/points", - "gift/index", - "gift/redeem", - "gift/detail", - "gift/add", + "ticket/index", + "ticket/detail", + // "gift/index", + // "gift/redeem", + // "gift/detail", + // "gift/add", "store/verification", "store/orders/index", "theme/index", diff --git a/src/pages/index/index.tsx b/src/pages/index/index.tsx index 2c36ff5..917221b 100644 --- a/src/pages/index/index.tsx +++ b/src/pages/index/index.tsx @@ -182,7 +182,7 @@ function Home() { key: 'ticket', title: '我的水票', icon: , - onClick: () => Taro.navigateTo({ url: '/user/gift/index' }), + onClick: () => Taro.navigateTo({ url: '/user/ticket/index' }), }, { key: 'order', diff --git a/src/user/ticket/add.config.ts b/src/user/ticket/add.config.ts new file mode 100644 index 0000000..5d97955 --- /dev/null +++ b/src/user/ticket/add.config.ts @@ -0,0 +1,4 @@ +export default definePageConfig({ + navigationBarTitleText: '新增收货地址', + navigationBarTextStyle: 'black' +}) diff --git a/src/user/ticket/add.tsx b/src/user/ticket/add.tsx new file mode 100644 index 0000000..493b1d3 --- /dev/null +++ b/src/user/ticket/add.tsx @@ -0,0 +1,323 @@ +import {useEffect, useState, useRef} from "react"; +import {useRouter} from '@tarojs/taro' +import {Button, Loading, CellGroup, Input, TextArea, Form, Switch, InputNumber, Radio, Image} from '@nutui/nutui-react-taro' +import {Edit, Upload as UploadIcon} from '@nutui/icons-react-taro' +import Taro from '@tarojs/taro' +import {View} from '@tarojs/components' +import {ShopArticle} from "@/api/shop/shopArticle/model"; +import {getShopArticle, addShopArticle, updateShopArticle} from "@/api/shop/shopArticle"; +import FixedButton from "@/components/FixedButton"; + +const AddShopArticle = () => { + const {params} = useRouter(); + const [loading, setLoading] = useState(true) + const [formData, setFormData] = useState({ + type: 0, // 默认常规文章 + status: 0, // 默认已发布 + permission: 0, // 默认所有人可见 + recommend: 0, // 默认不推荐 + showType: 10, // 默认小图展示 + virtualViews: 0, // 默认虚拟阅读量 + actualViews: 0, // 默认实际阅读量 + sortNumber: 0 // 默认排序 + }) + const formRef = useRef(null) + + // 判断是编辑还是新增模式 + const isEditMode = !!params.id + const articleId = params.id ? Number(params.id) : undefined + + // 文章类型选项 + const typeOptions = [ + { text: '常规文章', value: 0 }, + { text: '视频文章', value: 1 } + ] + + // 状态选项 + const statusOptions = [ + { text: '已发布', value: 0 }, + { text: '待审核', value: 1 }, + { text: '已驳回', value: 2 }, + { text: '违规内容', value: 3 } + ] + + // 可见性选项 + const permissionOptions = [ + { text: '所有人可见', value: 0 }, + { text: '登录可见', value: 1 }, + { text: '密码可见', value: 2 } + ] + + // 显示方式选项 + const showTypeOptions = [ + { text: '小图展示', value: 10 }, + { text: '大图展示', value: 20 } + ] + + const reload = async () => { + // 如果是编辑模式,加载文章数据 + if (isEditMode && articleId) { + try { + const article = await getShopArticle(articleId) + setFormData(article) + // 更新表单值 + if (formRef.current) { + formRef.current.setFieldsValue(article) + } + } catch (error) { + console.error('加载文章失败:', error) + Taro.showToast({ + title: '加载文章失败', + icon: 'error' + }); + } + } + } + + // 图片上传处理 + const handleImageUpload = async () => { + try { + const res = await Taro.chooseImage({ + count: 1, + sizeType: ['compressed'], + sourceType: ['album', 'camera'] + }); + + if (res.tempFilePaths && res.tempFilePaths.length > 0) { + // 这里应该调用上传接口,暂时使用本地路径 + const imagePath = res.tempFilePaths[0]; + setFormData({ + ...formData, + image: imagePath + }); + + Taro.showToast({ + title: '图片选择成功', + icon: 'success' + }); + } + } catch (error) { + Taro.showToast({ + title: '图片选择失败', + icon: 'error' + }); + } + }; + + // 提交表单 + const submitSucceed = async (values: any) => { + try { + // 准备提交的数据 + const submitData = { + ...formData, + ...values, + }; + + // 如果是编辑模式,添加id + if (isEditMode && articleId) { + submitData.articleId = articleId; + } + + // 执行新增或更新操作 + if (isEditMode) { + await updateShopArticle(submitData); + } else { + await addShopArticle(submitData); + } + + Taro.showToast({ + title: `${isEditMode ? '更新' : '保存'}成功`, + icon: 'success' + }); + + setTimeout(() => { + Taro.navigateBack(); + }, 1000); + + } catch (error) { + console.error('保存失败:', error); + Taro.showToast({ + title: `${isEditMode ? '更新' : '保存'}失败`, + icon: 'error' + }); + } + } + + const submitFailed = (error: any) => { + console.log(error, 'err...') + } + + useEffect(() => { + // 动态设置页面标题 + Taro.setNavigationBarTitle({ + title: isEditMode ? '编辑文章' : '新增文章' + }); + + reload().then(() => { + setLoading(false) + }) + }, [isEditMode]); + + if (loading) { + return 加载中 + } + + return ( + <> +
submitSucceed(values)} + onFinishFailed={(errors) => submitFailed(errors)} + > + {/* 基本信息 */} + + + + + + +