dev-v2
Joe 5 days ago
parent 5df7630661
commit 2263402cd3

@ -53,7 +53,7 @@
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@tinymce/tinymce-react": "^6.2.1",
"@tinymce/tinymce-react": "^6.3.0",
"@umijs/route-utils": "^2.2.2",
"aliyun-aliplayer": "^2.29.1",
"aliyun-upload-vod": "^1.0.6",

@ -147,7 +147,7 @@ const AdvancedEditor: React.FC<AdvancedEditorProps> = ({
const initConfig = {
height,
language: 'zh_CN',
language: 'zh-CN',
onboarding: false,
languageUrl: '/tinymce/langs/zh_CN.js',
plugins: customConfig.plugins || [

@ -47,7 +47,7 @@ export interface TinyMCEConfig {
// 默认配置
export const defaultConfig: TinyMCEConfig = {
height: 400,
language: 'zh_CN',
language: 'zh-CN',
languageUrl: '/tinymce/langs/zh_CN.js',
plugins: [
'advlist', 'autolink', 'lists', 'link', 'image', 'charmap', 'preview',

@ -0,0 +1,185 @@
import { listAdminTreeUsingGet } from '@/services/pop-b2b2c/pbcCategoryController';
import {
addOrUpdateFashionTrendUsingPost,
fashionTrendDetailForAdminUsingGet,
} from '@/services/pop-b2b2c/pbcFashionTrendController';
import { getProductPageForAdminUsingPost } from '@/services/pop-b2b2c/pbcProductController';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
import { useAccess, useModel } from '@umijs/max';
import { message, Modal } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
interface LinkProductModalProps {
visible: boolean;
onCancel: () => void;
trendId?: number;
onSuccess: () => void;
}
const LinkProductModal: React.FC<LinkProductModalProps> = ({
visible,
onCancel,
trendId,
onSuccess,
}) => {
const actionRef = useRef<ActionType>();
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const [detailInfo, setDetailInfo] = useState<API.PbcFashionTrend_>();
const access: any = useAccess();
const { initialState } = useModel('@@initialState');
const { currentUser } = initialState || { currentUser: {} };
useEffect(() => {
if (visible && trendId) {
fetchTrendDetail(trendId);
} else {
setSelectedRowKeys([]);
}
}, [visible, trendId]);
const fetchTrendDetail = async (id: number) => {
try {
const res = await fashionTrendDetailForAdminUsingGet({ pbcId: id });
if (res.retcode && res.data) {
const productIds = res.data.pbcProductIds
? res.data.pbcProductIds.split(',').map(Number)
: [];
setSelectedRowKeys(productIds);
setDetailInfo(res.data);
}
} catch (error) {
message.error('获取详情失败');
}
};
const handleOk = async () => {
if (!trendId) return;
setLoading(true);
try {
const pbcProductIds = selectedRowKeys.join(',');
const res = await addOrUpdateFashionTrendUsingPost({
...detailInfo,
pbcId: trendId,
pbcProductIds: pbcProductIds,
});
if (res.retcode) {
message.success('关联成功');
onSuccess();
onCancel();
} else {
message.error(res.retmsg || '关联失败');
}
} catch (error) {
message.error('关联失败');
} finally {
setLoading(false);
}
};
const columns: ProColumns<API.PbcProductVO>[] = [
{
title: '商品ID',
dataIndex: 'pbcId',
search: false,
},
{
title: '商品大类',
dataIndex: 'pbcProductTopCategoryName',
search: false,
},
{
title: '商品中类',
dataIndex: 'pbcProductParentCategoryName',
search: false,
},
{
title: '商品小类',
dataIndex: 'pbcProductCategoryName',
search: false,
},
{
title: '商品类目',
dataIndex: 'pbcProductCategoryId',
hideInTable: true,
valueType: 'cascader',
fieldProps: {
fieldNames: { label: 'pbcCategoryName', value: 'pbcId', children: 'children' },
},
request: async () => {
const msg = await listAdminTreeUsingGet({ type: 2 });
if (msg.retcode && msg.data) {
return msg.data;
}
return [];
},
},
{
title: '商品名称',
dataIndex: 'pbcProductTitle',
},
{
title: '款号',
dataIndex: 'pbcProductCode',
},
];
return (
<Modal
title="关联商品"
open={visible}
onCancel={onCancel}
onOk={handleOk}
width={1000}
confirmLoading={loading}
destroyOnHidden
>
<ProTable<API.PbcProductVO>
columns={columns}
actionRef={actionRef}
request={async (params) => {
const queryParam: API.PbcProductPageDTO = {
...params,
startDate:
params.pbcCreateAt && params.pbcCreateAt.length > 1
? params.pbcCreateAt[0]
: undefined,
endDate:
params.pbcCreateAt && params.pbcCreateAt.length > 1
? params.pbcCreateAt[1] + ' 23:59:59'
: undefined,
};
if (params.pbcProductCategoryId && params.pbcProductCategoryId.length === 3) {
queryParam.pbcProductCategoryId = params.pbcProductCategoryId[2];
}
queryParam.pbcUserType = 2;
if (access.isBusiness) {
queryParam.pbcBusinessId = currentUser?.pbcBusinessId;
}
const msg = await getProductPageForAdminUsingPost(queryParam);
return {
data: msg.data?.records || [],
success: !!msg.retcode,
total: msg.data?.total,
};
}}
rowKey="pbcId"
search={{
labelWidth: 'auto',
}}
pagination={{
pageSize: 10,
}}
rowSelection={{
selectedRowKeys,
onChange: (keys) => setSelectedRowKeys(keys),
preserveSelectedRowKeys: true,
}}
toolBarRender={false}
/>
</Modal>
);
};
export default LinkProductModal;

@ -1,6 +1,7 @@
import React, { useEffect, useRef, useState } from 'react';
import { DrawerForm, ProFormInstance, ProFormText, ProFormUploadButton, ProFormRadio, ProForm } from '@ant-design/pro-components';
import { message } from 'antd';
import { message, Input, Button } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import Upload, { RcFile } from 'antd/es/upload';
import AdvancedEditor from '@/components/TinyMCEEditor/AdvancedEditor';
import { fullConfig } from '@/components/TinyMCEEditor/config';
@ -24,11 +25,19 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const formRef = useRef<ProFormInstance>();
const [pbcType, setPbcType] = useState<number>(1);
const [videoThumbnail, setVideoThumbnail] = useState<string>("");
const [tags, setTags] = useState<string[]>([]);
useEffect(() => {
if (props.updateModalVisible) {
setPbcType(props.values.pbcType || 1)
setVideoThumbnail(props.values.pbcThumbNail || "")
}, [props.values.pbcId]);
if (props.values.pbcTags) {
setTags(props.values.pbcTags.split(','));
} else {
setTags([]);
}
}
}, [props.updateModalVisible, props.values]);
// 生成视频缩略图的函数
const generateVideoThumbnail = async (videoUrl: string) => {
@ -108,7 +117,8 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
pbcThumbNail = value.pbcThumbNail[0].url || value.pbcThumbNail[0].response.data;
}
}
return props.onSubmit({ ...value, pbcPicAddress, pbcThumbNail, pbcContent: value.pbcType === 3 ? '预览文件' : value.pbcContent, pbcId: props.values.pbcId })
const pbcTags = tags.filter(t => t && t.trim()).join(',');
return props.onSubmit({ ...props.values, ...value, pbcPicAddress, pbcThumbNail, pbcContent: value.pbcType === 3 ? '预览文件' : value.pbcContent, pbcId: props.values.pbcId, pbcTags })
}}
drawerProps={{
destroyOnHidden: true,
@ -339,6 +349,32 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
{ required: true, message: `请上传${pbcType === 2 ? '视频' : '文件'}'` },
]}
/>}
<ProForm.Item label="标签" required>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px' }}>
{tags.map((tag, index) => (
<Input
key={index}
style={{ width: 100 }}
value={tag}
onChange={(e) => {
const newTags = [...tags];
newTags[index] = e.target.value;
setTags(newTags);
}}
placeholder="请输入标签"
/>
))}
<Button
type="link"
onClick={() => {
setTags([...tags, '']);
}}
icon={<PlusOutlined />}
>
</Button>
</div>
</ProForm.Item>
{pbcType !== 3 ? <ProForm.Item
name="pbcContent"
label="趋势内容"

@ -6,6 +6,7 @@ import React, { useRef, useState } from 'react';
import { Access, useAccess } from 'umi';
import { getFashionTrendPageUsingPost, removeFashionTrendUsingGet, addOrUpdateFashionTrendUsingPost, changeFashionTrendStateUsingGet } from '@/services/pop-b2b2c/pbcFashionTrendController';
import UpdateForm from './components/UpdateForm';
import LinkProductModal from './components/LinkProductModal';
/**
*
@ -68,6 +69,8 @@ const TableList: React.FC<any> = () => {
const actionRef = useRef<ActionType>();
const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
const [stepFormValues, setStepFormValues] = useState<API.PbcFashionTrend_>({});
const [linkModalVisible, setLinkModalVisible] = useState<boolean>(false);
const [currentTrendId, setCurrentTrendId] = useState<number>();
const handleAdd = async (fields: API.PbcFashionTrend_) => {
const hide = message.loading('正在提交');
@ -110,7 +113,7 @@ const TableList: React.FC<any> = () => {
{
title: '操作',
valueType: 'option',
width: 180,
width: 230,
render: (text, record) => (
<span>
<Access key="switch" accessible={access.fashionTrendUpdateState}>
@ -126,6 +129,18 @@ const TableList: React.FC<any> = () => {
}}
/>
</Access>
<Access key="link" accessible={access.fashionTrendSave}>
<Button
size="small"
type="link"
onClick={() => {
setCurrentTrendId(record.pbcId);
setLinkModalVisible(true);
}}
>
</Button>
</Access>
<Access key="config" accessible={access.fashionTrendSave}>
<Button
size="small"
@ -220,6 +235,14 @@ const TableList: React.FC<any> = () => {
updateModalVisible={updateModalVisible}
values={stepFormValues}
/>
<LinkProductModal
visible={linkModalVisible}
onCancel={() => setLinkModalVisible(false)}
trendId={currentTrendId}
onSuccess={() => {
actionRef.current?.reload();
}}
/>
</PageContainer>
);
};

@ -169,12 +169,6 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => {
<ProFormText
placeholder={'请输入副标题'}
label="副标题"
rules={[
{
required: true,
message: '副标题为必填项',
},
]}
width="md"
name="pbcSubTitle"
/>

@ -2,41 +2,41 @@
/* eslint-disable */
import request from '@/utils/request';
/** errorHtml GET /error */
export async function errorHtmlUsingGet(options?: { [key: string]: any }) {
return request<API.ModelAndView>('/error', {
/** error GET /error */
export async function errorUsingGet(options?: { [key: string]: any }) {
return request<Record<string, any>>('/error', {
method: 'GET',
...(options || {}),
});
}
/** errorHtml PUT /error */
export async function errorHtmlUsingPut(options?: { [key: string]: any }) {
return request<API.ModelAndView>('/error', {
/** error PUT /error */
export async function errorUsingPut(options?: { [key: string]: any }) {
return request<Record<string, any>>('/error', {
method: 'PUT',
...(options || {}),
});
}
/** errorHtml POST /error */
export async function errorHtmlUsingPost(options?: { [key: string]: any }) {
return request<API.ModelAndView>('/error', {
/** error POST /error */
export async function errorUsingPost(options?: { [key: string]: any }) {
return request<Record<string, any>>('/error', {
method: 'POST',
...(options || {}),
});
}
/** errorHtml DELETE /error */
export async function errorHtmlUsingDelete(options?: { [key: string]: any }) {
return request<API.ModelAndView>('/error', {
/** error DELETE /error */
export async function errorUsingDelete(options?: { [key: string]: any }) {
return request<Record<string, any>>('/error', {
method: 'DELETE',
...(options || {}),
});
}
/** errorHtml PATCH /error */
export async function errorHtmlUsingPatch(options?: { [key: string]: any }) {
return request<API.ModelAndView>('/error', {
/** error PATCH /error */
export async function errorUsingPatch(options?: { [key: string]: any }) {
return request<Record<string, any>>('/error', {
method: 'PATCH',
...(options || {}),
});

@ -47,7 +47,7 @@ export async function changeDefaultAddressUsingGet(
});
}
/** 根据user id获取默认收货地址 GET /b2b2c/pbcOrderAddress/getDefaultAddress */
/** 根据user id获取默认收货地址,买家端使用 GET /b2b2c/pbcOrderAddress/getDefaultAddress */
export async function getDefaultAddressUsingGet(options?: { [key: string]: any }) {
return request<API.AjaxResultPbcOrderAddress_>('/b2b2c/pbcOrderAddress/getDefaultAddress', {
method: 'GET',
@ -55,7 +55,7 @@ export async function getDefaultAddressUsingGet(options?: { [key: string]: any }
});
}
/** 根据user id获取收货地址列表 列表 GET /b2b2c/pbcOrderAddress/getOrderAddressList */
/** 根据user id获取收货地址列表 如果当前用户是商家则返回商家的地址列表 列表 GET /b2b2c/pbcOrderAddress/getOrderAddressList */
export async function getOrderAddressListUsingGet(options?: { [key: string]: any }) {
return request<API.AjaxResultListPbcOrderAddress_>('/b2b2c/pbcOrderAddress/getOrderAddressList', {
method: 'GET',

@ -2643,15 +2643,19 @@ declare namespace API {
pbcId?: number;
/** 图片或者视频的地址 */
pbcPicAddress?: string;
/** 多个商品ID使用逗号分隔例如1,2,3 */
pbcProductIds?: string;
/** 查看次数 */
pbcScanCnt?: number;
/** 状态,0是删除1是正常2是作废 */
pbcState?: number;
/** 多个标签名称,使用逗号分隔,例如:春季,宽松,休闲 */
pbcTags?: string;
/** 缩略图 */
pbcThumbNail?: string;
/** 标题 */
pbcTitle?: string;
/** 类型1是图片2是视频 */
/** 类型1是图片2是视频,3是文件 */
pbcType?: number;
/** 更新时间 */
pbcUpdateAt?: string;
@ -2659,6 +2663,8 @@ declare namespace API {
pbcUpdateBy?: number;
/** 更新人 */
pbcUpdateByUserName?: string;
/** 关联商品列表 */
productList?: PbcProduct[];
};
type PbcGenerateBusinessPosterDTO = {
@ -2964,6 +2970,8 @@ declare namespace API {
};
type PbcOrderAddress_ = {
/** 商户id */
pbcBusinessId?: number;
/** 创建时间 */
pbcCreateAt?: string;
/** 创建人 */
@ -3409,6 +3417,8 @@ declare namespace API {
pbcBusinessName?: string;
/** 主键 */
pbcId?: number;
/** 商品类目 */
pbcProductCategory?: string;
/** 商品细分类id也就是三级类目id */
pbcProductCategoryId?: number;
/** 商品细分类,也就是三级类目名称 */
@ -3423,6 +3433,8 @@ declare namespace API {
pbcProductOriginalProvince?: string;
/** 产地省份编码 */
pbcProductOriginalProvinceCode?: string;
/** 货架号 */
pbcProductShelfNumber?: string;
/** 商品标题 */
pbcProductTitle?: string;
/** 产品类型私密PRIVATE、公开PUBLIC */

Loading…
Cancel
Save