Commit 3b7be2236ce179d07e014f5de1d7849c1a752a72
1 parent
43b738e2
快速报价app tab新增
Showing
4 changed files
with
153 additions
and
30 deletions
src/mobile/components/SelectInput.jsx
| 1 | import React, { useState, useRef, useEffect, useCallback } from "react"; | 1 | import React, { useState, useRef, useEffect, useCallback } from "react"; |
| 2 | -import { Input, Popup, Button, Toast, PickerView, SearchBar } from "antd-mobile"; | 2 | +import { Input, Popup, Button, Toast, PickerView, SearchBar,Checkbox } from "antd-mobile"; |
| 3 | import { DownOutline } from "antd-mobile-icons"; | 3 | import { DownOutline } from "antd-mobile-icons"; |
| 4 | import commonConfig from "@/utils/config"; | 4 | import commonConfig from "@/utils/config"; |
| 5 | import * as commonServices from "@/services/services"; | 5 | import * as commonServices from "@/services/services"; |
| @@ -18,8 +18,11 @@ const SelectInput = props => { | @@ -18,8 +18,11 @@ const SelectInput = props => { | ||
| 18 | const { masterData } = props.state; | 18 | const { masterData } = props.state; |
| 19 | const [bCanInput, setBCanInput] = useState(props.bCanInput); | 19 | const [bCanInput, setBCanInput] = useState(props.bCanInput); |
| 20 | const { bReadonly } = itemDetail || {}; | 20 | const { bReadonly } = itemDetail || {}; |
| 21 | + const [propsType, setPropsType] = useState(""); | ||
| 21 | useEffect(() => { | 22 | useEffect(() => { |
| 22 | if (!itemDetail) return; | 23 | if (!itemDetail) return; |
| 24 | + const type = itemDetail.sName.charAt(0); | ||
| 25 | + setPropsType(type); | ||
| 23 | const viewRowNew = itemDetail.sName ? viewRow?.[itemDetail.sName] : ""; | 26 | const viewRowNew = itemDetail.sName ? viewRow?.[itemDetail.sName] : ""; |
| 24 | if (itemDetail.sDropDownType === "const") { | 27 | if (itemDetail.sDropDownType === "const") { |
| 25 | return; | 28 | return; |
| @@ -109,7 +112,7 @@ const SelectInput = props => { | @@ -109,7 +112,7 @@ const SelectInput = props => { | ||
| 109 | setCopyColumns(list); | 112 | setCopyColumns(list); |
| 110 | // getSqlDropDownData(searchValue); | 113 | // getSqlDropDownData(searchValue); |
| 111 | } else if ((sDropDownType = "const")) { | 114 | } else if ((sDropDownType = "const")) { |
| 112 | - if (!itemDetail.showDropDown) return | 115 | + if (!itemDetail.showDropDown) return; |
| 113 | const list = Object.entries(JSON.parse(itemDetail.showDropDown)).map(([key, value]) => ({ | 116 | const list = Object.entries(JSON.parse(itemDetail.showDropDown)).map(([key, value]) => ({ |
| 114 | label: value, | 117 | label: value, |
| 115 | value: key, | 118 | value: key, |
| @@ -121,7 +124,7 @@ const SelectInput = props => { | @@ -121,7 +124,7 @@ const SelectInput = props => { | ||
| 121 | if (sDropDownType === "sql") { | 124 | if (sDropDownType === "sql") { |
| 122 | getSqlDropDownData(searchValue); | 125 | getSqlDropDownData(searchValue); |
| 123 | } else if ((sDropDownType = "const")) { | 126 | } else if ((sDropDownType = "const")) { |
| 124 | - if (!itemDetail.showDropDown) return | 127 | + if (!itemDetail.showDropDown) return; |
| 125 | const list = Object.entries(JSON.parse(itemDetail.showDropDown)).map(([key, value]) => ({ | 128 | const list = Object.entries(JSON.parse(itemDetail.showDropDown)).map(([key, value]) => ({ |
| 126 | label: value, | 129 | label: value, |
| 127 | value: key, | 130 | value: key, |
| @@ -144,20 +147,27 @@ const SelectInput = props => { | @@ -144,20 +147,27 @@ const SelectInput = props => { | ||
| 144 | return ( | 147 | return ( |
| 145 | <div> | 148 | <div> |
| 146 | <div className={styles.inputBox}> | 149 | <div className={styles.inputBox}> |
| 147 | - <Input | ||
| 148 | - placeholder="" | ||
| 149 | - value={value} | ||
| 150 | - onChange={val => { | ||
| 151 | - setValue(val); | ||
| 152 | - props.onDataChange(tableName, itemDetail.sName, { [itemDetail.sName]: val }, null, coplyColumns); | ||
| 153 | - }} | ||
| 154 | - readOnly={bReadonly} | ||
| 155 | - /> | ||
| 156 | - {!bCanInput ? ( | ||
| 157 | - <div className={styles.icons} onClick={clickBtn}> | ||
| 158 | - <DownOutline /> | 150 | + {propsType === "b" ? ( |
| 151 | + <Checkbox style={{height:'3.125rem'}}/> | ||
| 152 | + ) : ( | ||
| 153 | + <div> | ||
| 154 | + {" "} | ||
| 155 | + <Input | ||
| 156 | + placeholder="" | ||
| 157 | + value={value} | ||
| 158 | + onChange={val => { | ||
| 159 | + setValue(val); | ||
| 160 | + props.onDataChange(tableName, itemDetail.sName, { [itemDetail.sName]: val }, null, coplyColumns); | ||
| 161 | + }} | ||
| 162 | + readOnly={bReadonly} | ||
| 163 | + /> | ||
| 164 | + {!bCanInput ? ( | ||
| 165 | + <div className={styles.icons} onClick={clickBtn}> | ||
| 166 | + <DownOutline /> | ||
| 167 | + </div> | ||
| 168 | + ) : null} | ||
| 159 | </div> | 169 | </div> |
| 160 | - ) : null} | 170 | + )} |
| 161 | </div> | 171 | </div> |
| 162 | <Popup visible={visible} onMaskClick={() => setVisible(false)} onClose={() => setVisible(false)} bodyStyle={{ height: "50vh" }}> | 172 | <Popup visible={visible} onMaskClick={() => setVisible(false)} onClose={() => setVisible(false)} bodyStyle={{ height: "50vh" }}> |
| 163 | <div className={styles.popupHeader}> | 173 | <div className={styles.popupHeader}> |
src/mobile/quotation/detailNew.jsx
| 1 | import { useRef, useEffect, useState, useCallback, useMemo } from "react"; | 1 | import { useRef, useEffect, useState, useCallback, useMemo } from "react"; |
| 2 | import { history } from "umi"; | 2 | import { history } from "umi"; |
| 3 | -import { Toast, Input, Tabs, Selector, Grid, Image, Button, Checkbox, Switch, Dialog, Radio, Space } from "antd-mobile"; | 3 | +import { Toast, Input, Tabs, Selector, Grid, Image, Button, Checkbox, Switch, Dialog, Radio, Space, CenterPopup } from "antd-mobile"; |
| 4 | import { AddOutline, MinusOutline, EditFill, CloseOutline } from "antd-mobile-icons"; | 4 | import { AddOutline, MinusOutline, EditFill, CloseOutline } from "antd-mobile-icons"; |
| 5 | import commonConfig from "@/utils/config"; | 5 | import commonConfig from "@/utils/config"; |
| 6 | import * as commonServices from "@/services/services"; | 6 | import * as commonServices from "@/services/services"; |
| @@ -1171,11 +1171,11 @@ const MasterComponent = props => { | @@ -1171,11 +1171,11 @@ const MasterComponent = props => { | ||
| 1171 | const QuotationTabs = props => { | 1171 | const QuotationTabs = props => { |
| 1172 | const { state } = props; | 1172 | const { state } = props; |
| 1173 | const { selectedNode } = state; | 1173 | const { selectedNode } = state; |
| 1174 | - const sAllPartsName = selectedNode?.sAllPartsName; | ||
| 1175 | - const sAllPartsNameList = sAllPartsName?.split(","); | ||
| 1176 | - // sAllPartsNameList.push('+') | ||
| 1177 | - const [activeKey, setActiveKey] = useState(sAllPartsNameList && sAllPartsNameList.length ? sAllPartsNameList[0] : null); | ||
| 1178 | - | 1174 | + const [sAllPartsNameList, setSAllPartsNameList] = useState(selectedNode?.sAllPartsName?.split(",") || []); |
| 1175 | + const [activeKey, setActiveKey] = useState(sAllPartsNameList.length ? sAllPartsNameList[0] : null); | ||
| 1176 | + const [visible, setVisible] = useState(false); | ||
| 1177 | + const [value, setValue] = useState(""); | ||
| 1178 | + const partsList = selectedNode?.sAllPartsName?.split(","); | ||
| 1179 | useEffect(() => { | 1179 | useEffect(() => { |
| 1180 | // 更新父组件的状态 | 1180 | // 更新父组件的状态 |
| 1181 | props.setState(pre => ({ ...pre, boxModel: activeKey })); | 1181 | props.setState(pre => ({ ...pre, boxModel: activeKey })); |
| @@ -1185,6 +1185,15 @@ const QuotationTabs = props => { | @@ -1185,6 +1185,15 @@ const QuotationTabs = props => { | ||
| 1185 | ...props, | 1185 | ...props, |
| 1186 | boxModel: activeKey, | 1186 | boxModel: activeKey, |
| 1187 | }; | 1187 | }; |
| 1188 | + | ||
| 1189 | + // 处理添加新标签的逻辑 | ||
| 1190 | + const handleAdd = () => { | ||
| 1191 | + // 弹窗 | ||
| 1192 | + setVisible(true); | ||
| 1193 | + // const newSAllPartsNameList = [...sAllPartsNameList, '111']; // 创建一个新的数组,包含新增的元素 | ||
| 1194 | + // setSAllPartsNameList(newSAllPartsNameList); // 更新状态,触发组件重新渲染 | ||
| 1195 | + }; | ||
| 1196 | + | ||
| 1188 | return ( | 1197 | return ( |
| 1189 | <div> | 1198 | <div> |
| 1190 | <div className={styles.tabsBox}> | 1199 | <div className={styles.tabsBox}> |
| @@ -1194,25 +1203,91 @@ const QuotationTabs = props => { | @@ -1194,25 +1203,91 @@ const QuotationTabs = props => { | ||
| 1194 | setActiveKey(key); | 1203 | setActiveKey(key); |
| 1195 | }} | 1204 | }} |
| 1196 | > | 1205 | > |
| 1197 | - {sAllPartsNameList && sAllPartsNameList.length | 1206 | + {sAllPartsNameList.length |
| 1198 | ? sAllPartsNameList.map((pane, index) => ( | 1207 | ? sAllPartsNameList.map((pane, index) => ( |
| 1199 | - <Tabs.Tab key={pane} title={pane} > | ||
| 1200 | - <BoxComponent {...tabsProps} paneKey={pane} /> | ||
| 1201 | - {/* <CloseOutline className={styles.tabClearBtn}/> */} | ||
| 1202 | - </Tabs.Tab> | 1208 | + <> |
| 1209 | + <Tabs.Tab | ||
| 1210 | + key={pane} | ||
| 1211 | + title={ | ||
| 1212 | + <div className={styles.tabTitle}> | ||
| 1213 | + <div>{pane}</div> | ||
| 1214 | + {partsList.includes(pane) ? ( | ||
| 1215 | + "" | ||
| 1216 | + ) : ( | ||
| 1217 | + <CloseOutline | ||
| 1218 | + style={{ marginLeft: "1rem", position: "absolute", top: "0", right: "-2.5rem" }} | ||
| 1219 | + onClick={() => { | ||
| 1220 | + const newTabs = sAllPartsNameList.filter(panes => panes !== pane); | ||
| 1221 | + setSAllPartsNameList(newTabs); | ||
| 1222 | + // 如果删除的是当前活动的 Tab,选择新的活动 Tab | ||
| 1223 | + setActiveKey(0); | ||
| 1224 | + }} | ||
| 1225 | + /> | ||
| 1226 | + )} | ||
| 1227 | + </div> | ||
| 1228 | + } | ||
| 1229 | + > | ||
| 1230 | + <BoxComponent {...tabsProps} paneKey={pane} /> | ||
| 1231 | + </Tabs.Tab> | ||
| 1232 | + </> | ||
| 1203 | )) | 1233 | )) |
| 1204 | : ""} | 1234 | : ""} |
| 1205 | </Tabs> | 1235 | </Tabs> |
| 1206 | - {/* <Button | 1236 | + <Button |
| 1207 | className={styles.tabAddBtn} | 1237 | className={styles.tabAddBtn} |
| 1208 | color="primary" | 1238 | color="primary" |
| 1209 | fill="solid" | 1239 | fill="solid" |
| 1210 | size="small" | 1240 | size="small" |
| 1211 | style={{ width: "1.93rem", height: "1.93rem", display: "flex", justifyContent: "center", alignItems: "center", textAlign: "center" }} | 1241 | style={{ width: "1.93rem", height: "1.93rem", display: "flex", justifyContent: "center", alignItems: "center", textAlign: "center" }} |
| 1212 | - onClick={() => {}} | 1242 | + onClick={handleAdd} // 调用 handleAdd 方法 |
| 1213 | > | 1243 | > |
| 1214 | <AddOutline /> | 1244 | <AddOutline /> |
| 1215 | - </Button> */} | 1245 | + </Button> |
| 1246 | + <CenterPopup | ||
| 1247 | + visible={visible} | ||
| 1248 | + // onMaskClick={() => { | ||
| 1249 | + // setVisible(false); | ||
| 1250 | + // }} | ||
| 1251 | + > | ||
| 1252 | + <div className={styles.addTabs}> | ||
| 1253 | + <div>请输入新标签名称:</div> | ||
| 1254 | + <Input | ||
| 1255 | + placeholder="请输入内容" | ||
| 1256 | + clearable | ||
| 1257 | + value={value} | ||
| 1258 | + onChange={val => { | ||
| 1259 | + setValue(val); | ||
| 1260 | + }} | ||
| 1261 | + /> | ||
| 1262 | + <div className={styles.addTabsBtn}> | ||
| 1263 | + <Button | ||
| 1264 | + color="primary" | ||
| 1265 | + fill="outline" | ||
| 1266 | + size="small" | ||
| 1267 | + style={{ marginRight: "1rem" }} | ||
| 1268 | + onClick={() => { | ||
| 1269 | + setValue(""); | ||
| 1270 | + setVisible(false); | ||
| 1271 | + }} | ||
| 1272 | + > | ||
| 1273 | + 取消 | ||
| 1274 | + </Button> | ||
| 1275 | + <Button | ||
| 1276 | + color="primary" | ||
| 1277 | + fill="solid" | ||
| 1278 | + size="small" | ||
| 1279 | + onClick={() => { | ||
| 1280 | + const newSAllPartsNameList = [...sAllPartsNameList, value]; // 创建一个新的数组,包含新增的元素 | ||
| 1281 | + setSAllPartsNameList(newSAllPartsNameList); // 更新状态,触发组件重新渲染 | ||
| 1282 | + setVisible(false); | ||
| 1283 | + setValue(""); | ||
| 1284 | + }} | ||
| 1285 | + > | ||
| 1286 | + 确认 | ||
| 1287 | + </Button> | ||
| 1288 | + </div> | ||
| 1289 | + </div> | ||
| 1290 | + </CenterPopup> | ||
| 1216 | </div> | 1291 | </div> |
| 1217 | </div> | 1292 | </div> |
| 1218 | ); | 1293 | ); |
src/mobile/quotation/quotationDetail.css
| @@ -140,3 +140,22 @@ | @@ -140,3 +140,22 @@ | ||
| 140 | right: 0; | 140 | right: 0; |
| 141 | top: 0; | 141 | top: 0; |
| 142 | } | 142 | } |
| 143 | +.tabsBox .tabTitle { | ||
| 144 | + display: flex; | ||
| 145 | + align-items: center; | ||
| 146 | + position: relative; | ||
| 147 | +} | ||
| 148 | +.addTabs { | ||
| 149 | + height: 12rem; | ||
| 150 | + padding: 1rem; | ||
| 151 | + position: relative; | ||
| 152 | +} | ||
| 153 | +.addTabs :global .adm-input-element { | ||
| 154 | + height: 3rem; | ||
| 155 | + border: 1px solid #dededf; | ||
| 156 | +} | ||
| 157 | +.addTabs .addTabsBtn { | ||
| 158 | + position: absolute; | ||
| 159 | + right: 5%; | ||
| 160 | + bottom: 10%; | ||
| 161 | +} |
src/mobile/quotation/quotationDetail.less
| @@ -148,4 +148,23 @@ | @@ -148,4 +148,23 @@ | ||
| 148 | right: 0; | 148 | right: 0; |
| 149 | top: 0; | 149 | top: 0; |
| 150 | } | 150 | } |
| 151 | + .tabTitle{ | ||
| 152 | + display: flex; | ||
| 153 | + align-items: center; | ||
| 154 | + position: relative; | ||
| 155 | + } | ||
| 151 | } | 156 | } |
| 157 | +.addTabs{ | ||
| 158 | + height: 12rem; | ||
| 159 | + padding: 1rem; | ||
| 160 | + position: relative; | ||
| 161 | + :global .adm-input-element{ | ||
| 162 | + height: 3rem; | ||
| 163 | + border: 1px solid #dededf; | ||
| 164 | + } | ||
| 165 | + .addTabsBtn{ | ||
| 166 | + position: absolute; | ||
| 167 | + right: 5%; | ||
| 168 | + bottom: 10%; | ||
| 169 | + } | ||
| 170 | +} | ||
| 152 | \ No newline at end of file | 171 | \ No newline at end of file |