| | |
| | | form.setFieldsValue({ |
| | | title: data.title, |
| | | sortOrder: data.sortOrder || 45, |
| | | homepageDisplay: data.homepageDisplay === 1, |
| | | showOnHome: data.showOnHome === true || data.showOnHome === 'true' || data.showOnHome === 1, |
| | | coverImage: data.coverImage, |
| | | carouselImages: data.carouselImages, |
| | | detailImages: data.detailImages, |
| | | }); |
| | | |
| | | // 设置封面图 |
| | | if (data.coverImage) { |
| | | setCoverImageUrl(IMAGE_URL + data.coverImage); |
| | | const isFullUrl = data.coverImage.startsWith('http://') || data.coverImage.startsWith('https://'); |
| | | const imageUrl = isFullUrl |
| | | ? data.coverImage |
| | | : IMAGE_URL + data.coverImage.replace(/^\/+/, ''); |
| | | setCoverImageUrl(imageUrl); |
| | | } |
| | | |
| | | // 设置轮播图 |
| | | if (data.carouselImages) { |
| | | const imageArray = Array.isArray(data.carouselImages) |
| | | ? data.carouselImages |
| | | : data.carouselImages.split(',').filter(Boolean); |
| | | const fileList = imageArray.map((url, index) => ({ |
| | | uid: `-${index}`, |
| | | name: `image-${index}.jpg`, |
| | | status: 'done', |
| | | url: IMAGE_URL + url, |
| | | })); |
| | | if (data.detailImages) { |
| | | const imageArray = Array.isArray(data.detailImages) |
| | | ? data.detailImages |
| | | : typeof data.detailImages === 'string' |
| | | ? data.detailImages.split(',').filter(Boolean) |
| | | : []; |
| | | const fileList = imageArray.map((url, index) => { |
| | | const isFullUrl = url.startsWith('http://') || url.startsWith('https://'); |
| | | const imageUrl = isFullUrl |
| | | ? url |
| | | : IMAGE_URL + url.replace(/^\/+/, ''); |
| | | return { |
| | | uid: `-${index}`, |
| | | name: `image-${index}.jpg`, |
| | | status: 'done', |
| | | url: imageUrl, |
| | | response: url, // 保存原始值 |
| | | }; |
| | | }); |
| | | setCarouselImageList(fileList); |
| | | form.setFieldValue('carouselImages', imageArray.join(',')); |
| | | // 将 detailImages 设置为逗号分隔的字符串 |
| | | const detailImagesStr = imageArray.join(','); |
| | | form.setFieldValue('detailImages', detailImagesStr); |
| | | } |
| | | |
| | | // 设置富文本内容 |
| | |
| | | let params = announcementContent; |
| | | params.content = html; |
| | | setAnnouncementContent(params); |
| | | form.setFieldsValue({ content: params }); |
| | | // form.setFieldsValue({ content: params }); |
| | | }; |
| | | |
| | | // 处理封面图上传成功 |
| | | const handleCoverImageSuccess = (response) => { |
| | | setCoverImageUrl(IMAGE_URL + response); |
| | | const isFullUrl = response && (response.startsWith('http://') || response.startsWith('https://')); |
| | | const imageUrl = isFullUrl ? response : IMAGE_URL + response; |
| | | setCoverImageUrl(imageUrl); |
| | | form.setFieldsValue({ coverImage: response }); |
| | | }; |
| | | |
| | |
| | | // 如果是已存在的图片,从url中提取相对路径 |
| | | if (file.url) { |
| | | if (file.url.startsWith(IMAGE_URL)) { |
| | | return file.url.replace(IMAGE_URL, ''); |
| | | return file.url.replace(IMAGE_URL, '').replace(/^\/+/, ''); |
| | | } |
| | | // 如果是完整URL,直接返回 |
| | | if (file.url.startsWith('http://') || file.url.startsWith('https://')) { |
| | | return file.url; |
| | | } |
| | | return file.url; |
| | | } |
| | | return null; |
| | | }) |
| | | .filter(Boolean); |
| | | form.setFieldsValue({ carouselImages: urls.join(',') }); |
| | | // 将 detailImages 设置为逗号分隔的字符串 |
| | | form.setFieldsValue({ detailImages: urls.join(',') }); |
| | | }; |
| | | |
| | | // 处理轮播图删除 |
| | |
| | | return item.response; |
| | | } |
| | | if (item.url && item.url.startsWith(IMAGE_URL)) { |
| | | return item.url.replace(IMAGE_URL, ''); |
| | | return item.url.replace(IMAGE_URL, '').replace(/^\/+/, ''); |
| | | } |
| | | // 如果是完整URL,直接返回 |
| | | if (item.url && (item.url.startsWith('http://') || item.url.startsWith('https://'))) { |
| | | return item.url; |
| | | } |
| | | return item.url; |
| | | }) |
| | | .filter(Boolean); |
| | | form.setFieldsValue({ carouselImages: urls.join(',') }); |
| | | // 将 detailImages 设置为逗号分隔的字符串 |
| | | form.setFieldsValue({ detailImages: urls.join(',') }); |
| | | return true; |
| | | }; |
| | | |
| | |
| | | const submitData = { |
| | | title: values.title, |
| | | coverImage: values.coverImage, |
| | | carouselImages: values.carouselImages || '', |
| | | detailImages: values.detailImages |
| | | ? (typeof values.detailImages === 'string' |
| | | ? values.detailImages |
| | | : Array.isArray(values.detailImages) |
| | | ? values.detailImages.join(',') |
| | | : '') |
| | | : '', |
| | | sortOrder: values.sortOrder || 45, |
| | | homepageDisplay: values.homepageDisplay ? 1 : 0, |
| | | showOnHome: values.showOnHome === true || values.showOnHome === 'true' || values.showOnHome === 1, |
| | | content: announcementContent.content, |
| | | }; |
| | | |
| | |
| | | {/* 公告标题 */} |
| | | <ProFormText |
| | | name="title" |
| | | label="*公告标题" |
| | | label="公告标题" |
| | | placeholder="请输入" |
| | | wrapperCol={{ span: 12 }} |
| | | rules={[{ required: true, message: '请输入公告标题' }]} |
| | |
| | | </Form.Item> |
| | | |
| | | {/* 详情轮播图 */} |
| | | <Form.Item name="carouselImages" label="详情轮播图"> |
| | | <Form.Item name="detailImages" label="详情轮播图"> |
| | | <Upload |
| | | name="carouselImages" |
| | | name="detailImages" |
| | | listType="picture-card" |
| | | fileList={carouselImageList} |
| | | beforeUpload={beforeUpload} |
| | |
| | | fieldProps={{ |
| | | style: { width: '120px' }, |
| | | }} |
| | | initialValue={45} |
| | | /> |
| | | <div style={{ fontSize: '12px', color: '#999', marginTop: '4px', marginLeft: '8px' }}> |
| | | 数值越大越靠前 |
| | |
| | | </div> |
| | | |
| | | {/* 是否展示在首页 */} |
| | | <Form.Item name="homepageDisplay" label="是否展示在首页:" style={{ marginBottom: 0 }}> |
| | | <Form.Item name="showOnHome" label="是否展示在首页:" style={{ marginBottom: 0 }}> |
| | | <ProFormSwitch |
| | | name="homepageDisplay" |
| | | name="showOnHome" |
| | | disabled={isReadOnly} |
| | | /> |
| | | </Form.Item> |
| | |
| | | {/* 公告内容 */} |
| | | <Form.Item |
| | | name="content" |
| | | label="*公告内容" |
| | | label="公告内容" |
| | | wrapperCol={{ span: 24 }} |
| | | rules={[{ required: true, message: '请输入公告内容' }]} |
| | | // rules={[{ required: true, message: '请输入公告内容' }]} |
| | | > |
| | | <BraftEditorCom |
| | | data={announcementContent.content || ''} |
| | |
| | | import React, { useRef } from 'react'; |
| | | import { PageContainer, ProTable } from '@ant-design/pro-components'; |
| | | import { Button, message, Popconfirm, Image, Space } from 'antd'; |
| | | import { Button, Image, Space } from 'antd'; |
| | | import { history } from '@umijs/max'; |
| | | import { buildProTableDataSource, sendRequest, showDelConfirm } from '@/utils/antdUtils'; |
| | | import { getAnnouncementList, deleteAnnouncement } from './service'; |
| | | |
| | | |
| | | const AnnouncementManagement = () => { |
| | | const actionRef = useRef(); |
| | | |
| | | // 是否首页展示映射 |
| | | const homepageDisplayMap = { |
| | | 1: { text: '是' }, |
| | | 0: { text: '否' }, |
| | | const showOnHomeMap = { |
| | | true: { text: '是' }, |
| | | false: { text: '否' }, |
| | | 'true': { text: '是' }, |
| | | 'false': { text: '否' }, |
| | | }; |
| | | |
| | | // 删除公告 |
| | | const handleDelete = async (id) => { |
| | | try { |
| | | const res = await deleteAnnouncement(id); |
| | | if (res.code === 200) { |
| | | message.success('删除成功'); |
| | | actionRef.current?.reload(); |
| | | } else { |
| | | message.error(res.msg || '删除失败'); |
| | | } |
| | | } catch (error) { |
| | | message.error('删除失败'); |
| | | const status = await sendRequest(deleteAnnouncement, id); |
| | | if (status) { |
| | | actionRef.current?.reload(); |
| | | } |
| | | }; |
| | | |
| | |
| | | }, |
| | | }, |
| | | { |
| | | title: '发布时间', |
| | | dataIndex: 'publishTime', |
| | | valueType: 'date', |
| | | width: 150, |
| | | title: '创建时间', |
| | | dataIndex: 'createTime', |
| | | valueType: 'dateTime', |
| | | width: 180, |
| | | align: 'center', |
| | | hideInTable: false, |
| | | fieldProps: { |
| | |
| | | }, |
| | | }, |
| | | { |
| | | title: '创建人', |
| | | dataIndex: 'createBy', |
| | | hideInSearch: true, |
| | | width: 120, |
| | | align: 'center', |
| | | ellipsis: true, |
| | | }, |
| | | { |
| | | title: '是否首页展示', |
| | | dataIndex: 'homepageDisplay', |
| | | dataIndex: 'showOnHome', |
| | | valueType: 'select', |
| | | hideInTable: true, |
| | | valueEnum: homepageDisplayMap, |
| | | hideInTable: false, |
| | | width: 120, |
| | | align: 'center', |
| | | valueEnum: showOnHomeMap, |
| | | fieldProps: { |
| | | placeholder: '请选择', |
| | | }, |
| | | render: (text,record) => { |
| | | return record.showOnHome ? '是' : '否'; |
| | | }, |
| | | }, |
| | | { |
| | | title: '浏览人数', |
| | | dataIndex: 'viewCount', |
| | | dataIndex: 'lookNum', |
| | | hideInSearch: true, |
| | | width: 120, |
| | | align: 'center', |
| | | render: (text) => text || 0, |
| | | }, |
| | | { |
| | | title: '排序', |
| | | dataIndex: 'sortOrder', |
| | | hideInSearch: true, |
| | | width: 100, |
| | | align: 'center', |
| | | render: (text) => text || 0, |
| | | }, |
| | |
| | | <Button type="link" size="small" onClick={() => handleEdit(record)}> |
| | | 编辑 |
| | | </Button> |
| | | <Popconfirm |
| | | title="确认删除该公告?" |
| | | onConfirm={() => handleDelete(record.id)} |
| | | okText="确认" |
| | | cancelText="取消" |
| | | <Button |
| | | type="link" |
| | | size="small" |
| | | danger |
| | | onClick={() => { |
| | | showDelConfirm(async () => { |
| | | await handleDelete(record.id); |
| | | }, '删除后不可恢复,请谨慎操作!', '确认', '取消', '确认删除该公告?'); |
| | | }} |
| | | > |
| | | <Button type="link" size="small" danger> |
| | | 删除 |
| | | </Button> |
| | | </Popconfirm> |
| | | 删除 |
| | | </Button> |
| | | </Space> |
| | | ), |
| | | }, |
| | |
| | | 新增公告 |
| | | </Button>, |
| | | ]} |
| | | request={async (params, sort, filter) => { |
| | | const { current, pageSize, title, publishTime, homepageDisplay, ...rest } = params; |
| | | |
| | | request={async (params) => { |
| | | const { current, pageSize, title, createTime, showOnHome, ...rest } = params; |
| | | const requestParams = { |
| | | ...rest, |
| | | pageNum: current, |
| | | pageSize, |
| | | title: title || undefined, |
| | | publishTime: publishTime || undefined, |
| | | homepageDisplay: homepageDisplay !== undefined ? homepageDisplay : undefined, |
| | | createTime: createTime || undefined, |
| | | showOnHome: showOnHome !== undefined ? showOnHome : undefined, |
| | | }; |
| | | |
| | | const res = await getAnnouncementList(requestParams); |
| | | |
| | | return { |
| | | data: (res.data?.records || []).map((item, index) => ({ |
| | | ...item, |
| | | index: (current - 1) * pageSize + index + 1, |
| | | })), |
| | | success: res.code === 200, |
| | | total: res.data?.total || 0, |
| | | }; |
| | | const result = await buildProTableDataSource(getAnnouncementList, requestParams); |
| | | // 添加序号 |
| | | result.data = result.data.map((item, index) => ({ |
| | | ...item, |
| | | index: ((current || 1) - 1) * (pageSize || 10) + index + 1, |
| | | })); |
| | | return result; |
| | | }} |
| | | columns={columns} |
| | | scroll={{ x: 1200 }} |
| | |
| | | |
| | | // 获取公告列表(分页) |
| | | export async function getAnnouncementList(params) { |
| | | return request('/announcement/page', { |
| | | return request('/t-notice/pageList', { |
| | | method: 'POST', |
| | | data: params, |
| | | }); |
| | |
| | | |
| | | // 删除公告 |
| | | export async function deleteAnnouncement(id) { |
| | | return request(`/announcement/${id}`, { |
| | | return request(`/t-notice/delete/${id}`, { |
| | | method: 'DELETE', |
| | | }); |
| | | } |
| | | |
| | | // 获取公告详情 |
| | | export async function getAnnouncementDetail(id) { |
| | | return request(`/announcement/${id}`, { |
| | | return request(`/t-notice/detail/${id}`, { |
| | | method: 'GET', |
| | | }); |
| | | } |
| | | |
| | | // 新增公告 |
| | | export async function addAnnouncement(params) { |
| | | return request('/announcement', { |
| | | return request('/t-notice/add', { |
| | | method: 'POST', |
| | | data: params, |
| | | }); |
| | |
| | | |
| | | // 编辑公告 |
| | | export async function editAnnouncement(params) { |
| | | return request('/announcement', { |
| | | method: 'PUT', |
| | | return request('/t-notice/update', { |
| | | method: 'POST', |
| | | data: params, |
| | | }); |
| | | } |
| | |
| | | import React, { useRef, useState } from 'react'; |
| | | import { PageContainer, ProTable } from '@ant-design/pro-components'; |
| | | import { Button, Space, Popconfirm, message } from 'antd'; |
| | | import { Button, Space } from 'antd'; |
| | | import { buildProTableDataSource, sendRequest, showDelConfirm } from '@/utils/antdUtils'; |
| | | import { getPhysicalGoodsOrderList, deletePhysicalGoodsOrder } from './service'; |
| | | import OrderDetailModal from './components/OrderDetailModal'; |
| | | import { exportExcell } from '@/utils/utils' |
| | |
| | | |
| | | // 删除订单 |
| | | const handleDelete = async (id) => { |
| | | const res = await deletePhysicalGoodsOrder(id); |
| | | if (res.code === 200) { |
| | | message.success('删除成功'); |
| | | const status = await sendRequest(deletePhysicalGoodsOrder, id); |
| | | if (status) { |
| | | actionRef.current?.reload(); |
| | | } else { |
| | | message.error(res.message || '删除失败'); |
| | | } |
| | | }; |
| | | |
| | |
| | | </Button> |
| | | </Access> |
| | | <Access accessible={access.physicalGoodsOrder_del || false}> |
| | | <Popconfirm title="确认删除?" onConfirm={() => handleDelete(record.id)}> |
| | | <Button type="link" danger> |
| | | 删除 |
| | | </Button> |
| | | </Popconfirm> |
| | | <Button |
| | | type="link" |
| | | danger |
| | | onClick={() => { |
| | | showDelConfirm(async () => { |
| | | await handleDelete(record.id); |
| | | }, '删除后不可恢复,请谨慎操作!', '确认', '取消', '确认删除?'); |
| | | }} |
| | | > |
| | | 删除 |
| | | </Button> |
| | | </Access> |
| | | </Space> |
| | | ), |
| | |
| | | actionRef={actionRef} |
| | | columns={columns} |
| | | request={async (params) => { |
| | | const { current, pageSize, ...rest } = params; |
| | | const { ...rest } = params; |
| | | setSearchParams({ |
| | | ...rest, |
| | | pageNum: current, |
| | | pageSize, |
| | | pageNum: params.current, |
| | | pageSize: params.pageSize, |
| | | }); |
| | | const res = await getPhysicalGoodsOrderList({ |
| | | ...rest, |
| | | pageNum: current, |
| | | pageSize, |
| | | }); |
| | | return { |
| | | data: res.data?.records || [], |
| | | success: res.code === 200, |
| | | total: res.data?.total || 0, |
| | | }; |
| | | const result = await buildProTableDataSource(getPhysicalGoodsOrderList, rest); |
| | | return result; |
| | | }} |
| | | pagination={{ |
| | | showQuickJumper: true, |
| | |
| | | import { exportExcell } from '@/utils/utils'; |
| | | import { Button, message, Popconfirm } from 'antd'; |
| | | import { request } from '@umijs/max'; |
| | | import { Button } from 'antd'; |
| | | import { useRef, useState } from 'react'; |
| | | import { PageContainer, ProTable } from '@ant-design/pro-components'; |
| | | import { buildProTableDataSource, sendRequest, showDelConfirm } from '@/utils/antdUtils'; |
| | | import RefundDetailModal from './components/RefundDetailModal'; |
| | | import { deleteRefundApplication, pageRefundList } from './service'; |
| | | import { Access, useAccess } from 'umi'; |
| | |
| | | </Button> |
| | | </Access> |
| | | <Access accessible={access.refundAudit_del || false}> |
| | | <Popconfirm |
| | | title="确认删除该退款申请?" |
| | | onConfirm={() => handleDelete(record.id)} |
| | | okText="确认" |
| | | cancelText="取消" |
| | | <Button |
| | | type="link" |
| | | size="small" |
| | | danger |
| | | onClick={() => { |
| | | showDelConfirm(async () => { |
| | | await handleDelete(record.id); |
| | | }, '删除后不可恢复,请谨慎操作!', '确认', '取消', '确认删除该退款申请?'); |
| | | }} |
| | | > |
| | | <Button type="link" size="small" danger> |
| | | 删除 |
| | | </Button> |
| | | </Popconfirm> |
| | | 删除 |
| | | </Button> |
| | | </Access> |
| | | </> |
| | | ), |
| | |
| | | |
| | | // 删除退款申请 |
| | | const handleDelete = async (id) => { |
| | | try { |
| | | const res = await deleteRefundApplication(id); |
| | | if (res.code === 200) { |
| | | message.success('删除成功'); |
| | | actionRef.current?.reload(); |
| | | } else { |
| | | message.error(res.msg || '删除失败'); |
| | | } |
| | | } catch (error) { |
| | | message.error('删除失败'); |
| | | const status = await sendRequest(deleteRefundApplication, id); |
| | | if (status) { |
| | | actionRef.current?.reload(); |
| | | } |
| | | }; |
| | | |
| | |
| | | }} |
| | | toolBarRender={false} |
| | | request={async (params) => { |
| | | const { current, pageSize, ...rest } = params; |
| | | const { ...rest } = params; |
| | | |
| | | // 保存搜索参数,用于导出 |
| | | setSearchParams({ |
| | | ...rest, |
| | | pageNum: current, |
| | | pageSize, |
| | | pageNum: params.current, |
| | | pageSize: params.pageSize, |
| | | }); |
| | | |
| | | const res = await pageRefundList({ |
| | | ...rest, |
| | | pageNum: current, |
| | | pageSize, |
| | | }); |
| | | |
| | | return { |
| | | data: res.data?.records || [], |
| | | success: res.code === 200, |
| | | total: res.data?.total || 0, |
| | | }; |
| | | const result = await buildProTableDataSource(pageRefundList, rest); |
| | | return result; |
| | | }} |
| | | columns={columns} |
| | | scroll={{ x: 1600 }} |
| | |
| | | import React, { useRef } from 'react'; |
| | | import { PageContainer, ProTable } from '@ant-design/pro-components'; |
| | | import { Button, message, Popconfirm, Image, Space } from 'antd'; |
| | | import { Button, Image, Space } from 'antd'; |
| | | import { history } from '@umijs/max'; |
| | | import { buildProTableDataSource, sendRequest, showDelConfirm } from '@/utils/antdUtils'; |
| | | import { getStrategyList, deleteStrategy } from './service'; |
| | | |
| | | const StrategyManagement = () => { |
| | |
| | | |
| | | // 删除攻略 |
| | | const handleDelete = async (id) => { |
| | | try { |
| | | const res = await deleteStrategy(id); |
| | | if (res.code === 200) { |
| | | message.success('删除成功'); |
| | | actionRef.current?.reload(); |
| | | } else { |
| | | message.error(res.msg || '删除失败'); |
| | | } |
| | | } catch (error) { |
| | | message.error('删除失败'); |
| | | const status = await sendRequest(deleteStrategy, id); |
| | | if (status) { |
| | | actionRef.current?.reload(); |
| | | } |
| | | }; |
| | | |
| | |
| | | <Button type="link" size="small" onClick={() => handleEdit(record)}> |
| | | 编辑 |
| | | </Button> |
| | | <Popconfirm |
| | | title="确认删除该攻略?" |
| | | onConfirm={() => handleDelete(record.id)} |
| | | okText="确认" |
| | | cancelText="取消" |
| | | <Button |
| | | type="link" |
| | | size="small" |
| | | danger |
| | | onClick={() => { |
| | | showDelConfirm(async () => { |
| | | await handleDelete(record.id); |
| | | }, '删除后不可恢复,请谨慎操作!', '确认', '取消', '确认删除该攻略?'); |
| | | }} |
| | | > |
| | | <Button type="link" size="small" danger> |
| | | 删除 |
| | | </Button> |
| | | </Popconfirm> |
| | | 删除 |
| | | </Button> |
| | | </Space> |
| | | ), |
| | | }, |
| | |
| | | 新增攻略 |
| | | </Button>, |
| | | ]} |
| | | request={async (params, sort, filter) => { |
| | | request={async (params) => { |
| | | const { current, pageSize, title, createTime, ...rest } = params; |
| | | |
| | | const requestParams = { |
| | | ...rest, |
| | | pageNum: current, |
| | | pageSize, |
| | | title: title || undefined, |
| | | createTime: createTime || undefined, |
| | | }; |
| | | |
| | | const res = await getStrategyList(requestParams); |
| | | |
| | | return { |
| | | data: (res.data?.records || []).map((item, index) => ({ |
| | | ...item, |
| | | index: (current - 1) * pageSize + index + 1, |
| | | })), |
| | | success: res.code === 200, |
| | | total: res.data?.total || 0, |
| | | }; |
| | | const result = await buildProTableDataSource(getStrategyList, requestParams); |
| | | // 添加序号 |
| | | result.data = result.data.map((item, index) => ({ |
| | | ...item, |
| | | index: ((current || 1) - 1) * (pageSize || 10) + index + 1, |
| | | })); |
| | | return result; |
| | | }} |
| | | columns={columns} |
| | | scroll={{ x: 1200 }} |