dev-v2
Joe 4 months ago
parent d68fa31ed5
commit af3bdb782c

@ -39,7 +39,6 @@ export default defineConfig({
}, },
keepalive: [/./], keepalive: [/./],
tabsLayout: { tabsLayout: {
hasDropdown: true,
hasFixedHeader: true hasFixedHeader: true
}, },
/** /**

@ -116,6 +116,7 @@ export default [
name: '采购员管理', name: '采购员管理',
path: '/purchase-agent', path: '/purchase-agent',
icon: 'UserSwitch', icon: 'UserSwitch',
access: 'purchaseAgent',
routes: [ routes: [
{ {
path: '/purchase-agent/list', path: '/purchase-agent/list',
@ -141,6 +142,7 @@ export default [
name: '商家管理', name: '商家管理',
path: '/business', path: '/business',
icon: 'shop', icon: 'shop',
access: 'business',
routes: [ routes: [
{ {
path: '/business/list', path: '/business/list',
@ -172,6 +174,7 @@ export default [
name: '会员管理', name: '会员管理',
path: '/member', path: '/member',
icon: 'team', icon: 'team',
access: 'member',
routes: [ routes: [
{ {
name: '会员管理', name: '会员管理',
@ -191,6 +194,7 @@ export default [
name: '商品管理', name: '商品管理',
path: '/product', path: '/product',
icon: 'skin', icon: 'skin',
access: 'product',
routes: [ routes: [
{ {
name: '商品类目管理', name: '商品类目管理',
@ -241,6 +245,7 @@ export default [
name: '课程管理', name: '课程管理',
path: '/training-classes', path: '/training-classes',
icon: 'book', icon: 'book',
access: 'trainingClasses',
routes: [ routes: [
{ {
name: '课程维护', name: '课程维护',

@ -4,9 +4,11 @@
export default function access(initialState: { currentUser?: API.PbcUsersVO | undefined }) { export default function access(initialState: { currentUser?: API.PbcUsersVO | undefined }) {
const { currentUser } = initialState || {}; const { currentUser } = initialState || {};
if (currentUser?.currentAuthority) { if (currentUser?.currentAuthority) {
console.log(currentUser.pbcUserRole)
const params: any = { const params: any = {
dashboard: false, dashboard: false,
dashboardUser: currentUser.pbcUserMobile !== '13052023298', dashboardUser: currentUser.pbcUserMobile !== '13052023298',
isBusiness: currentUser.pbcUserRole === 2,
dashboardQuery: false, dashboardQuery: false,
operations: false, operations: false,
operationsQuery: false, operationsQuery: false,
@ -69,11 +71,34 @@ export default function access(initialState: { currentUser?: API.PbcUsersVO | un
adBannerQuery: false, adBannerQuery: false,
adBannerAdd: false, adBannerAdd: false,
adBannerUpdate: false, adBannerUpdate: false,
purchaseAgent: false,
purchaseAgentQuery: false,
recommendPurchaseAgentQuery: false,
trainingClasses: false,
trainingClassesQuery: false,
trainingClassesCategoryQuery: false,
}; };
for (let i = 0; i < currentUser?.currentAuthority.length; i++) { for (let i = 0; i < currentUser?.currentAuthority.length; i++) {
const element = currentUser?.currentAuthority[i]; const element = currentUser?.currentAuthority[i];
params[element] = true; params[element] = true;
} }
params.product =
params.productCategoryQuery ||
params.productLabelQuery ||
params.productLabelTypeQuery ||
params.productQuery;
params.member =
params.memberQuery ||
params.memberGradeQuery;
params.purchaseAgent =
params.purchaseAgentQuery ||
params.recommendPurchaseAgentQuery;
params.business =
params.businessQuery ||
params.recommendBusinessQuery;
params.trainingClasses =
params.trainingClassesQuery ||
params.trainingClassesCategoryQuery;
return params; return params;
} }
return {}; return {};

@ -35,6 +35,7 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={ footer={
info.pbcBusinessApprovalResult === 0 info.pbcBusinessApprovalResult === 0
? [ ? [

@ -108,6 +108,7 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={[ footer={[
<Button <Button
key="back" key="back"

@ -98,6 +98,7 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={[ footer={[
<Button <Button
key="back" key="back"

@ -4,7 +4,7 @@ import dayjs from 'dayjs';
import { PageContainer, ProCard, ProForm, ProFormDateRangePicker, ProFormGroup, ProFormInstance, ProFormRadio } from '@ant-design/pro-components'; import { PageContainer, ProCard, ProForm, ProFormDateRangePicker, ProFormGroup, ProFormInstance, ProFormRadio } from '@ant-design/pro-components';
import { Button, Card, Col, message, Row, Spin, Statistic } from 'antd'; import { Button, Card, Col, message, Row, Spin, Statistic } from 'antd';
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { Access, history, useAccess } from '@umijs/max'; import { Access, history, useAccess, useModel } from '@umijs/max';
import Constants from '@/constants'; import Constants from '@/constants';
import { disabledDate } from '@/utils/utils'; import { disabledDate } from '@/utils/utils';
@ -56,6 +56,9 @@ const Welcome: React.FC = () => {
pbcViewTotalNumber: 0 pbcViewTotalNumber: 0
}); });
const { initialState } = useModel('@@initialState');
const { currentUser } = initialState || { currentUser: {} };
const config: any = { const config: any = {
xField: 'value', xField: 'value',
yField: 'label', yField: 'label',
@ -112,6 +115,9 @@ const Welcome: React.FC = () => {
param.endDate = dayjs(param.dateRange[1]).format('YYYY-MM-DD') + ' 23:59:59' param.endDate = dayjs(param.dateRange[1]).format('YYYY-MM-DD') + ' 23:59:59'
delete param.dateRange delete param.dateRange
} }
if (access.isBusiness) {
param.businessId = currentUser?.pbcBusinessId
}
handleLoadChange(true) handleLoadChange(true)
dashboardUsingPost(param).then(res => { dashboardUsingPost(param).then(res => {
handleLoadChange(false) handleLoadChange(false)
@ -251,7 +257,9 @@ const Welcome: React.FC = () => {
<Row style={{ marginBottom: 12 }} gutter={16}> <Row style={{ marginBottom: 12 }} gutter={16}>
<Col span={8}> <Col span={8}>
<Card title="注册情况" bodyStyle={{ display: 'flex', justifyContent: 'space-between' }} bordered={false}> <Card title="注册情况" bodyStyle={{ display: 'flex', justifyContent: 'space-between' }} bordered={false}>
<Statistic title="商家数" valueStyle={{ color: '#3f8600', fontSize: 30 }} value={pbcRegisterStatical.businessNumber || 0} /> <Access accessible={!access.isBusiness}>
<Statistic title="商家数" valueStyle={{ color: '#3f8600', fontSize: 30 }} value={pbcRegisterStatical.businessNumber || 0} />
</Access>
<Statistic title="会员数" valueStyle={{ color: '#3f8600', fontSize: 30 }} value={pbcRegisterStatical.vipNumber || 0} /> <Statistic title="会员数" valueStyle={{ color: '#3f8600', fontSize: 30 }} value={pbcRegisterStatical.vipNumber || 0} />
</Card> </Card>
</Col> </Col>
@ -285,33 +293,35 @@ const Welcome: React.FC = () => {
</Card> </Card>
</Col> </Col>
</Row> </Row>
<Row style={{ marginBottom: 12 }} gutter={16}> <Row gutter={[12,12]}>
<Col span={12}> <Access accessible={!access.isBusiness}>
<Card title="商户浏览量排行" extra={ <Col span={12}>
<Button type="link" onClick={() => { <Card title="商户浏览量排行" extra={
const param: any = ref.current?.getFieldsValue() <Button type="link" onClick={() => {
let startDate = param.pbcQueryType === 1 ? dayjs().format('YYYY-MM-DD') : dayjs().date(1).format('YYYY-MM-DD') const param: any = ref.current?.getFieldsValue()
let endDate = dayjs().format('YYYY-MM-DD') let startDate = param.pbcQueryType === 1 ? dayjs().format('YYYY-MM-DD') : dayjs().date(1).format('YYYY-MM-DD')
if (param.dateRange) { let endDate = dayjs().format('YYYY-MM-DD')
startDate = dayjs(param.dateRange[0]).format('YYYY-MM-DD') if (param.dateRange) {
endDate = dayjs(param.dateRange[1]).format('YYYY-MM-DD') startDate = dayjs(param.dateRange[0]).format('YYYY-MM-DD')
} endDate = dayjs(param.dateRange[1]).format('YYYY-MM-DD')
history.push(`/dashboard/business-views?startDate=${startDate}&endDate=${endDate}`)
}}>{'更多>>'}</Button>
} bordered={false}>
<Bar {...config} data={data1} onReady={(plot) => {
plot.on('plot:click', (evt: { x: any; y: any; }) => {
const { x, y } = evt;
const tooltipData = plot.chart.getTooltipItems({ x, y });
let id = ""
if (tooltipData && tooltipData.length > 0) {
id = tooltipData[0].data.pbcBusinessId
} }
history.push(`/business/detail/${id}?isEdit=0`) history.push(`/dashboard/business-views?startDate=${startDate}&endDate=${endDate}`)
}); }}>{'更多>>'}</Button>
}} /> } bordered={false}>
</Card> <Bar {...config} data={data1} onReady={(plot) => {
</Col> plot.on('plot:click', (evt: { x: any; y: any; }) => {
const { x, y } = evt;
const tooltipData = plot.chart.getTooltipItems({ x, y });
let id = ""
if (tooltipData && tooltipData.length > 0) {
id = tooltipData[0].data.pbcBusinessId
}
history.push(`/business/detail/${id}?isEdit=0`)
});
}} />
</Card>
</Col>
</Access>
<Col span={12}> <Col span={12}>
<Card title="浏览量入口占比" bordered={false}> <Card title="浏览量入口占比" bordered={false}>
<Pie {...pieConfig} onReady={(plot) => { <Pie {...pieConfig} onReady={(plot) => {
@ -343,8 +353,6 @@ const Welcome: React.FC = () => {
}} /> }} />
</Card> </Card>
</Col> </Col>
</Row>
<Row style={{ marginBottom: 12 }} gutter={16}>
<Col span={12}> <Col span={12}>
<Card title="商品浏览次数排行榜" bordered={false}> <Card title="商品浏览次数排行榜" bordered={false}>
<Bar {...config} data={data3} onReady={(plot) => { <Bar {...config} data={data3} onReady={(plot) => {
@ -375,8 +383,6 @@ const Welcome: React.FC = () => {
}} /> }} />
</Card> </Card>
</Col> </Col>
</Row>
<Row gutter={16}>
<Col span={12}> <Col span={12}>
<Card title="搜索关键词排行" bordered={false}> <Card title="搜索关键词排行" bordered={false}>
<WordCloud {...wordCloudConfig} data={data5} /> <WordCloud {...wordCloudConfig} data={data5} />

@ -1,5 +1,6 @@
import Constants from '@/constants'; import Constants from '@/constants';
import { import {
getUsersPageByBusinessIdUsingPost,
pbcUsersPageUsingPost, pbcUsersPageUsingPost,
updateMemberRecordStateUsingGet, updateMemberRecordStateUsingGet,
} from '@/services/pop-b2b2c/pbcUsersController'; } from '@/services/pop-b2b2c/pbcUsersController';
@ -7,7 +8,7 @@ import { gradeListUsingPost } from '@/services/pop-b2b2c/pbcVipGradeController';
import { handlePageQuery } from '@/utils/utils'; import { handlePageQuery } from '@/utils/utils';
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components'; import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
import { PageContainer } from '@ant-design/pro-layout'; import { PageContainer } from '@ant-design/pro-layout';
import { Access, useAccess } from '@umijs/max'; import { Access, useAccess, useModel } from '@umijs/max';
import { Button, message, Popconfirm, Switch } from 'antd'; import { Button, message, Popconfirm, Switch } from 'antd';
import React, { useRef } from 'react'; import React, { useRef } from 'react';
@ -24,6 +25,19 @@ const fetchData = async (params: API.PageVO) => {
} as any; } as any;
}; };
/**
*
* @param param0
*/
const fetchBusinessData = async (params: API.GetBusinessUserPageVO) => {
const msg = await getUsersPageByBusinessIdUsingPost(params);
return {
data: msg.data?.records,
total: msg.data?.total,
success: msg.retcode,
} as any;
};
const handleUpdateState = async (id: number, state: number) => { const handleUpdateState = async (id: number, state: number) => {
const hide = message.loading('正在保存'); const hide = message.loading('正在保存');
if (!id) return false; if (!id) return false;
@ -48,6 +62,9 @@ const TableList: React.FC<{}> = () => {
const actionRef = useRef<ActionType>(); const actionRef = useRef<ActionType>();
const access: any = useAccess(); const access: any = useAccess();
const { initialState } = useModel('@@initialState');
const { currentUser } = initialState || { currentUser: {} };
const columns: ProColumns<API.PbcUsers>[] = [ const columns: ProColumns<API.PbcUsers>[] = [
{ {
title: '会员类型', title: '会员类型',
@ -83,6 +100,7 @@ const TableList: React.FC<{}> = () => {
{ {
title: '会员等级', title: '会员等级',
dataIndex: 'pbcVipGradeName', dataIndex: 'pbcVipGradeName',
search: false,
valueType: 'select', valueType: 'select',
request: async () => { request: async () => {
const msg = await gradeListUsingPost(); const msg = await gradeListUsingPost();
@ -159,21 +177,34 @@ const TableList: React.FC<{}> = () => {
columns={columns} columns={columns}
actionRef={actionRef} actionRef={actionRef}
request={(param: any) => { request={(param: any) => {
console.log(param) let queryParam
let hasUserType = false if (access.isBusiness) {
if (param.pbcUserType) { queryParam = {
param.pbcUserType = parseInt(param.pbcUserType) ...param,
hasUserType = true pbcBusinessId: currentUser?.pbcBusinessId,
} startDate: param.pbcCreateAt && param.pbcCreateAt.length > 1 ? param.pbcCreateAt[0] : undefined,
const queryParam = handlePageQuery(param); endDate: param.pbcCreateAt && param.pbcCreateAt.length > 1 ? param.pbcCreateAt[1] : undefined,
if (!hasUserType && queryParam.filters) { pbcCreateAt: undefined
queryParam.filters.push({ }
key: 'pbcUserType'.replace(/([A-Z])/g, '_$1').toLowerCase(), return fetchBusinessData(queryParam);
value: 1, } else {
action: '<=', let hasUserType = false
}); if (param.pbcUserType) {
param.pbcUserType = parseInt(param.pbcUserType)
hasUserType = true
}
queryParam = handlePageQuery(param);
if (!hasUserType && queryParam.filters) {
queryParam.filters.push({
key: 'pbcUserType'.replace(/([A-Z])/g, '_$1').toLowerCase(),
value: 1,
action: '<=',
});
}
return fetchData(queryParam);
} }
return fetchData(queryParam);
}} }}
rowKey="pbcId" rowKey="pbcId"
size="small" size="small"

@ -79,6 +79,7 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={[ footer={[
<Button <Button
key="back" key="back"

@ -27,6 +27,7 @@ import { getLabelListForAdminUsingPost } from '@/services/pop-b2b2c/pbcProductLa
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import './index.less' import './index.less'
import CropImage from '@/components/CropImage'; import CropImage from '@/components/CropImage';
import { useAccess, useModel, history } from '@umijs/max';
interface DraggableUploadListItemProps { interface DraggableUploadListItemProps {
originNode: React.ReactElement<any, string | React.JSXElementConstructor<any>>; originNode: React.ReactElement<any, string | React.JSXElementConstructor<any>>;
@ -63,6 +64,10 @@ const Detail: React.FC<any> = () => {
const params = useParams(); const params = useParams();
const [cities] = useState(() => getCities()) const [cities] = useState(() => getCities())
const [isEdit] = useState(() => !!params.id) const [isEdit] = useState(() => !!params.id)
const access: any = useAccess();
const { initialState } = useModel('@@initialState');
const { currentUser } = initialState || { currentUser: {} };
const [colorData, setColorData] = useState<API.PbcCommonData[]>() const [colorData, setColorData] = useState<API.PbcCommonData[]>()
const [commonDataList, setCommonDataList] = useState<API.PbcCommonData[]>() const [commonDataList, setCommonDataList] = useState<API.PbcCommonData[]>()
@ -128,27 +133,61 @@ const Detail: React.FC<any> = () => {
getTags() getTags()
}, [pbcBusinessId]) }, [pbcBusinessId])
useEffect(() => {
if (access.isBusiness) {
formRef.current?.setFieldValue('pbcBusinessId', currentUser?.pbcBusinessId);
setPbcBusinessId(currentUser?.pbcBusinessId)
}
}, [])
useEffect(() => { useEffect(() => {
if (isEdit && params.id) { if (isEdit && params.id) {
productDetailForAdminUsingGet({ productId: parseInt(params.id) }).then((res) => { productDetailForAdminUsingGet({ productId: parseInt(params.id) }).then((res) => {
if (res.retcode && res.data) { if (res.retcode && res.data) {
const data = res.data; const data = res.data;
let commonData: any = {}
if (data.productCommonDataList) {
for (let i = 0; i < data.productCommonDataList.length; i++) {
const element = data.productCommonDataList[i];
if (element.pbcSystemInputType === 'select') {
commonData[`value${i}`] = element.pbcCommonDataSystemValue
} else {
commonData[`value${i}`] = element.pbcCommonDataSystem
}
}
}
// 处理表单数据 // 处理表单数据
const formData = { const formData = {
...data, ...data,
...commonData,
pbcState: data.pbcState ? `${data.pbcState}` : null, pbcState: data.pbcState ? `${data.pbcState}` : null,
pbcProductCategoryIdList: [data.pbcProductTopCategoryId, data.pbcProductParentCategoryId, data.pbcProductCategoryId], pbcProductCategoryIdList: [data.pbcProductTopCategoryId, data.pbcProductParentCategoryId, data.pbcProductCategoryId],
pbcZone: data.pbcProductOriginalProvince ? [data.pbcProductOriginalProvince, data.pbcProductOriginalCity] : undefined, pbcZone: data.pbcProductOriginalProvince ? [data.pbcProductOriginalProvince, data.pbcProductOriginalCity] : undefined,
pbcProductImages: data.pbcProductImages ? data.pbcProductImages.split(',').map((url: string) => ({ pbcProductImages: data.pbcProductImages ? data.pbcProductImages.split(',').map((url: string) => ({
uid: url, uid: url,
name: url, name: url.substring(url.lastIndexOf('/') + 1),
status: 'done', status: 'done',
url: url, url: url,
response: { data: url } response: { data: url }
})) : [], })) : [],
pbcProductDetailImages: data.pbcProductDetailImages ? data.pbcProductDetailImages.split(',').map((url: string) => ({ pbcProductDetailImages: data.pbcProductDetailImages ? data.pbcProductDetailImages.split(',').map((url: string) => ({
uid: url, uid: url,
name: url, name: url.substring(url.lastIndexOf('/') + 1),
status: 'done',
url: url,
response: { data: url }
})) : [],
pbcProductVideoThumbnail: data.pbcProductVideoThumbnail ? [{
uid: data.pbcProductVideoThumbnail,
name: data.pbcProductVideoThumbnail.substring(data.pbcProductVideoThumbnail.lastIndexOf('/') + 1),
status: 'done',
url: data.pbcProductVideoThumbnail,
response: { data: data.pbcProductVideoThumbnail }
}] : [],
pbcProductDetailVideos: data.pbcProductDetailVideos ? data.pbcProductDetailVideos.split(',').map((url: string) => ({
uid: url,
name: url.substring(url.lastIndexOf('/') + 1),
status: 'done', status: 'done',
url: url, url: url,
response: { data: url } response: { data: url }
@ -256,7 +295,6 @@ const Detail: React.FC<any> = () => {
if (commonDataList) { if (commonDataList) {
for (let i = 0; i < commonDataList.length; i++) { for (let i = 0; i < commonDataList.length; i++) {
const element = commonDataList[i]; const element = commonDataList[i];
console.log(values[`value${i}`])
let name = '' let name = ''
if (element.pbcSystemInputType === 'select' && element.commonDataValueList) { if (element.pbcSystemInputType === 'select' && element.commonDataValueList) {
name = element.commonDataValueList.find(e => e.pbcId === values[`value${i}`])?.pbcSystemValue || '' name = element.commonDataValueList.find(e => e.pbcId === values[`value${i}`])?.pbcSystemValue || ''
@ -288,6 +326,8 @@ const Detail: React.FC<any> = () => {
productCommonDataList: specItems, productCommonDataList: specItems,
pbcProductImages: values.pbcProductImages.filter((e: any) => e.response && e.response.data).map((e: any) => e.response.data).join(','), pbcProductImages: values.pbcProductImages.filter((e: any) => e.response && e.response.data).map((e: any) => e.response.data).join(','),
pbcProductDetailImages: values.pbcProductDetailImages.filter((e: any) => e.response && e.response.data).map((e: any) => e.response.data).join(','), pbcProductDetailImages: values.pbcProductDetailImages.filter((e: any) => e.response && e.response.data).map((e: any) => e.response.data).join(','),
pbcProductVideoThumbnail: values.pbcProductVideoThumbnail && values.pbcProductVideoThumbnail.length > 0 ? values.pbcProductVideoThumbnail[0].response.data : '',
pbcProductDetailVideos: values.pbcProductDetailVideos && values.pbcProductDetailVideos.length > 0 ? values.pbcProductDetailVideos.filter((e: any) => e.response && e.response.data).map((e: any) => e.response.data).join(',') : '',
pbcZone: undefined, pbcZone: undefined,
colorItems: undefined, colorItems: undefined,
specItems: undefined, specItems: undefined,
@ -295,9 +335,11 @@ const Detail: React.FC<any> = () => {
} }
const msg = await addOrUpdateProductForAdminUsingPost(params) const msg = await addOrUpdateProductForAdminUsingPost(params)
if (msg.retcode) { if (msg.retcode) {
formRef.current?.resetFields() if (!isEdit) {
formRef.current?.resetFields()
}
message.success("保存成功!") message.success("保存成功!")
history.back(); history.push('/product/list')
return true return true
} else { } else {
message.error(msg.retmsg) message.error(msg.retmsg)
@ -324,11 +366,12 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={[ footer={[
<Button <Button
key="back" key="back"
onClick={() => { onClick={() => {
history.back(); history.push('/product/list')
}} }}
> >
@ -351,6 +394,7 @@ const Detail: React.FC<any> = () => {
rules={[ rules={[
{ required: true, message: '请选择所属商户' } { required: true, message: '请选择所属商户' }
]} ]}
disabled={access.isBusiness}
onChange={(value) => { onChange={(value) => {
formRef.current?.setFieldValue('labelAssociationList', []) formRef.current?.setFieldValue('labelAssociationList', [])
setPbcBusinessId(value as number) setPbcBusinessId(value as number)
@ -621,10 +665,7 @@ const Detail: React.FC<any> = () => {
}, },
onPreview: async (file) => { onPreview: async (file) => {
if (file.uid === '-1') { if (file.response && file.response.data) {
window.open(file.url);
}
if (file.response && file.response.retcode) {
window.open(file.response.data); window.open(file.response.data);
} }
}, },
@ -662,11 +703,7 @@ const Detail: React.FC<any> = () => {
return isLt2M || Upload.LIST_IGNORE; return isLt2M || Upload.LIST_IGNORE;
}, },
onPreview: async (file) => { onPreview: async (file) => {
if (file.response && file.response.data) {
if (file.uid === '-1') {
window.open(file.url);
}
if (file.response && file.response.retcode) {
window.open(file.response.data); window.open(file.response.data);
} }
}, },
@ -680,6 +717,100 @@ const Detail: React.FC<any> = () => {
</DndContext> </DndContext>
</Col> </Col>
</Row> </Row>
<Row gutter={20}>
<Col span={24}>
<ProFormUploadButton
label="封面视频"
name="pbcProductVideoThumbnail"
max={1}
fieldProps={{
name: 'file',
accept: 'video/mp4',
multiple: false,
headers: {
authorization: localStorage.getItem('token') ?? '',
},
action: process.env.BASE_URL + '/oss/imgUpload',
beforeUpload(file: RcFile) {
const isLt100M = file.size / 1024 / 1024 < 100;
if (!isLt100M) {
message.error('视频大小不能超过100MB!');
}
return isLt100M || Upload.LIST_IGNORE;
},
onPreview: async (file) => {
const url = file.url || (file.response && file.response.data);
if (url) {
const videoWindow = window.open('', '_blank');
if (videoWindow) {
videoWindow.document.write(`
<html>
<body style=\"margin:0;display:flex;align-items:center;justify-content:center;height:100vh;background:#000;\">
<video src=\"${url}\" controls autoplay style=\"max-width:100vw;max-height:100vh;\"></video>
</body>
</html>
`);
}
} else {
message.warning('无法预览该视频');
}
},
}}
rules={[
{ required: false, message: '请上传封面视频' },
]}
/>
</Col>
</Row>
<Row gutter={20}>
<Col span={24}>
<DndContext sensors={[sensor]} onDragEnd={(event) => onDragEnd(event, "pbcProductDetailVideos")}>
<SortableContext items={formRef.current?.getFieldValue("pbcProductDetailVideos") ? formRef.current?.getFieldValue("pbcProductDetailVideos").map((i: any) => i.uid) : []} strategy={verticalListSortingStrategy}>
<ProFormUploadButton
label="详情视频"
name="pbcProductDetailVideos"
fieldProps={{
name: 'file',
accept: 'video/mp4',
multiple: true,
headers: {
authorization: localStorage.getItem('token') ?? '',
},
itemRender: (originNode, file) => <DraggableUploadListItem originNode={originNode} file={file} />,
action: process.env.BASE_URL + '/oss/imgUpload',
beforeUpload(file: RcFile) {
const isLt100M = file.size / 1024 / 1024 < 100;
if (!isLt100M) {
message.error('视频大小不能超过100MB!');
}
return isLt100M || Upload.LIST_IGNORE;
},
onPreview: async (file) => {
const url = file.url || (file.response && file.response.data);
if (url) {
const videoWindow = window.open('', '_blank');
if (videoWindow) {
videoWindow.document.write(`
<html>
<body style=\"margin:0;display:flex;align-items:center;justify-content:center;height:100vh;background:#000;\">
<video src=\"${url}\" controls autoplay style=\"max-width:100vw;max-height:100vh;\"></video>
</body>
</html>
`);
}
} else {
message.warning('无法预览该视频');
}
},
}}
rules={[
{ required: false, message: '请上传详情视频' },
]}
/>
</SortableContext>
</DndContext>
</Col>
</Row>
{commonDataList ? commonDataList.map((e, index) => <Row key={e.pbcId} align="middle" gutter={20}> {commonDataList ? commonDataList.map((e, index) => <Row key={e.pbcId} align="middle" gutter={20}>
<Col span={6}> <Col span={6}>
<ProFormText width="sm" disabled name={`name${index}`} initialValue={e.pbcSystemName} placeholder="请输入规格名称" rules={[ <ProFormText width="sm" disabled name={`name${index}`} initialValue={e.pbcSystemName} placeholder="请输入规格名称" rules={[

@ -5,9 +5,10 @@ import {
import { CheckCircleOutlined, InfoCircleOutlined } from '@ant-design/icons'; import { CheckCircleOutlined, InfoCircleOutlined } from '@ant-design/icons';
import { ProCard } from '@ant-design/pro-components'; import { ProCard } from '@ant-design/pro-components';
import { PageContainer } from '@ant-design/pro-layout'; import { PageContainer } from '@ant-design/pro-layout';
import { Access, useAccess, useParams } from '@umijs/max'; import { Access, useAccess, useParams, history } from '@umijs/max';
import { Button, Col, Descriptions, Image, message, Row, Tag } from 'antd'; import { Button, Col, Descriptions, Image, message, Row, Tag } from 'antd';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import Constants from '@/constants';
const Detail: React.FC<any> = () => { const Detail: React.FC<any> = () => {
const params = useParams(); const params = useParams();
@ -44,13 +45,14 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={ footer={
info.pbcState !== 3 info.pbcState !== 3
? [ ? [
<Button <Button
key="back" key="back"
onClick={() => { onClick={() => {
history.back(); history.push('/product/list')
}} }}
> >
@ -80,7 +82,7 @@ const Detail: React.FC<any> = () => {
<Button <Button
key="back" key="back"
onClick={() => { onClick={() => {
history.back(); history.push('/product/list')
}} }}
> >
@ -106,15 +108,21 @@ const Detail: React.FC<any> = () => {
</> </>
} }
column={3} column={3}
contentStyle={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all', maxWidth: 400 }}
> >
<Descriptions.Item label="名称">{info.pbcProductTitle}</Descriptions.Item> <Descriptions.Item label="名称" style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all', maxWidth: 400 }}>{info.pbcProductTitle}</Descriptions.Item>
<Descriptions.Item label="商品类目"> <Descriptions.Item label="商品类目" style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all', maxWidth: 400 }}>
{info.pbcProductTopCategoryName}/{info.pbcProductParentCategoryName}/ {info.pbcProductTopCategoryName}/{info.pbcProductParentCategoryName}/
{info.pbcProductCategoryName} {info.pbcProductCategoryName}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="价格">¥{info.pbcProductPrice}</Descriptions.Item> <Descriptions.Item label="价格">¥{info.pbcProductPrice}</Descriptions.Item>
<Descriptions.Item label="所属商户" style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all', maxWidth: 400 }}>{info.pbcBusinessName}</Descriptions.Item>
<Descriptions.Item label="编号" style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all', maxWidth: 400 }}>{info.pbcProductCode}</Descriptions.Item>
<Descriptions.Item label="产地" style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all', maxWidth: 400 }}>{info.pbcProductOriginalProvince}{info.pbcProductOriginalCity ? '/' + info.pbcProductOriginalCity : ''}</Descriptions.Item>
<Descriptions.Item label="库存">{info.pbcProductStock}</Descriptions.Item>
<Descriptions.Item label="货架号" span={2}>{info.pbcProductShelfNumber}</Descriptions.Item>
<Descriptions.Item label="颜色" span={3}> <Descriptions.Item label="颜色" span={3}>
<div style={{ display: 'flex', flexWrap: 'wrap', width: 1000 }}> <div style={{ display: 'flex', flexWrap: 'wrap', maxWidth: 800 }}>
{info.colorDataList?.map((e) => ( {info.colorDataList?.map((e) => (
<Row <Row
key={e.pbcId} key={e.pbcId}
@ -123,18 +131,33 @@ const Detail: React.FC<any> = () => {
> >
<Col span={8}>{e.pbcCommonDataSystem}</Col> <Col span={8}>{e.pbcCommonDataSystem}</Col>
<Col span={8}> <Col span={8}>
<Image width={100} src={e.pbcColorImageUrl} /> <Image style={{ objectFit: 'contain' }} width={100} height={100} src={e.pbcColorImageUrl} />
</Col> </Col>
</Row> </Row>
))} ))}
</div> </div>
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="商品标签" span={3} style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all', maxWidth: 400 }}>
{info.labelAssociationList && info.labelAssociationList.length > 0 ? info.labelAssociationList.map((tag: any) => (
<Tag key={tag.pbcId}>{tag.pbcLabelName}</Tag>
)) : '-'}
</Descriptions.Item>
<Descriptions.Item label="封面视频" span={3}>
{info.pbcProductVideoThumbnail ? (
<video width={240} height={160} controls src={info.pbcProductVideoThumbnail} style={{ background: '#000' }} />
) : '-'}
</Descriptions.Item>
<Descriptions.Item label="详情视频" span={3}>
{info.pbcProductDetailVideos ? info.pbcProductDetailVideos.split(',').map((url: string) => (
<video key={url} width={240} height={160} controls src={url} style={{ marginRight: 12, background: '#000' }} />
)) : '-'}
</Descriptions.Item>
<Descriptions.Item label="相册图片" span={3}> <Descriptions.Item label="相册图片" span={3}>
<div style={{ display: 'flex', width: '100%', flexWrap: 'wrap' }}> <div style={{ display: 'flex', width: '100%', flexWrap: 'wrap' }}>
<Image.PreviewGroup> <Image.PreviewGroup>
{images.map((e) => ( {images.map((e) => (
<div key={e} style={{ marginBottom: 10, marginRight: 20 }}> <div key={e} style={{ marginBottom: 10, marginRight: 20 }}>
<Image width={100} src={e} /> <Image style={{ objectFit: 'contain' }} width={100} height={100} src={e} />
</div> </div>
))} ))}
</Image.PreviewGroup> </Image.PreviewGroup>
@ -145,7 +168,7 @@ const Detail: React.FC<any> = () => {
<Image.PreviewGroup> <Image.PreviewGroup>
{detailImages.map((e) => ( {detailImages.map((e) => (
<div key={e} style={{ marginBottom: 10, marginRight: 20 }}> <div key={e} style={{ marginBottom: 10, marginRight: 20 }}>
<Image width={100} src={e} /> <Image style={{ objectFit: 'contain' }} width={100} height={100} src={e} />
</div> </div>
))} ))}
</Image.PreviewGroup> </Image.PreviewGroup>
@ -169,12 +192,11 @@ const Detail: React.FC<any> = () => {
</Row> </Row>
))} ))}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="详情描述" span={3}> <Descriptions.Item label="详情描述" span={3} style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-all', maxWidth: 400 }}>
{info.pbcProductDetail} {info.pbcProductDetail}
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="可见范围" span={3}> <Descriptions.Item label="状态">{Constants.pbcState?.[info.pbcState as keyof typeof Constants.pbcState] || '-'}</Descriptions.Item>
{info.pbcProductVipLevels} <Descriptions.Item label="可见范围">{Constants.pbcProductType?.[info.pbcProductType as keyof typeof Constants.pbcProductType] || '-'}</Descriptions.Item>
</Descriptions.Item>
</Descriptions> </Descriptions>
</ProCard> </ProCard>
</PageContainer> </PageContainer>

@ -8,7 +8,7 @@ import {
} from '@/services/pop-b2b2c/pbcProductController'; } from '@/services/pop-b2b2c/pbcProductController';
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components'; import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
import { PageContainer } from '@ant-design/pro-layout'; import { PageContainer } from '@ant-design/pro-layout';
import { Access, useAccess, history, useLocation } from '@umijs/max'; import { Access, useAccess, history, useLocation, useModel } from '@umijs/max';
import { Button, message, Popconfirm, Space } from 'antd'; import { Button, message, Popconfirm, Space } from 'antd';
import moment from 'moment'; import moment from 'moment';
import React, { useRef, useEffect } from 'react'; import React, { useRef, useEffect } from 'react';
@ -36,6 +36,9 @@ const TableList: React.FC<{}> = () => {
const access: any = useAccess(); const access: any = useAccess();
const location = useLocation(); const location = useLocation();
const { initialState } = useModel('@@initialState');
const { currentUser } = initialState || { currentUser: {} };
useEffect(() => { useEffect(() => {
actionRef.current?.reload(); actionRef.current?.reload();
}, [location.pathname]); }, [location.pathname]);
@ -94,6 +97,7 @@ const TableList: React.FC<{}> = () => {
title: '所属商户', title: '所属商户',
dataIndex: 'pbcBusinessId', dataIndex: 'pbcBusinessId',
hideInTable: true, hideInTable: true,
search: !access.isBusiness,
valueType: 'select', valueType: 'select',
fieldProps: { fieldProps: {
showSearch: true, showSearch: true,
@ -132,7 +136,7 @@ const TableList: React.FC<{}> = () => {
{ {
title: '操作', title: '操作',
fixed: 'right', fixed: 'right',
width: 300, width: 230,
valueType: 'option', valueType: 'option',
render: (text, record) => ( render: (text, record) => (
<Space> <Space>
@ -165,24 +169,26 @@ const TableList: React.FC<{}> = () => {
</Button> </Button>
) : ( ) : (
<Button <Access accessible={!access.isBusiness}>
type="link" <Button
size="small" type="link"
onClick={() => { size="small"
changeProductStateForAdminUsingGet({ pcbId: record.pbcId || 0, state: 1 }).then( onClick={() => {
(res) => { changeProductStateForAdminUsingGet({ pcbId: record.pbcId || 0, state: 1 }).then(
if (res.retcode) { (res) => {
message.success('已上架'); if (res.retcode) {
actionRef.current?.reload(); message.success('已上架');
} else { actionRef.current?.reload();
message.error(res.retmsg); } else {
} message.error(res.retmsg);
}, }
); },
}} );
> }}
>
</Button>
</Button>
</Access>
)} )}
</Access> </Access>
<Access key="remove" accessible={access.productRemove}> <Access key="remove" accessible={access.productRemove}>
@ -230,6 +236,9 @@ const TableList: React.FC<{}> = () => {
startDate: param.pbcCreateAt && param.pbcCreateAt.length > 1 ? param.pbcCreateAt[0] : undefined, startDate: param.pbcCreateAt && param.pbcCreateAt.length > 1 ? param.pbcCreateAt[0] : undefined,
endDate: param.pbcCreateAt && param.pbcCreateAt.length > 1 ? param.pbcCreateAt[1] + ' 23:59:59' : undefined endDate: param.pbcCreateAt && param.pbcCreateAt.length > 1 ? param.pbcCreateAt[1] + ' 23:59:59' : undefined
} }
if (access.isBusiness) {
queryParam.pbcBusinessId = currentUser?.pbcBusinessId
}
return fetchData(queryParam); return fetchData(queryParam);
}} }}
rowKey="pbcId" rowKey="pbcId"

@ -33,6 +33,7 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={ footer={
info.pbcReviewStatus === 0 info.pbcReviewStatus === 0
? [ ? [

@ -30,6 +30,7 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={ footer={
info.pbcApprovalStatus === 0 info.pbcApprovalStatus === 0
? [ ? [

@ -79,6 +79,7 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={[ footer={[
<Button <Button
key="back" key="back"

@ -59,6 +59,7 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={[ footer={[
<Button <Button
key="back" key="back"

@ -288,6 +288,7 @@ const Detail: React.FC<any> = () => {
header={{ header={{
title: '', title: '',
}} }}
footerToolBarProps={{ portalDom: false }}
footer={[ footer={[
<Button <Button
key="back" key="back"

@ -313,3 +313,11 @@ export async function searchProductListUsingPost(
...(options || {}), ...(options || {}),
}); });
} }
/** 查看商品列表 通用 POST /b2b2c/pbcproduct/update */
export async function updateUsingPost(options?: { [key: string]: any }) {
return request<API.AjaxResult>('/b2b2c/pbcproduct/update', {
method: 'POST',
...(options || {}),
});
}

@ -124,7 +124,7 @@ export async function typeListUsingPatch(body: API.AjaxRequest, options?: { [key
} }
/** 热销商品列表,类型有新品、主推、热销 列表 POST /b2b2c/pbcproducthot/update */ /** 热销商品列表,类型有新品、主推、热销 列表 POST /b2b2c/pbcproducthot/update */
export async function updateUsingPost(body: API.PbcProductHot, options?: { [key: string]: any }) { export async function updateUsingPost1(body: API.PbcProductHot, options?: { [key: string]: any }) {
return request<API.AjaxResultString_>('/b2b2c/pbcproducthot/update', { return request<API.AjaxResultString_>('/b2b2c/pbcproducthot/update', {
method: 'POST', method: 'POST',
headers: { headers: {

@ -124,3 +124,21 @@ export async function getLabelListForFrontUsingPost(
}, },
); );
} }
/** 获取标签分页 分页 POST /b2b2c/pbcProductLabelConfig/front/getLabelPage */
export async function getLabelPageForFrontUsingPost(
body: API.PbcProductLabelConfig_,
options?: { [key: string]: any },
) {
return request<API.AjaxResultIPagePbcProductLabelConfig_>(
'/b2b2c/pbcProductLabelConfig/front/getLabelPage',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
},
);
}

@ -4,8 +4,11 @@ import request from '@/utils/request';
/** 获取昨天的热门标签 GET /b2b2c/pbcProductLabelHot/front/getHotLabelList */ /** 获取昨天的热门标签 GET /b2b2c/pbcProductLabelHot/front/getHotLabelList */
export async function getHotLabelListUsingGet(options?: { [key: string]: any }) { export async function getHotLabelListUsingGet(options?: { [key: string]: any }) {
return request<API.AjaxResultListString_>('/b2b2c/pbcProductLabelHot/front/getHotLabelList', { return request<API.AjaxResultListPbcProductLabelConfig_>(
method: 'GET', '/b2b2c/pbcProductLabelHot/front/getHotLabelList',
...(options || {}), {
}); method: 'GET',
...(options || {}),
},
);
} }

@ -137,6 +137,21 @@ export async function getUserRecordByIdUsingGet(
}); });
} }
/** getUsersPageByBusinessId 分页,按照搜索条件查询出用户记录 POST /b2b2c/pbcusers/getUsersPageByBusinessId */
export async function getUsersPageByBusinessIdUsingPost(
body: API.GetBusinessUserPageVO,
options?: { [key: string]: any },
) {
return request<API.AjaxResultIPagePbcUsers_>('/b2b2c/pbcusers/getUsersPageByBusinessId', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
/** 导入店铺会员 import POST /b2b2c/pbcusers/importMember */ /** 导入店铺会员 import POST /b2b2c/pbcusers/importMember */
export async function importMemberUsingPost( export async function importMemberUsingPost(
body: {}, body: {},

@ -309,6 +309,12 @@ declare namespace API {
retmsg?: string; retmsg?: string;
}; };
type AjaxResultListPbcProductLabelConfig_ = {
data?: PbcProductLabelConfig_[];
retcode?: number;
retmsg?: string;
};
type AjaxResultListPbcProductLabelConfigType_ = { type AjaxResultListPbcProductLabelConfigType_ = {
data?: PbcProductLabelConfigType_[]; data?: PbcProductLabelConfigType_[];
retcode?: number; retcode?: number;
@ -393,12 +399,6 @@ declare namespace API {
retmsg?: string; retmsg?: string;
}; };
type AjaxResultListString_ = {
data?: string[];
retcode?: number;
retmsg?: string;
};
type AjaxResultLong_ = { type AjaxResultLong_ = {
data?: number; data?: number;
retcode?: number; retcode?: number;
@ -950,6 +950,31 @@ declare namespace API {
businessId: number; businessId: number;
}; };
type GetBusinessUserPageVO = {
/** 当前页 */
current?: number;
/** 注册结束日期 */
endDate?: string;
/** 条数 */
pageSize?: number;
/** 商户id */
pbcBusinessId?: number;
/** 状态,0是删除1是正常2是作废 */
pbcState?: number;
/** 用户手机号 */
pbcUserMobile?: string;
/** 用户姓名 */
pbcUserName?: string;
/** 用户昵称 */
pbcUserNickName?: string;
/** 用户分享源的昵称 */
pbcUserSourceUserNickName?: string;
/** 0表示商户1表示会员, 2管理员 */
pbcUserType?: number;
/** 注册开始日期 */
startDate?: string;
};
type getEmailVerificationCodeUsingGETParams = { type getEmailVerificationCodeUsingGETParams = {
/** email */ /** email */
email: string; email: string;
@ -2823,6 +2848,8 @@ declare namespace API {
pbcProductDetailImages?: string; pbcProductDetailImages?: string;
/** 细节视频 */ /** 细节视频 */
pbcProductDetailVideos?: string; pbcProductDetailVideos?: string;
/** 店铺主页宣传 */
pbcProductHomepagePromotion?: string;
/** 浏览量 */ /** 浏览量 */
pbcProductHot?: number; pbcProductHot?: number;
/** 商品相册图 */ /** 商品相册图 */
@ -2853,6 +2880,8 @@ declare namespace API {
pbcProductTopCategoryName?: string; pbcProductTopCategoryName?: string;
/** 产品类型私密PRIVATE、公开PUBLIC */ /** 产品类型私密PRIVATE、公开PUBLIC */
pbcProductType?: string; pbcProductType?: string;
/** 视频封面 */
pbcProductVideoThumbnail?: string;
/** 逗号分割字符串,私密商品,对应会员等级 */ /** 逗号分割字符串,私密商品,对应会员等级 */
pbcProductVipLevels?: string; pbcProductVipLevels?: string;
/** 成品鞋展示图片地址 */ /** 成品鞋展示图片地址 */
@ -2952,6 +2981,8 @@ declare namespace API {
pbcProductDetailImages?: string; pbcProductDetailImages?: string;
/** 细节视频 */ /** 细节视频 */
pbcProductDetailVideos?: string; pbcProductDetailVideos?: string;
/** 店铺主页宣传 */
pbcProductHomepagePromotion?: string;
/** 商品相册图 */ /** 商品相册图 */
pbcProductImages?: string; pbcProductImages?: string;
/** 产地城市 */ /** 产地城市 */
@ -2980,6 +3011,8 @@ declare namespace API {
pbcProductTopCategoryName?: string; pbcProductTopCategoryName?: string;
/** 产品类型:私密、公开 */ /** 产品类型:私密、公开 */
pbcProductType?: string; pbcProductType?: string;
/** 视频封面 */
pbcProductVideoThumbnail?: string;
/** 逗号分割字符串,私密商品,对应会员等级 */ /** 逗号分割字符串,私密商品,对应会员等级 */
pbcProductVipLevels?: string; pbcProductVipLevels?: string;
/** 成品鞋展示图片地址 */ /** 成品鞋展示图片地址 */
@ -3183,6 +3216,8 @@ declare namespace API {
pageSize?: number; pageSize?: number;
/** 商户id */ /** 商户id */
pbcBusinessId?: number; pbcBusinessId?: number;
/** 商品标签id */
pbcProductLabelId?: number;
/** 产地城市 */ /** 产地城市 */
pbcProductOriginalCity?: string; pbcProductOriginalCity?: string;
/** 产地城市编码 */ /** 产地城市编码 */
@ -3302,6 +3337,8 @@ declare namespace API {
pbcProductDetailImages?: string; pbcProductDetailImages?: string;
/** 细节视频 */ /** 细节视频 */
pbcProductDetailVideos?: string; pbcProductDetailVideos?: string;
/** 店铺主页宣传 */
pbcProductHomepagePromotion?: string;
/** 浏览量 */ /** 浏览量 */
pbcProductHot?: number; pbcProductHot?: number;
/** 商品相册图 */ /** 商品相册图 */
@ -3332,6 +3369,8 @@ declare namespace API {
pbcProductTopCategoryName?: string; pbcProductTopCategoryName?: string;
/** 产品类型私密PRIVATE、公开PUBLIC */ /** 产品类型私密PRIVATE、公开PUBLIC */
pbcProductType?: string; pbcProductType?: string;
/** 视频封面 */
pbcProductVideoThumbnail?: string;
/** 逗号分割字符串,私密商品,对应会员等级 */ /** 逗号分割字符串,私密商品,对应会员等级 */
pbcProductVipLevels?: string; pbcProductVipLevels?: string;
/** 成品鞋展示图片地址 */ /** 成品鞋展示图片地址 */

Loading…
Cancel
Save