Commit 1b62e1f0 authored by XieZhiXiong's avatar XieZhiXiong
parents 9233b1fc b64ff9d2
......@@ -39,9 +39,9 @@
"braft-editor": "^2.3.9",
"classnames": "^2.2.6",
"core-js": "^3.6.5",
"god": "^0.1.25",
"god": "^0.1.26",
"lingxi-design": "^1.0.7",
"lingxi-design-ui": "^1.0.8",
"lingxi-design-ui": "^1.0.9",
"lingxi-editor-core": "^1.0.6",
"lingxi-web": "^1.0.6",
"lint-staged": "^10.0.7",
......@@ -65,4 +65,4 @@
"ora": "^4.0.4",
"typescript": "^3.9.7"
}
}
}
\ No newline at end of file
......@@ -4,17 +4,21 @@
*/
//express模块
console.log(process.argv)
var express =require("express");
var app =express();
const path = require('path')
const { createProxyMiddleware } = require('http-proxy-middleware')
const port = 4398
const apiProxyTarget = 'http://10.0.0.25:8100'
// 用于解决刷新后404问题
var history = require('connect-history-api-fallback');
app.use('/api',createProxyMiddleware(
{
target: 'http://10.0.0.25:8100',
target: apiProxyTarget,
changeOrigin: true,
pathRewrite: { '^/api' : '' }
}
......
......@@ -4,6 +4,7 @@
.size_require {
color: #97A0AF;
margin-left: 24px;
}
.upload_btn {
......@@ -11,7 +12,6 @@
width: 104px;
height: 104px;
display: flex;
margin-right: 24px;
align-items: center;
justify-content: center;
color: #6B778C;
......@@ -26,6 +26,11 @@
border: 1px dashed rgba(223, 225, 230, 1);
}
&.large {
width: 175px;
height: 120px;
}
&>img {
height: 100%;
width: auto;
......@@ -33,17 +38,41 @@
margin: 0 auto;
}
.img_box {
width: 104px;
height: 104px;
background-size: auto 100%;
background-repeat: no-repeat;
background-position: center center;
&>p {
margin-top: 12px;
}
}
// 删除效果
.delete_wrap {
display: none;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
position: absolute;
left: 0;
top: 0;
border-radius: 2px;
.delete_btn {
color: #fff;
position: absolute;
top:50%;
left:50%;
transform: translate(-50%, -50%);
}
}
&>p {
margin-top: 12px;
.upload_wrap{
position: relative;
width: 104px;
height: 104px;
&:hover {
.delete_wrap {
display: block;
}
}
}
}
\ No newline at end of file
import React, { useState, Fragment, forwardRef } from 'react'
import { Upload, message } from 'antd'
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons'
import { Upload, message, Button } from 'antd'
import { LoadingOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons'
import { UploadFile, UploadChangeParam } from 'antd/lib/upload/interface'
import cx from 'classnames'
import styles from './index.less'
......@@ -10,21 +10,24 @@ interface UploadImagePorpsType {
size?: string;
onChange: Function;
disabled?: boolean;
large?: boolean;
fileMaxSize?: number;
showDesc?: boolean
}
const UploadImage: React.FC<UploadImagePorpsType> = forwardRef((props, ref) => {
const { imgUrl, onChange, size = "386x256", disabled = false } = props
const { imgUrl, onChange, showDesc = true, size = "386x256", disabled = false, large = false, fileMaxSize = 200 } = props
const [loading, setLoading] = useState<boolean>(false)
const beforeUpload = (file: UploadFile) => {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg';
if (!isJpgOrPng) {
message.error('仅支持上传JPEG/JPG/PNG文件!');
}
const isLt200k = file.size / 1024 < 200;
if (!isLt200k) {
message.error('上传图片不超过200K!');
const isSizeLimit = file.size / 1024 < fileMaxSize;
if (!isSizeLimit) {
message.error(`上传图片不超过${fileMaxSize}K!`);
}
return isJpgOrPng && isLt200k;
return isJpgOrPng && isSizeLimit;
}
const uploadProps = {
......@@ -54,6 +57,10 @@ const UploadImage: React.FC<UploadImagePorpsType> = forwardRef((props, ref) => {
beforeUpload
};
const clearImage = () => {
onChange('')
}
const uploadButton = (
<Fragment>
{loading ? <LoadingOutlined /> : <PlusOutlined />}
......@@ -63,16 +70,24 @@ const UploadImage: React.FC<UploadImagePorpsType> = forwardRef((props, ref) => {
return (
<div className={styles.upload_image_wrap}>
<Upload {...uploadProps}>
{<div className={cx(styles.upload_btn, !imgUrl ? styles.isAdd : "")}>
{
imgUrl ? <div className={styles.img_box} style={{ backgroundImage: `url(${imgUrl})` }} ></div> : uploadButton
}
</div>}
</Upload>
<div className={styles.size_require}>
<p>支持JPG/PNG/JPEG, <br />最大不超过 200K, <br />尺寸:{size}</p>
<div className={styles.upload_wrap}>
<Upload {...uploadProps}>
{<div className={cx(styles.upload_btn, !imgUrl ? styles.isAdd : "", large ? styles.large : '')}>
{
imgUrl ? <img src={imgUrl} /> : uploadButton
}
</div>}
</Upload>
{
imgUrl && <div className={styles.delete_wrap}><Button onClick={clearImage} className={styles.delete_btn} type="text" icon={<DeleteOutlined />} /></div>
}
</div>
{
showDesc &&
<div className={styles.size_require}>
<p>支持JPG/PNG/JPEG, <br />最大不超过 {fileMaxSize}K, <br />尺寸:{size}</p>
</div>
}
</div>
)
})
......
......@@ -36,6 +36,33 @@ export const SHOP_TYPES = [
name: "渠道积分商城"
},
]
export enum LAYOUT_TYPE {
/**
* 企业商城
*/
mall = 'mall',
/**
* 店铺(店铺商城)
*/
shop = 'shop',
/**
* 渠道商城
*/
channel = 'channel',
/**
* 企业商城-积分商城
*/
scoreMall = 'scoreMall',
/**
* 店铺-积分兑换
*/
shopScoreMall = 'shopScoreMall',
/**
* 渠道商城-积分兑换
*/
channelScoreMall = 'channelScoreMall',
}
// 本地环境跳过权限校验
export const isDev = process.env.NODE_ENV === "development"
......
......@@ -15,6 +15,7 @@ import { PublicApi } from '@/services/api';
import TabTree from '@/components/TabTree';
import { createFormActions } from '@formily/antd';
import { useTreeTabs } from '@/hooks/useTreeTabs';
import { useRowSelectionTable } from '@/hooks/useRowSelectionTable';
const formActions = createFormActions()
......@@ -35,6 +36,7 @@ const CategoryAttributes: React.FC<{}> = () => {
const [selectTableRow, setSelectTableRow] = useState<any[]>([])
const [selectedTableRowKeys, setSelectedTableRowKeys] = useState<Array<number>>([]) //表格选择
const [linkTableRowData, setLinkTableRowData] = useState<any[]>([])
const [attributeRowSelection, attributeRowCtl] = useRowSelectionTable()
const {
treeStatus,
......@@ -55,25 +57,28 @@ const CategoryAttributes: React.FC<{}> = () => {
// 获取选中项的关联属性列表
useEffect(() => {
if (selectKey)
ref.current.reload({ current: 1, pageSize: 10, name: '', categoryId: selectKey })
ref.current.reload({ current: 1, pageSize: 10, name: '', categoryId: selectKey, isByCategory: true })
}, [selectKey])
const fetchLinkAttributeData = (params: any) => {
console.log(params, 'params')
return new Promise((resolve, reject) => {
PublicApi.getProductPlatformGetCategoryAttributeList({...params, categoryId: selectKey, name: params.name || ''}).then(res=>{
PublicApi.getProductPlatformGetCategoryAttributeList({...params, categoryId: selectKey, name: params.name || '', isByCategory: true}).then(res=>{
resolve(res.data)
setLinkTableRowData(res.data.data)
})
})
}
// 获取所有属性列表
// 获取所有属性列表 modal
const fetchAttributeData = (params: any) => {
return new Promise((resolve, reject) => {
PublicApi.getProductPlatformGetAttributeList({ ...params, name: params.name || '' }).then(res=>{
PublicApi.getProductPlatformGetCategoryAttributeList({...params, categoryId: selectKey, name: params.name || '', isByCategory: false}).then(res=>{
resolve(res.data)
})
// PublicApi.getProductPlatformGetAttributeList({ ...params, name: params.name || '' }).then(res=>{
// resolve(res.data)
// })
})
}
......@@ -84,43 +89,37 @@ const CategoryAttributes: React.FC<{}> = () => {
const handleSelectOk = () => {
setRoleVisible(false)
// if (selectTableRow.length) {
PublicApi.postProductPlatformSaveCategoryAttribute({ categoryId: selectKey, attributeIds: selectedTableRowKeys }).then(res=>{
if(res.code === 1000)
setTimeout(() => ref.current.reload(), 500)
})
// }
PublicApi.postProductPlatformSaveCategoryAttribute({ categoryId: selectKey, attributeIds: attributeRowCtl.selectedRowKeys }).then(res=>{
if(res.code === 1000)
setTimeout(() => ref.current.reload(), 500)
})
}
const handleSelectCancel = () => {
setRoleVisible(false)
setSelectedTableRowKeys([])
attributeRowCtl.setSelectedRowKeys([])
}
const columns: ColumnType<any>[] = [
{
title: 'ID',
dataIndex: 'id',
align: 'center',
key: 'id',
},
{
title: '属性名称',
dataIndex: 'name',
align: 'center',
key: 'name',
render: (text: any, record: any) => <span className="commonPickColor" onClick={() => handleSee(record)}>{text}&nbsp;<EyeOutlined /></span>
},
{
title: '属性组名称',
dataIndex: 'groupName',
align: 'center',
key: 'groupName',
},
{
title: '展示方式',
dataIndex: 'type',
align: 'center',
key: 'type',
render: (text: any, record: any) => {
let _txt: string = ''
......@@ -137,13 +136,11 @@ const CategoryAttributes: React.FC<{}> = () => {
{
title: '是否必填',
dataIndex: 'isEmpty',
align: 'center',
key: 'isEmpty',
render: (text: any, record: any) => (<>{text ? '是' : '否'}</>)
},
{
title: '状态',
align: 'center',
dataIndex: 'isEnable',
key: 'isEnable',
render: (text: any, record: any) => text ? '有效' : '无效',
......@@ -151,7 +148,6 @@ const CategoryAttributes: React.FC<{}> = () => {
{
title: '操作',
dataIndex: 'option',
align: 'center',
render: (text: any, record: any) => {
return (
<>
......@@ -166,25 +162,21 @@ const CategoryAttributes: React.FC<{}> = () => {
{
title: 'ID',
dataIndex: 'id',
align: 'center',
key: 'id',
},
{
title: '属性名称',
dataIndex: 'name',
align: 'center',
key: 'name',
},
{
title: '属性组名称',
dataIndex: 'groupName',
align: 'center',
key: 'groupName',
},
{
title: '展示方式',
dataIndex: 'type',
align: 'center',
key: 'type',
render: (text: any, record: any) => {
let _txt: string = ''
......@@ -201,7 +193,6 @@ const CategoryAttributes: React.FC<{}> = () => {
{
title: '是否必填',
dataIndex: 'isEmpty',
align: 'center',
key: 'isEmpty',
render: (text: any, record: any) => (<>{text ? '是' : '否'}</>)
}
......@@ -240,8 +231,7 @@ const CategoryAttributes: React.FC<{}> = () => {
linkTableRowData.forEach((item, index) => {
linkArray.push(item.id)
})
console.log(linkArray)
setSelectedTableRowKeys(linkArray)
attributeRowCtl.setSelectedRowKeys([])
}
......@@ -291,7 +281,7 @@ const CategoryAttributes: React.FC<{}> = () => {
name: {
type: 'string',
'x-component-props': {
placeHolder: '属性名称'
placeholder: '属性名称'
},
'x-component': 'Search'
}
......@@ -321,11 +311,12 @@ const CategoryAttributes: React.FC<{}> = () => {
onCancel={handleSelectCancel}
okText="确认"
cancelText="取消"
width={704}
>
<StandardTable
columns={columnsLink}
currentRef={refLink}
rowSelection={rowSelection}
rowSelection={attributeRowSelection}
fetchTableData={(params: any) => fetchAttributeData(params)}
tableProps={{
rowKey: 'id'
......@@ -338,7 +329,7 @@ const CategoryAttributes: React.FC<{}> = () => {
name: {
type: 'string',
'x-component-props': {
placeHolder: '属性名称'
placeholder: '属性名称'
},
'x-component': 'Search'
}
......
......@@ -74,6 +74,7 @@ const ClassProperty: React.FC<{}> = () => {
setNodeRecord(undefined)
// 保存后要将是否填写过表单设为false
setIsEditForm(false)
flag = false
})
}
......@@ -125,8 +126,6 @@ const ClassProperty: React.FC<{}> = () => {
setIsEditForm(true)
flag = false
}
else
flag = true
})
}}
schema={classSchema}
......
......@@ -16,13 +16,14 @@ import { ColumnType } from 'antd/lib/table/interface';
import { PublicApi } from '@/services/api';
import { createFormActions } from '@formily/antd';
import { useTreeTabs } from '@/hooks/useTreeTabs';
import TabTree from '@/components/TabTree';
import TabTree, { createTreeActions } from '@/components/TabTree';
import { GetProductCustomerGetCustomerAttributeResponse } from '@/services';
const formActions = createFormActions()
const treeActions = createTreeActions()
const fetchAttributeTreeData = async (params?) => {
const res = await PublicApi.getProductPlatformGetAttributeTree()
const res = await PublicApi.getProductPlatformGetAttributeTree({filterInput: true})
return res
}
......@@ -43,6 +44,7 @@ const PropertyValue: React.FC<{}> = () => {
setTreeMaps,
resetMenu
} = useTreeTabs({
treeActions,
fetchMenuData: fetchAttributeTreeData,
})
......@@ -177,6 +179,7 @@ const PropertyValue: React.FC<{}> = () => {
? <TabTree
fetchData = {params => fetchAttributeTreeData(params)}
treeData={treeData}
actions={treeActions}
handleSelect={(key, node) => onHandleSelect(key, node)}
customKey="id"
/>
......
......@@ -96,7 +96,14 @@ const Products: React.FC<{}> = () => {
title: '价格',
dataIndex: 'min',
key: 'min',
render: (text:any, reocrd:any)=>(<>{reocrd.min} ~ ¥{reocrd.max}</>)
render: (text:any, reocrd:any) => {
if(reocrd.priceType === 1)
return <>{reocrd.min} ~ ¥{reocrd.max}</>
if(reocrd.priceType === 3)
return <>{reocrd.min} ~ {reocrd.max}</>
if(reocrd.priceType === 2)
return null
}
},
{
title: '审核时间',
......
......@@ -402,7 +402,7 @@ const viewProducts: React.FC<{}> = () => {
<Col span={20}>
<p>
{
productDetail?.commodityAreaList.map(_item => <p>{_item.provinceName+'/'+(_item.cityName||'')}</p>)
productDetail?.commodityAreaList.length>0 ? productDetail?.commodityAreaList.map(_item => <p>{_item.provinceName+'/'+(_item.cityName||'')}</p>) : '全国'
}
</p>
</Col>
......
......@@ -149,11 +149,18 @@
height:240px;
margin-left: 16px;
border:1px solid rgba(235,236,240,1);
video {
width: 100%;
height: 100%;
}
}
p{
padding: 16px;
padding: 0 16px;
}
}
.description-word-box{
flex-direction: column;
}
.product-img-box{
margin: 24px;
padding: 12px 0;
......
......@@ -110,7 +110,14 @@ const Products: React.FC<{}> = () => {
title: '价格',
dataIndex: 'min',
key: 'min',
render: (text:any, reocrd:any)=>(<>{reocrd.min} ~ ¥{reocrd.max}</>)
render: (text:any, reocrd:any) => {
if(reocrd.priceType === 1)
return <>{reocrd.min} ~ ¥{reocrd.max}</>
if(reocrd.priceType === 3)
return <>{reocrd.min} ~ {reocrd.max}</>
if(reocrd.priceType === 2)
return null
}
},
{
title: '审核时间',
......@@ -277,7 +284,7 @@ const Products: React.FC<{}> = () => {
</Col>
<Col span={4}>
<Select value={filterParams.status} onChange={(v)=>setFilterParams({...filterParams, status: +v})} style={{width:'100%'}} placeholder="商品状态">
<Option value={1}>待提交审核</Option>
{/* <Option value={1}>待提交审核</Option> */}
<Option value={2}>待审核</Option>
<Option value={3}>审核不通过</Option>
<Option value={4}>审核通过</Option>
......
......@@ -2,19 +2,14 @@ import React, { useState, useRef, ReactNode, useEffect } from 'react'
import { history } from 'umi'
import { Button, Steps, Card, Space, Radio, Row, Col, Descriptions, Table, Tabs, Tag, Divider } from 'antd'
import { PageHeaderWrapper } from '@ant-design/pro-layout'
import {
QuestionCircleOutlined,
FormOutlined,
UserOutlined
} from '@ant-design/icons'
import { ColumnType } from 'antd/lib/table/interface'
import cx from 'classnames'
import ReutrnEle from '@/components/ReturnEle'
import styles from "./index.less"
import { PublicApi } from '@/services/api'
import {
GetProductCommodityGetCommodityResponse,
GetProductCommodityGetCommodityCheckRecordResponse,
GetProductCommodityGetShopResponse
} from '@/services'
import moment from 'moment'
......@@ -369,7 +364,7 @@ const viewProducts: React.FC<{}> = () => {
<Col span={20}>
<p>
{
productDetail?.commodityAreaList.map(_item => <p>{_item.provinceName+'/'+(_item.cityName||'')}</p>)
productDetail?.commodityAreaList.length>0 ? productDetail?.commodityAreaList.map(_item => <p>{_item.provinceName+'/'+(_item.cityName||'')}</p>) : '全国'
}
</p>
</Col>
......@@ -592,10 +587,14 @@ const viewProducts: React.FC<{}> = () => {
</Space>
<Space direction="vertical" style={{width:'100%'}}>
<Card headStyle={{borderBottom:'none'}} title="商品描述">
{/* 预留 文字区块 */}
{/* <div className={styles.descriptionBox}>
<p>商品描述商品描述商品描述商品描述商品描述商品描述商品描述商品描述商品描述商品描述商品描述商品描述商品描述商品描述商品描述商品描述商品描述</p>
</div> */}
{/* 文字区块 */}
<div className={cx(styles.descriptionBox, styles.descriptionWordBox)}>
{
productDetail?.commodityRemark?.word?.length>0 ? productDetail?.commodityRemark?.word.map((_item, _index) =>
_item && <p>{_item}</p>
) : <p className={styles.descriptNull}>暂无文字数据</p>
}
</div>
{/* 视频区块 */}
<div className={styles.descriptionBox}>
{
......@@ -603,15 +602,15 @@ const viewProducts: React.FC<{}> = () => {
<video src={_item} controls={true}>
您的浏览器不支持视频标签,请及时升级。
</video>
</div>) : <p>暂无数据</p>
</div>) : <p className={styles.descriptNull}>暂无视频数据</p>
}
</div>
{/* 图片区块 */}
<div className={styles.descriptionBox}>
{
productDetail?.commodityRemark?.image?.length>0 ? productDetail?.commodityRemark?.image.map((_item, _index)=> <div key={_index} className={styles.imgItem}>
productDetail?.commodityRemark?.image?.length>0 ? productDetail?.commodityRemark?.image.map((_item, _index)=> _item && <div key={_index} className={styles.imgItem}>
<img src={_item} />
</div>) : <p>暂无数据</p>
</div>) : <p className={styles.descriptNull}>暂无图片数据</p>
}
</div>
</Card>
......
export const menuData = [
{
"path": "/shop",
"name": "首页",
"key": "shopHome",
},
{
"path": "/commodity",
"name": "商品商城",
"key": "shopCommodity",
},
{
"path": "/purchaseOnline",
"name": "在线求购",
"key": "purchaseOnline",
},
{
"path": "/pointsMall",
"name": "积分商城",
"key": "shopPointsMall",
},
{
"path": "/shops",
"name": "店铺",
"key": "shops",
},
{
"path": "/shop/infomation",
"name": "资讯",
"key": "shopInfomation",
},
]
\ No newline at end of file
......@@ -6,6 +6,8 @@ import SettingPanel from '../settingsPanel'
import config from '../configs'
import { topBarConfig, topAdvertConfig, headerConfig, mainNavConfig, bannerAdvertConfig, interactAdvertConfig, mallLayoutConfig, FindMoreConfig, InformationConfig, FooterConfig } from './defaultData'
import Loading from './loading'
import { LAYOUT_TYPE } from '@/constants'
import { menuData } from './defaultMenu'
import { PublicApi } from '@/services/api'
import styles from './index.less'
......@@ -114,6 +116,11 @@ const MallEdit: React.FC<MallEditPropsType> = (props) => {
}
const getComponentsConfig = async () => {
// 导航栏
mainNavConfig[mainNavConfig.key].props.menuData = menuData
mainNavConfig[mainNavConfig.key].props.type = LAYOUT_TYPE.mall
mainNavConfig[mainNavConfig.key].props.categoryList = []
// 一号位广告
bannerAdvertConfig[bannerAdvertConfig.key].props.advertList = await findFirstAdvertsByType()
// 二号位广告
......
......@@ -150,10 +150,10 @@ const TemplateDetail: React.FC<TemplateDetailPropsType> = (props) => {
<LayoutOutlined />
<label>装修</label>
</div>
<div className={cx(styles.btn, detailInfo?.use === 1 ? styles.use : '')} onClick={() => handleUseTemplate()}>
{/* <div className={cx(styles.btn, detailInfo?.use === 1 ? styles.use : '')} onClick={() => handleUseTemplate()}>
<PlayCircleOutlined />
<label>{detailInfo?.use === 1 ? '启用中' : '启用'}</label>
</div>
</div> */}
</Fragment>
)
}
......
......@@ -30,22 +30,7 @@ const CheckBrand: React.FC<{}> = () => {
const { id } = history.location.query
if(id){
setQueryId(id)
PublicApi.getProductBrandGetPlatformBrand({id: id}).then(res => {
console.log(res.data, 'data')
if(res.code===1000){
setBrandInfo(res.data)
if(res.data.status===1)
setFixStep(0)
else if(res.data.status===2)
setFixStep(1)
else
setFixStep(2)
}
})
PublicApi.getProductBrandGetBrandCheckRecord({brandId: id}).then(res=> {
if(res.code===1000)
setRecordData(res.data)
})
loadPageData(id)
}
}, [])
......@@ -106,6 +91,24 @@ const CheckBrand: React.FC<{}> = () => {
},
];
const loadPageData = (id: string) => {
PublicApi.getProductBrandGetPlatformBrand({id: id}).then(res => {
if(res.code===1000){
setBrandInfo(res.data)
if(res.data.status===1)
setFixStep(0)
else if(res.data.status===2)
setFixStep(1)
else
setFixStep(2)
}
})
PublicApi.getProductBrandGetBrandCheckRecord({brandId: id}).then(res=> {
if(res.code===1000)
setRecordData(res.data)
})
}
const fixStatus = (state: number) => {
if(state === 1)
return <><span className="commonStatusInvalid"></span>待提交审核</>
......@@ -147,17 +150,17 @@ const CheckBrand: React.FC<{}> = () => {
</Descriptions>
</>
const handleApplyCheck = (status: number) => {
const handleApplyCheck = () => {
setVisibleModal(true)
}
const handleOK = () => {
checkForm.validateFields().then(values => {
console.log(values, 'value')
PublicApi.postProductBrandCheckBrand({ id: brandInfo?.id, ...values }).then(res=>{
if(res.code=1000){
handleCancel()
setDisableCheck(true)
loadPageData(brandInfo.id)
}
})
})
......@@ -249,7 +252,7 @@ const CheckBrand: React.FC<{}> = () => {
}
]}
>
<TextArea rows={3} placeholder="请填写原因" />
<TextArea rows={3} maxLength={60} placeholder="请填写原因" />
</Form.Item>
</Form>
</Modal>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment