From c9d133313511853300b36e1060b90d011df91fef Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Thu, 25 Jul 2024 09:50:14 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E5=95=86=E5=9F=8E=E6=A8=A1=E7=89=88?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=9A=E4=BB=B6=E6=95=B0=E9=87=8F=E8=B4=AD?= =?UTF-8?q?=E4=B9=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/column.tsx | 16 ++++- .../open/mallTemplate/index.module.less | 68 ++++++++++--------- .../open/mallTemplate/pages/shoppingCar.tsx | 14 +++- .../open/mallTemplate/widget/item.tsx | 67 +++++++++++------- .../open/mallTemplate/widget/product.tsx | 35 ++++++++-- src/ts/base/schema.ts | 4 +- 6 files changed, 138 insertions(+), 66 deletions(-) diff --git a/src/config/column.tsx b/src/config/column.tsx index 6d57f3e53..1cc07413e 100644 --- a/src/config/column.tsx +++ b/src/config/column.tsx @@ -304,9 +304,23 @@ export const PhysicalProperties = (props: schema.XProperty[]) => { id: 'count', name: '实体商品数量', code: 'count', - valueType: '描述型', + valueType: '数值型', remark: '实体商品数量', }, + { + id: 'isMultiple', + name: '是否能购买多件', + code: 'isMultiple', + valueType: '描述型', + remark: '是否能购买多件', + }, + { + id: 'carCount', + name: '下单数量', + code: 'carCount', + valueType: '数值型', + remark: '下单数量', + }, ...props, ] as schema.XProperty[]; }; diff --git a/src/executor/open/mallTemplate/index.module.less b/src/executor/open/mallTemplate/index.module.less index 2d970461f..44cacaa7e 100644 --- a/src/executor/open/mallTemplate/index.module.less +++ b/src/executor/open/mallTemplate/index.module.less @@ -70,7 +70,7 @@ } .introduce { font-size: 12px; - color: #424A57; + color: #424a57; font-weight: 500; } } @@ -176,47 +176,51 @@ justify-content: space-between; gap: 10px; > * { - flex: 1 + flex: 1; } } } } - .carItem { display: flex; - width: 100%; - margin-top: 12px; - .image { - display: flex; - justify-content: center; - width: 80px; - height: 80px; - line-height: 24px; - color: #15181d; - font-size: 14px; - .ant-skeleton-image { - width: 100%; - } - } - .content { - margin-left: 10px; + justify-content: space-between; + align-items: center; + .carItemInfo { display: flex; - flex-direction: column; - .title { + width: 100%; + margin-top: 12px; + .image { display: flex; - justify-content: space-between; - font-weight: bold; + justify-content: center; + width: 80px; + height: 80px; + line-height: 24px; + color: #15181d; + font-size: 14px; + .ant-skeleton-image { + width: 100%; + } } - .tag { + .content { margin-left: 10px; - } - .remark { - margin-top: 4px; - font-size: 12px; - color: #666666; - } - .amount { - font-weight: bold; + display: flex; + flex-direction: column; + .title { + display: flex; + justify-content: space-between; + font-weight: bold; + } + .tag { + margin-left: 10px; + } + .remark { + margin-top: 4px; + font-size: 12px; + color: #666666; + } + .amount { + font-weight: bold; + } } } } diff --git a/src/executor/open/mallTemplate/pages/shoppingCar.tsx b/src/executor/open/mallTemplate/pages/shoppingCar.tsx index 301dc484a..d1c1acea6 100644 --- a/src/executor/open/mallTemplate/pages/shoppingCar.tsx +++ b/src/executor/open/mallTemplate/pages/shoppingCar.tsx @@ -102,7 +102,10 @@ export const RightCar: React.FC = ({ page }) => { p + (n.price ?? 0), 0)} + value={selectedRows.reduce( + (p, n) => p + ((n.price || 0) * (n.carCount || 1) ?? 0), + 0, + )} prefix={'合计:'} suffix="¥" /> @@ -130,7 +133,14 @@ export const RightCar: React.FC = ({ page }) => { setCenter(<>)} + finished={async (success) => { + if (success) { + if (await page.shoppingCar.batchRemove(selectedRows)) { + setSelectedRows([]); + } + } + setCenter(<>); + }} />, ); } diff --git a/src/executor/open/mallTemplate/widget/item.tsx b/src/executor/open/mallTemplate/widget/item.tsx index e6b436eb6..5fd076843 100644 --- a/src/executor/open/mallTemplate/widget/item.tsx +++ b/src/executor/open/mallTemplate/widget/item.tsx @@ -1,6 +1,6 @@ import { model, schema } from '@/ts/base'; import { IMallTemplate } from '@/ts/core/thing/standard/page/mallTemplate'; -import { Carousel, Image, Skeleton, Tag } from 'antd'; +import { Carousel, Image, Skeleton, Tag, InputNumber } from 'antd'; import React from 'react'; import cls from './../index.module.less'; @@ -10,31 +10,52 @@ interface IProps { images: (product: schema.XProduct) => model.FileItemShare[]; } -export const ItemProduct: React.FC = ({ product, images }) => { +export const ItemProduct: React.FC = ({ current, product, images }) => { + const onChange = (e: any) => { + const value = +e.target.value > +product.count ? product.count : e.target.value; + current.shoppingCar.create({ + ...product, + carCount: +value, + }); + }; return (
- - {images(product).map((item, index) => { - return ( - } - /> - ); - })} - -
-
-
{product.title ?? '[未设置名称]'}
- - {product.typeName ?? '商品'} - +
+ + {images(product).map((item, index) => { + return ( + } + /> + ); + })} + +
+
+
{product.title ?? '[未设置名称]'}
+ + {product.typeName ?? '商品'} + +
+
{product.remark}
+
{product.price ?? 0}¥
-
{product.remark}
-
{product.price ?? 0}¥
+
+
{ + e.stopPropagation(); + }}> +
); diff --git a/src/executor/open/mallTemplate/widget/product.tsx b/src/executor/open/mallTemplate/widget/product.tsx index e2378707f..3f365ee18 100644 --- a/src/executor/open/mallTemplate/widget/product.tsx +++ b/src/executor/open/mallTemplate/widget/product.tsx @@ -2,7 +2,7 @@ import EntityIcon from '@/components/Common/GlobalComps/entityIcon'; import { model, schema } from '@/ts/base'; import { IMallTemplate } from '@/ts/core/thing/standard/page/mallTemplate'; import { ShoppingCartOutlined } from '@ant-design/icons'; -import { Carousel, Image, Skeleton, Space } from 'antd'; +import { Carousel, Image, Skeleton, Space, message } from 'antd'; import React, { useEffect, useState } from 'react'; import cls from './../index.module.less'; import down from '/public/img/mallTemplate/down.svg'; @@ -30,11 +30,13 @@ const images = (product: schema.XProduct): model.FileItemShare[] => { export const Product: React.FC = ({ current, product }) => { const [center, setCenter] = useState(<>); const [staging, setStaging] = useState( - current.shoppingCar.products.some((a) => a.id == product.id), + current.shoppingCar.products.some((a) => !a.isMultiple && a.id == product.id), ); useEffect(() => { const id = current.shoppingCar.subscribe(() => { - setStaging(current.shoppingCar.products.some((a) => a.id == product.id)); + setStaging( + current.shoppingCar.products.some((a) => !a.isMultiple && a.id == product.id), + ); }); return () => current.shoppingCar.unsubscribe(id); }, []); @@ -169,7 +171,9 @@ export const Product: React.FC = ({ current, product }) => { {current.metadata.mode !== 'sharing' && (
¥{product.price ?? 0}
-
{0}人已买
+
+ {0}人已买{product.isMultiple && ` 数量:${product.count}件`} +
)}
@@ -182,10 +186,27 @@ export const Product: React.FC = ({ current, product }) => {
{ - if (staging) { - current.shoppingCar.remove(product); + if (product.isMultiple) { + let num = + current.shoppingCar.products.find((i) => i.id === product.id) + ?.carCount || 0; + num++; + if (!num) return; + if (num > (product.count || 0)) { + message.error('库存不足'); + return; + } + current.shoppingCar.create({ + ...product, + carCount: num, + }); + message.success('已加入购物车'); } else { - current.shoppingCar.create(product); + if (staging) { + current.shoppingCar.remove(product); + } else { + current.shoppingCar.create(product); + } } }} style={{ diff --git a/src/ts/base/schema.ts b/src/ts/base/schema.ts index 3cab42b86..f78717592 100644 --- a/src/ts/base/schema.ts +++ b/src/ts/base/schema.ts @@ -897,7 +897,7 @@ export interface XPageTemplate extends XStandard { } // 商城模板 -export interface XMallTemplate extends XPageTemplate {} +export interface XMallTemplate extends XPageTemplate { } // 绑定信息 export type Binding = { @@ -1303,6 +1303,8 @@ export type XProduct = { images?: string; // 品牌 brand?: string; + // 购买数量 + carCount?: number } & XThing; // 订单 -- Gitee From 4077f05f44dde9904633d634ef4d544215d7b8d9 Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Thu, 25 Jul 2024 16:55:29 +0800 Subject: [PATCH 02/13] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E5=99=A8=E5=85=AC=E5=BC=8F=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/ExecutorShowComp/index.tsx | 20 ++++++-- .../open/mallTemplate/widget/item.tsx | 26 +++++----- src/executor/tools/task/approval/index.tsx | 47 +++++++++++++++++++ 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/components/Common/ExecutorShowComp/index.tsx b/src/components/Common/ExecutorShowComp/index.tsx index d80256f0f..77e78d81e 100644 --- a/src/components/Common/ExecutorShowComp/index.tsx +++ b/src/components/Common/ExecutorShowComp/index.tsx @@ -462,7 +462,7 @@ const FormChangesTable: React.FC = (props) => { interface FieldChangeTableProps { work: IWork; formChange: model.FormChange; - finished: (e:model.FieldChange[]) => void; + finished: (e: model.FieldChange[]) => void; } export const FieldChangeTable: React.FC = (props) => { @@ -475,8 +475,8 @@ export const FieldChangeTable: React.FC = (props) => { title={'配置变更字段'} width={'80vw'} destroyOnClose - onCancel={()=>props.finished(fieldChanges)} - onOk={()=>props.finished(fieldChanges)}> + onCancel={() => props.finished(fieldChanges)} + onOk={() => props.finished(fieldChanges)}> search={false} options={false} @@ -758,6 +758,16 @@ export const ExecutorForm: React.FC = (props) => { return <>{formRef.current?.getFieldValue('beforeName')}; }, }, + { + title: '使用规则计算变动值', + dataIndex: 'switch', + valueType: 'switch', + width: 'md', + colProps: { + xs: 12, + md: 20, + }, + }, { title: '变动后值', dataIndex: 'after', @@ -767,7 +777,11 @@ export const ExecutorForm: React.FC = (props) => { }, renderFormItem: (_) => { const id = formRef.current?.getFieldValue('id'); + const isRule = formRef.current?.getFieldValue('switch'); const field = fields.find((item) => item.id == id); + if (isRule && field) { + field.valueType = '描述型'; + } if (field) { const clone = cloneField(field); return ( diff --git a/src/executor/open/mallTemplate/widget/item.tsx b/src/executor/open/mallTemplate/widget/item.tsx index 5fd076843..48f8f0d52 100644 --- a/src/executor/open/mallTemplate/widget/item.tsx +++ b/src/executor/open/mallTemplate/widget/item.tsx @@ -45,18 +45,20 @@ export const ItemProduct: React.FC = ({ current, product, images }) => {
{product.price ?? 0}¥
-
{ - e.stopPropagation(); - }}> - -
+ {product.isMultiple && ( +
{ + e.stopPropagation(); + }}> + +
+ )}
); }; diff --git a/src/executor/tools/task/approval/index.tsx b/src/executor/tools/task/approval/index.tsx index 6780a28a2..7bcfe41a2 100644 --- a/src/executor/tools/task/approval/index.tsx +++ b/src/executor/tools/task/approval/index.tsx @@ -8,6 +8,7 @@ import { ReceptionChange } from '@/ts/core/work/executor/reception'; import { AddNodeType, convertToFields, getNodeByNodeId } from '@/utils/work'; import ProTable from '@ant-design/pro-table'; import { Button, Card, Input, Modal, Space, message } from 'antd'; +import { isNumber } from 'lodash'; import React, { ReactNode, useState } from 'react'; export interface TaskDetailType { @@ -112,8 +113,54 @@ const TaskApproval: React.FC = ({ task, finished, fromData }) => let content: ReactNode = null; let title = '字段变更确认'; + const calcValue = () =>{ + const instance = props.executor.task.instanceData; + if (instance) { + for (const change of props.executor.metadata.changes) { + for (const form of instance.node.forms) { + const editData: model.FormEditData[] = instance.data[change.id]; + if (change.id == form.id) { + if (editData && editData.length > 0) { + editData[editData.length - 1].after.forEach((item) => { + for (const fieldChange of change.fieldChanges) { + let afterValue = fieldChange.after + if (fieldChange.switch && typeof(afterValue)==='string') { + afterValue = afterValue && afterValue.replace(/\s/g, '') + let current = 0 + const afterValueArr: (number | string)[] = [] + const regex = /[-+*/]/; + afterValue.split('').forEach((i: string, index: number) => { + if (regex.test(i)) { + const value = item[afterValue.slice(current, index)] + afterValueArr.push(value) + current = index + 1 + afterValueArr.push(i) + } else if (index === afterValue.length - 1) { + const value = item[afterValue.slice(current, afterValue.length)] + afterValueArr.push(value) + } + }) + afterValue = eval(afterValueArr.join('')) + if (!isNumber(afterValue)) { + throw new Error(`公式${fieldChange.after}填写错误`) + } + if (!(afterValue >= 0)) { + throw new Error(`计算为负数`) + } + fieldChange.after = afterValue + fieldChange.afterName = afterValue + } + } + }) + } + } + } + } + } + } if (props.executor.metadata.funcName == '字段变更') { + calcValue() content = ( 确认后,您的数据将自动产生变更操作,变更字段如下 -- Gitee From 4cf89a15f91f23ef0ec9606fc0a2bba9f4de17e3 Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Thu, 25 Jul 2024 17:02:04 +0800 Subject: [PATCH 03/13] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=95=86=E5=9F=8E?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=88=86=E7=B1=BB=E7=AD=9B=E9=80=89=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/executor/open/mallTemplate/pages/index.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/executor/open/mallTemplate/pages/index.tsx b/src/executor/open/mallTemplate/pages/index.tsx index 086698153..a77d4f369 100644 --- a/src/executor/open/mallTemplate/pages/index.tsx +++ b/src/executor/open/mallTemplate/pages/index.tsx @@ -225,15 +225,20 @@ const Filter: React.FC = ({ current, form }) => { selectByClick={true} onSelectionChanged={(e) => { const match: any = {}; - const userData: string[] = []; for (const { itemData } of e.component.getSelectedNodes()) { if (itemData?.value?.startsWith('T')) { match[itemData.value] = { _exists_: true }; } else if (itemData?.value?.startsWith('S')) { - userData.push(itemData.value); + if (match['T' + itemData.propertyId]?._in_) { + match['T' + itemData.propertyId]._in_.push(itemData.value); + } else { + match['T' + itemData.propertyId] = { + _in_: [itemData.value], + }; + } } } - current.command.emitter('filter', 'species', { match, userData }); + current.command.emitter('filter', 'species', { match }); }} />
@@ -241,7 +246,7 @@ const Filter: React.FC = ({ current, form }) => { }; interface FilterProps { - species: { userData: string[]; match: any }; + species: { match: any }; } interface ProviderProps extends DataProps { @@ -264,12 +269,11 @@ const Provider: React.FC = ({ current, form, renderBody }) => { const [size, setSize] = useState(24); const [total, setTotal] = useState(0); const filter = useRef([]); - const match = useRef({ species: { userData: [], match: {} } }); + const match = useRef({ species: { match: {} } }); const loadData = async (page: number, size: number) => { setLoading(true); const result = await form.loadThing({ requireTotalCount: true, - userData: match.current.species.userData, skip: (page - 1) * size, take: size, filter: form.parseFilter(filter.current), -- Gitee From 1b31fdf953fb84cc431821fe75c3e92993933d89 Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Thu, 25 Jul 2024 17:06:02 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=B4=AD=E7=89=A9?= =?UTF-8?q?=E8=BD=A6=E7=9A=84=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/executor/open/mallTemplate/index.module.less | 1 + 1 file changed, 1 insertion(+) diff --git a/src/executor/open/mallTemplate/index.module.less b/src/executor/open/mallTemplate/index.module.less index 44cacaa7e..8c2329054 100644 --- a/src/executor/open/mallTemplate/index.module.less +++ b/src/executor/open/mallTemplate/index.module.less @@ -185,6 +185,7 @@ display: flex; justify-content: space-between; align-items: center; + margin-left: 16px; .carItemInfo { display: flex; width: 100%; -- Gitee From d3839a8ad7ca0c0f39133f30458631e4c8993e90 Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Fri, 26 Jul 2024 11:00:23 +0800 Subject: [PATCH 05/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=95=86=E5=9F=8E?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E7=9A=84=E5=85=B1=E4=BA=AB=E4=BA=A4=E6=98=93?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=20=E4=BF=AE=E5=A4=8D=E6=95=B0=E9=87=8F?= =?UTF-8?q?=E5=8A=A0=E8=B4=AD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/column.tsx | 4 +- .../components/dataDetails/index.tsx | 17 +-- .../open/mallTemplate/pages/shoppingCar.tsx | 14 +- .../open/mallTemplate/widget/product.tsx | 125 +++++++----------- .../operate/entityForm/templateForm.tsx | 47 +------ 5 files changed, 70 insertions(+), 137 deletions(-) diff --git a/src/config/column.tsx b/src/config/column.tsx index 1cc07413e..7a852dbd6 100644 --- a/src/config/column.tsx +++ b/src/config/column.tsx @@ -315,9 +315,9 @@ export const PhysicalProperties = (props: schema.XProperty[]) => { remark: '是否能购买多件', }, { - id: 'carCount', + id: 'orderCount', name: '下单数量', - code: 'carCount', + code: 'orderCount', valueType: '数值型', remark: '下单数量', }, diff --git a/src/executor/open/mallTemplate/components/dataDetails/index.tsx b/src/executor/open/mallTemplate/components/dataDetails/index.tsx index 56117cddd..0059cffbb 100644 --- a/src/executor/open/mallTemplate/components/dataDetails/index.tsx +++ b/src/executor/open/mallTemplate/components/dataDetails/index.tsx @@ -8,9 +8,10 @@ interface IDataDetails { data: schema.XProduct; current: IMallTemplate; onCancel: () => void; + onAddCar: () => void; } -const DataDetails = ({ current, data, onCancel }: IDataDetails) => { +const DataDetails = ({ current, data, onCancel, onAddCar }: IDataDetails) => { const [staging, setStaging] = useState( current.shoppingCar.products.some((a) => a.id == data.id), ); @@ -203,7 +204,7 @@ const DataDetails = ({ current, data, onCancel }: IDataDetails) => {
{data.title || '[未设置名称]'}
{data.remark}
- {current.metadata.mode !== 'sharing' && ( + {data.mode !== 'sharing' && (
¥{data.price || 0}
{0}人已买
@@ -212,21 +213,13 @@ const DataDetails = ({ current, data, onCancel }: IDataDetails) => {
- {current.metadata.mode === 'sharing' ? ( + {data.mode === 'sharing' ? ( 立即申领 ) : ( {}}>立即购买 )}
-
{ - if (staging) { - current.shoppingCar.remove(data); - } else { - current.shoppingCar.create(data); - } - }}> +
加入购物车
diff --git a/src/executor/open/mallTemplate/pages/shoppingCar.tsx b/src/executor/open/mallTemplate/pages/shoppingCar.tsx index d1c1acea6..afd1de04b 100644 --- a/src/executor/open/mallTemplate/pages/shoppingCar.tsx +++ b/src/executor/open/mallTemplate/pages/shoppingCar.tsx @@ -2,7 +2,7 @@ import EntityIcon from '@/components/Common/GlobalComps/entityIcon'; import { model, schema } from '@/ts/base'; import { List as Link } from '@/ts/base/common/linq'; import { IMallTemplate } from '@/ts/core/thing/standard/page/mallTemplate'; -import { Button, Divider, Skeleton, Space, Statistic } from 'antd'; +import { Button, Divider, Skeleton, Space, Statistic, message } from 'antd'; import { List } from 'devextreme-react'; import React, { useEffect, useMemo, useState } from 'react'; import InfiniteScroll from 'react-infinite-scroll-component'; @@ -126,9 +126,19 @@ export const RightCar: React.FC = ({ page }) => { loading={loading} disabled={!work} onClick={async () => { + if (!selectedRows.length) { + message.error('请先选择商品'); + return + } const node = await work?.loadNode(); if (work && node) { - const instance = await work.applyData(node, selectedRows); + const rows = selectedRows.map((item) => { + return { + ...item, + orderCount: item.carCount, + }; + }); + const instance = await work.applyData(node, rows); setCenter( = ({ current, product }) => { }); return () => current.shoppingCar.unsubscribe(id); }, []); + const addCar = () => { + if (product.isMultiple) { + let num = + current.shoppingCar.products.find((i) => i.id === product.id)?.carCount || 0; + num++; + if (!num) return; + if (num > (product.count || 0)) { + message.error('库存不足'); + return; + } + current.shoppingCar.create({ + ...product, + carCount: num, + }); + message.success('已加入购物车'); + } else { + if (staging) { + current.shoppingCar.remove(product); + } else { + current.shoppingCar.create(product); + } + } + }; const loadBody = () => { switch (product.mode) { case '共享': @@ -52,74 +75,53 @@ export const Product: React.FC = ({ current, product }) => { setCenter(<>)} />, ) }> -
+ {images(product).map((item, index) => { return ( } /> ); })} - {product.title ?? '[未设置名称]'} -
+
-
{product.remark}
- {current.metadata.mode === 'sharing' && ( - <> -
- 供给方: - -
-
上架时间:{product.updateTime}
- - )} +
+ {product.brand && `[${product.brand}]`} + {product.title || '【暂无标题】'} +
+
+ 供给方: + +
+
上架时间:{product.updateTime}
- {current.metadata.mode !== 'sharing' && ( -
- ¥{product.price || 0} - {0}人已买 -
- )}
- - {current.metadata.mode !== 'sharing' ? '立即购买' : '立即申领'} - + 立即申领
-
+
{ - if (staging) { - current.shoppingCar.remove(product); - } else { - current.shoppingCar.create(product); - } - }} style={{ fontSize: 20, color: staging ? 'red' : undefined, }} /> - {current.metadata.mode === 'sharing' && ( - 加入购物车 - )} + 加入购物车
@@ -135,6 +137,7 @@ export const Product: React.FC = ({ current, product }) => { setCenter(<>)} />, ) @@ -168,55 +171,25 @@ export const Product: React.FC = ({ current, product }) => {
- {current.metadata.mode !== 'sharing' && ( -
-
¥{product.price ?? 0}
-
- {0}人已买{product.isMultiple && ` 数量:${product.count}件`} -
+
+
¥{product.price ?? 0}
+
+ {0}人已买{product.isMultiple && ` 数量:${product.count}件`}
- )} +
{}}> - - {current.metadata.mode !== 'sharing' ? '立即购买' : '立即申领'} - + 立即购买
{ - if (product.isMultiple) { - let num = - current.shoppingCar.products.find((i) => i.id === product.id) - ?.carCount || 0; - num++; - if (!num) return; - if (num > (product.count || 0)) { - message.error('库存不足'); - return; - } - current.shoppingCar.create({ - ...product, - carCount: num, - }); - message.success('已加入购物车'); - } else { - if (staging) { - current.shoppingCar.remove(product); - } else { - current.shoppingCar.create(product); - } - } - }} + onClick={addCar} style={{ fontSize: 20, color: staging ? 'red' : undefined, }} /> - {current.metadata.mode === 'sharing' && ( - 加入购物车 - )}
diff --git a/src/executor/operate/entityForm/templateForm.tsx b/src/executor/operate/entityForm/templateForm.tsx index c1009526d..a56c4cad7 100644 --- a/src/executor/operate/entityForm/templateForm.tsx +++ b/src/executor/operate/entityForm/templateForm.tsx @@ -78,8 +78,6 @@ const getMeta = (kind: string) => { const PageTemplateForm: React.FC = ({ formType, current, finished }) => { const [center, setCenter] = useState(<>); - const [isHideMode, setIsHideMode] = useState(true); - const [template, setTemplate] = useState('commonTemplate'); let initialValue: any = { public: false, open: false }; const formRef = useRef(); switch (formType) { @@ -87,11 +85,6 @@ const PageTemplateForm: React.FC = ({ formType, current, finished }) => initialValue = current.metadata; break; } - useEffect(() => { - if (formType === 'updatePageTemplate' && current.metadata.mode) { - setIsHideMode(false); - } - }, []); const columns: ProFormColumnsType[] = [ { title: '图标', @@ -101,9 +94,9 @@ const PageTemplateForm: React.FC = ({ formType, current, finished }) => return ( = ({ formType, current, finished }) => ], }, }, - { - title: '模板模式', - dataIndex: 'mode', - valueType: 'select', - initialValue: 'trading', - hideInForm: isHideMode, - fieldProps: { - options: [ - { - label: '共享', - value: 'sharing', - }, - { - label: '交易', - value: 'trading', - }, - ], - }, - }, { title: '模板', dataIndex: 'kind', @@ -244,23 +218,6 @@ const PageTemplateForm: React.FC = ({ formType, current, finished }) => generateCodeByInitials(values['name']), ); } - if ( - values['template'] === 'dataTemplate' || - values['template'] === 'realTemplate' - ) { - setIsHideMode(false); - } else if (values['template'] === 'commonTemplate') { - setIsHideMode(true); - if (Object.keys(values)[0] === 'template') { - if (values.template === 'dataTemplate') { - setTemplate('dataTemplate'); - } else if (values.template === 'realTemplate') { - setTemplate('realTemplate'); - } else { - setTemplate('commonTemplate'); - } - } - } }} onFinish={async (values) => { switch (formType) { -- Gitee From 80a544224336c3f33ffdfcfb631524c8009d361d Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Fri, 26 Jul 2024 12:05:51 +0800 Subject: [PATCH 06/13] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=A8=E6=88=B7?= =?UTF-8?q?=E5=95=86=E5=9F=8E=E6=A8=A1=E6=9D=BF=E5=B1=95=E7=A4=BA=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/executor/open/mallTemplate/index.module.less | 4 +++- src/executor/open/mallTemplate/pages/index.tsx | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/executor/open/mallTemplate/index.module.less b/src/executor/open/mallTemplate/index.module.less index 8c2329054..56dd5c7f4 100644 --- a/src/executor/open/mallTemplate/index.module.less +++ b/src/executor/open/mallTemplate/index.module.less @@ -121,8 +121,10 @@ } } -.dataSharing { +.physical { padding: 0px 20px; + height: calc(100vh - 46px) !important; + overflow-y: scroll; .content { width: 100%; display: flex; diff --git a/src/executor/open/mallTemplate/pages/index.tsx b/src/executor/open/mallTemplate/pages/index.tsx index a77d4f369..4924d1f57 100644 --- a/src/executor/open/mallTemplate/pages/index.tsx +++ b/src/executor/open/mallTemplate/pages/index.tsx @@ -29,10 +29,12 @@ interface IProps { export const MallTemplate: React.FC = ({ current }) => { return ( - +
@@ -67,7 +69,7 @@ const HotBody: React.FC = ({ current }) => { renderBody={(products) => { return ( - + {products.map((item) => { return ; })} @@ -118,7 +120,7 @@ const ContentBody: React.FC = ({ current }) => { form={form} renderBody={(products, loader) => { return ( - + {products.map((item) => { return ( -- Gitee From 1230bcb1e829ad6559745137d54acef36f484f47 Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Fri, 26 Jul 2024 15:58:22 +0800 Subject: [PATCH 07/13] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=9E=8B=E9=80=89=E6=8B=A9=E6=93=8D=E4=BD=9C=E4=BA=BA=E5=90=8E?= =?UTF-8?q?=E4=B8=8D=E8=83=BD=E4=BF=AE=E6=94=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DataStandard/WorkForm/Viewer/customItem/currentTarget.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/DataStandard/WorkForm/Viewer/customItem/currentTarget.tsx b/src/components/DataStandard/WorkForm/Viewer/customItem/currentTarget.tsx index c56174177..7a4010194 100644 --- a/src/components/DataStandard/WorkForm/Viewer/customItem/currentTarget.tsx +++ b/src/components/DataStandard/WorkForm/Viewer/customItem/currentTarget.tsx @@ -23,11 +23,12 @@ const CurrentTargetItem: React.FC = (props) => { return ( { -- Gitee From 7c3ce354f48e498649e4de3b85492d258d1c2c8d Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Mon, 29 Jul 2024 17:32:44 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=E5=95=86=E5=9F=8E=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E9=A6=96=E9=A1=B5=E8=AF=A6=E6=83=85=E9=A1=B5=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=AB=8B=E5=8D=B3=E8=B4=AD=E4=B9=B0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/dataDetails/index.tsx | 5 +- .../open/mallTemplate/pages/index.tsx | 71 ++++++++++++++++--- .../open/mallTemplate/pages/shoppingCar.tsx | 40 ++--------- .../open/mallTemplate/widget/product.tsx | 11 ++- 4 files changed, 77 insertions(+), 50 deletions(-) diff --git a/src/executor/open/mallTemplate/components/dataDetails/index.tsx b/src/executor/open/mallTemplate/components/dataDetails/index.tsx index 0059cffbb..ba1b8a81e 100644 --- a/src/executor/open/mallTemplate/components/dataDetails/index.tsx +++ b/src/executor/open/mallTemplate/components/dataDetails/index.tsx @@ -9,9 +9,10 @@ interface IDataDetails { current: IMallTemplate; onCancel: () => void; onAddCar: () => void; + onPurchase: (selectedRows: schema.XProduct[]) => void; } -const DataDetails = ({ current, data, onCancel, onAddCar }: IDataDetails) => { +const DataDetails = ({ current, data, onCancel, onAddCar, onPurchase }: IDataDetails) => { const [staging, setStaging] = useState( current.shoppingCar.products.some((a) => a.id == data.id), ); @@ -216,7 +217,7 @@ const DataDetails = ({ current, data, onCancel, onAddCar }: IDataDetails) => { {data.mode === 'sharing' ? ( 立即申领 ) : ( - {}}>立即购买 + 立即购买 )}
diff --git a/src/executor/open/mallTemplate/pages/index.tsx b/src/executor/open/mallTemplate/pages/index.tsx index 4924d1f57..5055e57db 100644 --- a/src/executor/open/mallTemplate/pages/index.tsx +++ b/src/executor/open/mallTemplate/pages/index.tsx @@ -11,6 +11,7 @@ import { Empty, Input, Layout, + message, Pagination, Row, Space, @@ -22,12 +23,44 @@ import React, { ReactNode, useEffect, useRef, useState } from 'react'; import { Product } from '../widget/product'; import cls from './../index.module.less'; import { RightCar } from './shoppingCar'; +import WorkStartDo from '../../work'; interface IProps { current: IMallTemplate; } export const MallTemplate: React.FC = ({ current }) => { + const [center, setCenter] = useState(<>); + const onPurchase = async (selectedRows: schema.XProduct[]) => { + const work = await current.findWork(); + if (!selectedRows.length) { + message.error('请先选择商品'); + return; + } + const node = await work?.loadNode(); + if (work && node) { + const rows = selectedRows.map((item) => { + return { + ...item, + orderCount: item.carCount, + }; + }); + const instance = await work.applyData(node, rows); + setCenter( + { + if (success) { + await current.shoppingCar.batchRemove(selectedRows); + } + setCenter(<>); + }} + />, + ); + } + return; + }; return (
@@ -39,17 +72,19 @@ export const MallTemplate: React.FC = ({ current }) => { bannerkey={current.id} />
- - + + + {center}
); }; interface IHotGroup { current: IMallTemplate; + onPurchase: (selectedRows: schema.XProduct[]) => void; } -const HotBody: React.FC = ({ current }) => { +const HotBody: React.FC = ({ current, onPurchase }) => { const [hot, setHot] = useState(); useEffect(() => { const id = current.subscribe(async () => setHot(await current.loadHot())); @@ -71,7 +106,14 @@ const HotBody: React.FC = ({ current }) => { {products.map((item) => { - return ; + return ( + + ); })} @@ -85,8 +127,11 @@ const HotBody: React.FC = ({ current }) => { interface DataProps extends IProps { form: IForm; } +interface IContentBody extends IProps { + onPurchase: (selectedRows: schema.XProduct[]) => void; +} -const ContentBody: React.FC = ({ current }) => { +const ContentBody: React.FC = ({ current, onPurchase }) => { const [loading, setLoading] = useState(true); const [form, setForm] = useState(); const loadContent = async () => { @@ -114,7 +159,7 @@ const ContentBody: React.FC = ({ current }) => {
- + = ({ current }) => { {products.map((item) => { return ( - + ); })} @@ -154,7 +203,11 @@ const ContentBody: React.FC = ({ current }) => { ); }; -const Group: React.FC = ({ current, form }) => { +interface IGroup extends DataProps { + onPurchase: (selectedRows: schema.XProduct[]) => void; +} + +const Group: React.FC = ({ current, form, onPurchase }) => { const [visible, setVisible] = useState(false); const [length, setLength] = useState(current.shoppingCar.products.length); useEffect(() => { @@ -178,7 +231,7 @@ const Group: React.FC = ({ current, form }) => { size={'large'} onClose={() => setVisible(false)} open={visible}> - + void; } interface IGroup { @@ -20,12 +20,11 @@ interface IGroup { items: schema.XProduct[]; } -export const RightCar: React.FC = ({ page }) => { +export const RightCar: React.FC = ({ page, onPurchase }) => { const [products, setProducts] = useState([]); const [loading, setLoading] = useState(false); const [selectedRows, setSelectedRows] = useState([]); const [work, setWork] = useState(); - const [center, setCenter] = useState(<>); const groups: IGroup[] = useMemo(() => { const result = new Link(products).GroupBy((item) => item.belongId); return Object.keys(result).map((item) => { @@ -125,37 +124,7 @@ export const RightCar: React.FC = ({ page }) => { type="primary" loading={loading} disabled={!work} - onClick={async () => { - if (!selectedRows.length) { - message.error('请先选择商品'); - return - } - const node = await work?.loadNode(); - if (work && node) { - const rows = selectedRows.map((item) => { - return { - ...item, - orderCount: item.carCount, - }; - }); - const instance = await work.applyData(node, rows); - setCenter( - { - if (success) { - if (await page.shoppingCar.batchRemove(selectedRows)) { - setSelectedRows([]); - } - } - setCenter(<>); - }} - />, - ); - } - return; - }}> + onClick={onPurchase.bind(this, selectedRows)}> {(() => { if (loading) { return '加载办事中...'; @@ -169,7 +138,6 @@ export const RightCar: React.FC = ({ page }) => {
- {center} ); }; diff --git a/src/executor/open/mallTemplate/widget/product.tsx b/src/executor/open/mallTemplate/widget/product.tsx index 917077478..5c5b83ae3 100644 --- a/src/executor/open/mallTemplate/widget/product.tsx +++ b/src/executor/open/mallTemplate/widget/product.tsx @@ -11,6 +11,7 @@ import DataDetails from '../components/dataDetails'; interface IProps { current: IMallTemplate; product: schema.XProduct; + onPurchase: (selectedRows: schema.XProduct[]) => void; } const images = (product: schema.XProduct): model.FileItemShare[] => { @@ -27,7 +28,7 @@ const images = (product: schema.XProduct): model.FileItemShare[] => { return images; }; -export const Product: React.FC = ({ current, product }) => { +export const Product: React.FC = ({ current, product, onPurchase }) => { const [center, setCenter] = useState(<>); const [staging, setStaging] = useState( current.shoppingCar.products.some((a) => !a.isMultiple && a.id == product.id), @@ -76,6 +77,7 @@ export const Product: React.FC = ({ current, product }) => { data={product} current={current} onAddCar={addCar} + onPurchase={onPurchase} onCancel={() => setCenter(<>)} />, ) @@ -110,7 +112,7 @@ export const Product: React.FC = ({ current, product }) => {
-
+
立即申领
@@ -139,6 +141,7 @@ export const Product: React.FC = ({ current, product }) => { data={product} onAddCar={addCar} onCancel={() => setCenter(<>)} + onPurchase={onPurchase} />, ) }> @@ -178,7 +181,9 @@ export const Product: React.FC = ({ current, product }) => {
-
{}}> +
立即购买
-- Gitee From a3d07814265359bb9cc1e42d898a3478d5b5461a Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Mon, 29 Jul 2024 18:46:50 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E5=8A=9E=E4=BA=8B=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E4=BF=AE=E6=94=B9=E7=94=A8target=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/executor/tools/task/start/default.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/executor/tools/task/start/default.tsx b/src/executor/tools/task/start/default.tsx index 32a9c6ab7..94d67dbc4 100644 --- a/src/executor/tools/task/start/default.tsx +++ b/src/executor/tools/task/start/default.tsx @@ -69,7 +69,7 @@ const DefaultWayStart: React.FC = ({ const [ser, setSer] = useState(); const [printModal, setPrintModal] = useState(false); const service = useRef( - new WorkFormService(apply.target.space, apply.instanceData, true, apply.reception), + new WorkFormService(apply.target, apply.instanceData, true, apply.reception), ); const hasReport = useMemo( @@ -227,6 +227,7 @@ const DefaultWayStart: React.FC = ({ removePrintIframe(); }; }, []); + return (
-- Gitee From 93d4f7919a32b8dfd4adce9afb386fcb745c9d48 Mon Sep 17 00:00:00 2001 From: SEN Date: Tue, 30 Jul 2024 09:40:37 +0800 Subject: [PATCH 10/13] =?UTF-8?q?fix:=20=E6=89=93=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b6fdbc82e..34b3eefdc 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,7 @@ "scripts": { "dev": "vite --mode development", "build": "node --max_old_space_size=20480 ./node_modules/.bin/vite build", - "build:beta": "vite build --mode beta", - "build:release": "vite build --mode release", - "build:legacy": "vite build --mode legacy ", - "build:deploy": "vite build --base=/vite-react-ts/", + "build:win": "cross-env LIMIT=40960 increase-memory-limit && vite build", "lint": "npm run lint:js && npm run lint:prettier && npm run tsc", "lint-staged": "lint-staged", "lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ", @@ -76,6 +73,7 @@ "antd": "^4.24.4", "axios": "^1.1.2", "bytemd": "^1.21.0", + "cross-env": "^7.0.3", "crypto-js": "^4.1.1", "dayjs": "^1.10.6", "devextreme": "^23.1.6", @@ -86,6 +84,7 @@ "for-editor": "^0.3.5", "handsontable": "^14.0.0", "html2canvas": "^1.4.1", + "increase-memory-limit": "^1.0.7", "jol-player": "^4.0.0", "pako": "^2.1.0", "pinyin-pro": "^3.19.6", -- Gitee From 66cc8bf18d78ef96146573bcc6c0109eb1cfb04a Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Tue, 30 Jul 2024 09:43:09 +0800 Subject: [PATCH 11/13] =?UTF-8?q?=E6=96=B0=E5=A2=9Etarget=E5=B1=9E?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/executor/tools/task/start/default.tsx | 2 +- src/executor/tools/workForm/detail.tsx | 3 ++- src/ts/scripting/core/services/FormServiceBase.ts | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/executor/tools/task/start/default.tsx b/src/executor/tools/task/start/default.tsx index 94d67dbc4..7b8332f63 100644 --- a/src/executor/tools/task/start/default.tsx +++ b/src/executor/tools/task/start/default.tsx @@ -69,7 +69,7 @@ const DefaultWayStart: React.FC = ({ const [ser, setSer] = useState(); const [printModal, setPrintModal] = useState(false); const service = useRef( - new WorkFormService(apply.target, apply.instanceData, true, apply.reception), + new WorkFormService(apply.target.space, apply.instanceData, true, apply.reception, undefined,apply.target), ); const hasReport = useMemo( diff --git a/src/executor/tools/workForm/detail.tsx b/src/executor/tools/workForm/detail.tsx index 735acee19..0af662023 100644 --- a/src/executor/tools/workForm/detail.tsx +++ b/src/executor/tools/workForm/detail.tsx @@ -21,6 +21,7 @@ import saveAs from 'file-saver'; import { IBelong } from '@/utils/excel'; import { Sequence } from '@/ts/core/thing/standard/sequence'; import { FormChangeEvent } from '@/ts/scripting/core/types/rule'; +import { ITarget } from '@/ts/core'; interface FormProps { allowEdit: boolean; form: schema.XForm; @@ -694,7 +695,7 @@ const DetailTable: React.FC = (props) => { EditModal.showFormSelect({ form: form, fields: fields, - belong: props.service.belong, + belong: props.service.target as ITarget, onSave: (values) => { values.forEach((item) => { if (formData.after.every((i) => i.id !== item.id)) { diff --git a/src/ts/scripting/core/services/FormServiceBase.ts b/src/ts/scripting/core/services/FormServiceBase.ts index ce39b37e8..71b5afce0 100644 --- a/src/ts/scripting/core/services/FormServiceBase.ts +++ b/src/ts/scripting/core/services/FormServiceBase.ts @@ -15,6 +15,7 @@ import ValidateHandler from '../rule/ValidateHandler'; import RenderHandler from '../rule/RenderHandler'; import SplitHandler from '../rule/SplitHandler'; import { Form } from '@/ts/core/thing/standard/form'; +import { ITarget } from '@/ts/core/target/base/target' export default abstract class FormServiceBase extends ScriptEnv @@ -24,6 +25,7 @@ export default abstract class FormServiceBase readonly model: model.InstanceDataModel; readonly allowEdit: boolean; readonly reception?: XReception; + readonly target?: ITarget; readonly formCodeMap: Dictionary = {}; @@ -59,12 +61,14 @@ export default abstract class FormServiceBase allowEdit = true, reception?: XReception, functionProvider?: FunctionProvider, + target?: ITarget ) { super(functionProvider); this.belong = belong; this.model = model; this.allowEdit = allowEdit; this.reception = reception; + this.target = target this.complete(this.model.node); this.executable = new ExecutableHandler(this, allowEdit); -- Gitee From 44a1879eca4cbe39ccb90133c4ba18e4d8e73685 Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Tue, 30 Jul 2024 13:41:25 +0800 Subject: [PATCH 12/13] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=95=86=E5=9F=8E?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=BA=94=E7=94=A8=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/column.tsx | 12 +- .../components/dataDetails/index.tsx | 17 +-- .../open/mallTemplate/pages/index.tsx | 58 +++++++-- .../open/mallTemplate/widget/product.tsx | 42 ++---- .../open/mallTemplate/widget/virtually.tsx | 122 ++++++++++++++++++ src/ts/base/schema.ts | 7 +- src/ts/core/public/enums.ts | 7 + src/ts/core/thing/standard/page/index.ts | 3 +- 8 files changed, 208 insertions(+), 60 deletions(-) create mode 100644 src/executor/open/mallTemplate/widget/virtually.tsx diff --git a/src/config/column.tsx b/src/config/column.tsx index 7a852dbd6..c365aeec0 100644 --- a/src/config/column.tsx +++ b/src/config/column.tsx @@ -281,7 +281,7 @@ export const FullEntityColumns = (fields: model.FieldModel[], typeName?: string) export const FullProperties = (typeName: string) => { switch (typeName) { case '虚拟商品': - return ProductProperties(); + return VirtuallyProperties(ProductProperties()); case '实体商品': return PhysicalProperties(ProductProperties()); case '报表数据': @@ -325,8 +325,7 @@ export const PhysicalProperties = (props: schema.XProperty[]) => { ] as schema.XProperty[]; }; -/** 商品属性 */ -export const ProductProperties = () => { +export const VirtuallyProperties = (props: schema.XProperty[]) => { return [ { id: 'icons', @@ -335,6 +334,13 @@ export const ProductProperties = () => { valueType: '附件型', remark: '图标组', }, + ...props, + ] as schema.XProperty[]; +}; + +/** 商品属性 */ +export const ProductProperties = () => { + return [ { id: 'title', name: '商品名称', diff --git a/src/executor/open/mallTemplate/components/dataDetails/index.tsx b/src/executor/open/mallTemplate/components/dataDetails/index.tsx index ba1b8a81e..0e00a80ab 100644 --- a/src/executor/open/mallTemplate/components/dataDetails/index.tsx +++ b/src/executor/open/mallTemplate/components/dataDetails/index.tsx @@ -1,4 +1,4 @@ -import React, { memo, useCallback, useState, useEffect } from 'react'; +import React, { memo, useCallback } from 'react'; import { Modal, Image, Tabs, Carousel, Skeleton } from 'antd'; import type { schema, model } from '@/ts/base'; import { IMallTemplate } from '@/ts/core/thing/standard/page/mallTemplate'; @@ -13,20 +13,11 @@ interface IDataDetails { } const DataDetails = ({ current, data, onCancel, onAddCar, onPurchase }: IDataDetails) => { - const [staging, setStaging] = useState( - current.shoppingCar.products.some((a) => a.id == data.id), - ); const getImage = useCallback((type: string, num?: number) => { let images: model.FileItemShare[] = []; images = JSON.parse(data[type] || '[]'); return num ? images.splice(0, num) : images; }, []); - useEffect(() => { - const id = current.shoppingCar.subscribe(() => { - setStaging(current.shoppingCar.products.some((a) => a.id == data.id)); - }); - return () => current.shoppingCar.unsubscribe(id); - }, []); const evaluateData = [ { key: 1, @@ -175,7 +166,7 @@ const DataDetails = ({ current, data, onCancel, onAddCar, onPurchase }: IDataDet
{current.metadata.template === 'dataTemplate' ? ( } className={cls.productImg} @@ -205,7 +196,7 @@ const DataDetails = ({ current, data, onCancel, onAddCar, onPurchase }: IDataDet
{data.title || '[未设置名称]'}
{data.remark}
- {data.mode !== 'sharing' && ( + {data.mode !== '共享' && (
¥{data.price || 0}
{0}人已买
@@ -214,7 +205,7 @@ const DataDetails = ({ current, data, onCancel, onAddCar, onPurchase }: IDataDet
- {data.mode === 'sharing' ? ( + {data.mode === '共享' ? ( 立即申领 ) : ( 立即购买 diff --git a/src/executor/open/mallTemplate/pages/index.tsx b/src/executor/open/mallTemplate/pages/index.tsx index 5055e57db..0f186358f 100644 --- a/src/executor/open/mallTemplate/pages/index.tsx +++ b/src/executor/open/mallTemplate/pages/index.tsx @@ -21,9 +21,11 @@ import { Content, Header } from 'antd/lib/layout/layout'; import { ScrollView, TreeView } from 'devextreme-react'; import React, { ReactNode, useEffect, useRef, useState } from 'react'; import { Product } from '../widget/product'; +import { Virtually } from '../widget/virtually'; import cls from './../index.module.less'; import { RightCar } from './shoppingCar'; import WorkStartDo from '../../work'; +import { TemplateType } from '@/ts/core/public/enums'; interface IProps { current: IMallTemplate; @@ -31,6 +33,31 @@ interface IProps { export const MallTemplate: React.FC = ({ current }) => { const [center, setCenter] = useState(<>); + // 加入购物车 + const onAddCar = (product: schema.XProduct, staging: boolean) => { + if (product.isMultiple) { + let num = + current.shoppingCar.products.find((i) => i.id === product.id)?.carCount || 0; + num++; + if (!num) return; + if (num > (product.count || 0)) { + message.error('库存不足'); + return; + } + current.shoppingCar.create({ + ...product, + carCount: num, + }); + message.success('已加入购物车'); + } else { + if (staging) { + current.shoppingCar.remove(product); + } else { + current.shoppingCar.create(product); + } + } + }; + // 结算 const onPurchase = async (selectedRows: schema.XProduct[]) => { const work = await current.findWork(); if (!selectedRows.length) { @@ -72,8 +99,8 @@ export const MallTemplate: React.FC = ({ current }) => { bannerkey={current.id} /> - - + + {center} ); @@ -81,10 +108,11 @@ export const MallTemplate: React.FC = ({ current }) => { interface IHotGroup { current: IMallTemplate; + onAddCar: (product: schema.XProduct, staging: boolean) => void; onPurchase: (selectedRows: schema.XProduct[]) => void; } -const HotBody: React.FC = ({ current, onPurchase }) => { +const HotBody: React.FC = ({ current, onPurchase, onAddCar }) => { const [hot, setHot] = useState(); useEffect(() => { const id = current.subscribe(async () => setHot(await current.loadHot())); @@ -111,6 +139,7 @@ const HotBody: React.FC = ({ current, onPurchase }) => { key={item.id} current={current} product={item} + onAddCar={onAddCar} onPurchase={onPurchase} /> ); @@ -129,9 +158,10 @@ interface DataProps extends IProps { } interface IContentBody extends IProps { onPurchase: (selectedRows: schema.XProduct[]) => void; + onAddCar: (product: schema.XProduct, staging: boolean) => void; } -const ContentBody: React.FC = ({ current, onPurchase }) => { +const ContentBody: React.FC = ({ current, onPurchase, onAddCar }) => { const [loading, setLoading] = useState(true); const [form, setForm] = useState(); const loadContent = async () => { @@ -170,11 +200,21 @@ const ContentBody: React.FC = ({ current, onPurchase }) => { {products.map((item) => { return ( - + {current.template === TemplateType.realTemplate ? ( + + ) : ( + + )} ); })} diff --git a/src/executor/open/mallTemplate/widget/product.tsx b/src/executor/open/mallTemplate/widget/product.tsx index 5c5b83ae3..f85b299eb 100644 --- a/src/executor/open/mallTemplate/widget/product.tsx +++ b/src/executor/open/mallTemplate/widget/product.tsx @@ -2,7 +2,7 @@ import EntityIcon from '@/components/Common/GlobalComps/entityIcon'; import { model, schema } from '@/ts/base'; import { IMallTemplate } from '@/ts/core/thing/standard/page/mallTemplate'; import { ShoppingCartOutlined } from '@ant-design/icons'; -import { Carousel, Image, Skeleton, Space, message } from 'antd'; +import { Carousel, Image, Skeleton, Space } from 'antd'; import React, { useEffect, useState } from 'react'; import cls from './../index.module.less'; import down from '/public/img/mallTemplate/down.svg'; @@ -11,6 +11,7 @@ import DataDetails from '../components/dataDetails'; interface IProps { current: IMallTemplate; product: schema.XProduct; + onAddCar: (product: schema.XProduct, staging: boolean) => void; onPurchase: (selectedRows: schema.XProduct[]) => void; } @@ -28,7 +29,7 @@ const images = (product: schema.XProduct): model.FileItemShare[] => { return images; }; -export const Product: React.FC = ({ current, product, onPurchase }) => { +export const Product: React.FC = ({ current, product, onAddCar, onPurchase }) => { const [center, setCenter] = useState(<>); const [staging, setStaging] = useState( current.shoppingCar.products.some((a) => !a.isMultiple && a.id == product.id), @@ -41,29 +42,6 @@ export const Product: React.FC = ({ current, product, onPurchase }) => { }); return () => current.shoppingCar.unsubscribe(id); }, []); - const addCar = () => { - if (product.isMultiple) { - let num = - current.shoppingCar.products.find((i) => i.id === product.id)?.carCount || 0; - num++; - if (!num) return; - if (num > (product.count || 0)) { - message.error('库存不足'); - return; - } - current.shoppingCar.create({ - ...product, - carCount: num, - }); - message.success('已加入购物车'); - } else { - if (staging) { - current.shoppingCar.remove(product); - } else { - current.shoppingCar.create(product); - } - } - }; const loadBody = () => { switch (product.mode) { case '共享': @@ -76,7 +54,7 @@ export const Product: React.FC = ({ current, product, onPurchase }) => { setCenter(<>)} />, @@ -112,11 +90,15 @@ export const Product: React.FC = ({ current, product, onPurchase }) => {
-
+
立即申领
-
+
= ({ current, product, onPurchase }) => { setCenter(<>)} onPurchase={onPurchase} />, @@ -189,7 +171,7 @@ export const Product: React.FC = ({ current, product, onPurchase }) => {
void; + onPurchase: (selectedRows: schema.XProduct[]) => void; +} + +export const Virtually: React.FC = ({ + product, + current, + onAddCar, + onPurchase, +}) => { + const [center, setCenter] = useState(<>); + const [staging, setStaging] = useState( + current.shoppingCar.products.some((a) => !a.isMultiple && a.id == product.id), + ); + const icons: model.FileItemShare[] = JSON.parse(product.icons || '[]'); + if (icons.length == 0) { + icons.push({} as model.FileItemShare); + } + useEffect(() => { + const id = current.shoppingCar.subscribe(() => { + setStaging( + current.shoppingCar.products.some((a) => !a.isMultiple && a.id == product.id), + ); + }); + return () => current.shoppingCar.unsubscribe(id); + }, []); + return ( + <> +
+
{ + setCenter( + setCenter(<>)} + onPurchase={onPurchase} + />, + ); + }}> +
+ {icons.map((item) => { + return ( + + ); + })} + {product.title ?? '[未设置名称]'} +
+
+ +
{product.remark}
+ {product.mode === MallTemplateMode.sharing && ( + <> +
+ 供给方: + +
+
上架时间:{product.updateTime}
+ + )} +
+
+
+
+ {product.mode !== MallTemplateMode.sharing && ( +
+ ¥{product.price || 0} + {0}人已买 +
+ )} +
+
+ + + {product.mode !== MallTemplateMode.sharing ? '立即购买' : '立即申领'} + +
+
+ + {product.mode === MallTemplateMode.sharing && ( + 加入购物车 + )} +
+
+
+
+ {center} + + ); +}; diff --git a/src/ts/base/schema.ts b/src/ts/base/schema.ts index 40b3b9f83..12b82efdd 100644 --- a/src/ts/base/schema.ts +++ b/src/ts/base/schema.ts @@ -1,4 +1,5 @@ import { model } from '.'; +import { MallTemplateMode, TemplateType } from '../core/public/enums'; import { ReceptionStatus, ReportTaskTreeSummary } from '../core/work/assign/reception/status'; import { NodeType, PeriodType, ReportTreeNodeTypes, ReportTreeTypes } from './enum'; @@ -887,13 +888,11 @@ export interface XPageTemplate extends XStandard { // 是否公开 open: boolean; // 模板类型 - template?: string; + template?: TemplateType; // 模板类型 kind?: string; // 自定义参数; params: T; - // 模版模式 共享 | 交易 - mode?: 'sharing' | 'trading'; } // 商城模板 @@ -1288,7 +1287,7 @@ export interface XSubscription extends XSyncing { // 商品 export type XProduct = { // 交易、共享 - mode: string; + mode: MallTemplateMode; // 商城 ID mallId: string; // 商品类型 diff --git a/src/ts/core/public/enums.ts b/src/ts/core/public/enums.ts index e20d4ad16..5b94c7021 100644 --- a/src/ts/core/public/enums.ts +++ b/src/ts/core/public/enums.ts @@ -114,3 +114,10 @@ export enum TemplateType { // 实体商品模板 realTemplate = 'realTemplate', } +/** 商城模板展示模式 */ +export enum MallTemplateMode { + // 共享 + sharing = '共享', + // 交易 + trading = '交易', +} diff --git a/src/ts/core/thing/standard/page/index.ts b/src/ts/core/thing/standard/page/index.ts index 3234a317c..c9d36a196 100644 --- a/src/ts/core/thing/standard/page/index.ts +++ b/src/ts/core/thing/standard/page/index.ts @@ -1,4 +1,5 @@ import { Command, schema } from '@/ts/base'; +import { TemplateType } from '@/ts/core/public/enums'; import { IWork } from '../../../work'; import { IDirectory } from '../../directory'; import { IStandardFileInfo, StandardFileInfo } from '../../fileinfo'; @@ -10,7 +11,7 @@ export interface IPageTemplate /** 自定义参数 */ params: T; /** 模板类型 */ - template?: string; + template?: TemplateType; /** 查找办事 */ loadWork(workId: string): Promise; } -- Gitee From 177351ae77712d9580c9a8804c7ed1e06d06e2ce Mon Sep 17 00:00:00 2001 From: maxJianguo <14449292+maxjianguo@user.noreply.gitee.com> Date: Wed, 31 Jul 2024 15:56:13 +0800 Subject: [PATCH 13/13] =?UTF-8?q?=E5=95=86=E5=9F=8E=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=88=86=E7=B1=BB=E9=9A=90=E8=97=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/executor/open/mallTemplate/pages/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/executor/open/mallTemplate/pages/index.tsx b/src/executor/open/mallTemplate/pages/index.tsx index 0f186358f..c7cc23a89 100644 --- a/src/executor/open/mallTemplate/pages/index.tsx +++ b/src/executor/open/mallTemplate/pages/index.tsx @@ -299,7 +299,9 @@ const Group: React.FC = ({ current, form, onPurchase }) => { }; const Filter: React.FC = ({ current, form }) => { - const lookups = form.fields.flatMap((item) => item.lookups ?? []); + const lookups = form.fields.flatMap((item) => + item.options?.species ? item.lookups ?? [] : [], + ); if (lookups.length === 0) { return <>; } -- Gitee