GoodsSpecificationScreenNew.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /* eslint-disable no-else-return */
  2. /* eslint-disable prefer-const */
  3. /* eslint-disable react/jsx-one-expression-per-line */
  4. /* eslint-disable no-underscore-dangle */
  5. /* eslint-disable no-shadow */
  6. import * as WebBrowser from "expo-web-browser";
  7. import * as React from "react";
  8. import { StyleSheet, View } from "react-native";
  9. import { useModel } from "flooks";
  10. import {
  11. Layout,
  12. Text,
  13. useTheme,
  14. Button,
  15. Input,
  16. Toggle,
  17. } from "@ui-kitten/components";
  18. import { useFocusEffect, useRoute } from "@react-navigation/native";
  19. import { useEventEmitter, useCreation, useMap, useUnmount } from "@umijs/hooks";
  20. import ActionButton from "react-native-action-button";
  21. import ListComponent from "../../components/ListComponentParent";
  22. import NavHeaderBar from "../../components/NavHeaderBar";
  23. const styles = StyleSheet.create({
  24. lay: {
  25. backgroundColor: "#fff",
  26. flex: 1,
  27. },
  28. padBot: {
  29. paddingBottom: 100,
  30. },
  31. list: {
  32. paddingVertical: 10,
  33. paddingHorizontal: 15,
  34. backgroundColor: "transparent",
  35. flex: 0,
  36. },
  37. item: {
  38. flexDirection: "row",
  39. alignItems: "center",
  40. paddingVertical: 10,
  41. },
  42. input: {
  43. marginHorizontal: 5,
  44. minWidth: 49,
  45. // width: 49,
  46. },
  47. text: {
  48. flex: 1,
  49. },
  50. flexRow: {
  51. flexDirection: "row",
  52. alignItems: "center",
  53. },
  54. buttonlast: {
  55. marginLeft: 10,
  56. },
  57. button: {
  58. alignSelf: "flex-start",
  59. },
  60. money: {
  61. marginLeft: 10,
  62. },
  63. addNew2: {
  64. width: 80,
  65. alignSelf: "center",
  66. },
  67. separatorStyle: {
  68. height: 0,
  69. },
  70. });
  71. export default function GoodsSpecificationScreen() {
  72. const theme = useTheme();
  73. const { changeBackground } = useModel("barModel", true);
  74. // const { mid } = useModel("userModel");
  75. const { httpPost } = useModel("httpModel", true);
  76. const { showDialog } = useModel("dialogModel");
  77. const [goodsId, setGoodsId] = React.useState(0);
  78. const list$ = useEventEmitter();
  79. const [dataMap, dataMapAction] = useMap();
  80. const [editMap, editMapAction] = useMap();
  81. const parentIds = useCreation(() => {
  82. return Array.from(dataMap.keys());
  83. }, [dataMap]);
  84. const { delText, editText, YMZEFF, confirm, cancel, removeTips } = useModel(
  85. "wordsModel"
  86. );
  87. const {
  88. addClassGoods,
  89. getGoodsClassParent,
  90. setGoodsClassMap,
  91. editGoodsMap,
  92. } = useModel("goodsModel");
  93. useFocusEffect(
  94. React.useCallback(() => {
  95. changeBackground(theme["color-primary-500"]);
  96. }, [])
  97. );
  98. useUnmount(() => {
  99. setGoodsClassMap(goodsId, dataMap);
  100. dataMapAction.reset();
  101. editMapAction.reset();
  102. console.log(editGoodsMap);
  103. });
  104. const route = useRoute();
  105. function getList() {
  106. const { params } = route;
  107. const { goodsId } = params || {};
  108. setGoodsId(goodsId || "NEW");
  109. return getGoodsClassParent(goodsId || "NEW").then(res => {
  110. dataMapAction.setAll(res);
  111. return Promise.resolve();
  112. });
  113. }
  114. const editInfo = info => {
  115. if (!info.parent) {
  116. dataMapAction.set(info.id, {
  117. ...info,
  118. edit: true,
  119. });
  120. } else {
  121. let parentinfo = dataMapAction.get(info.parent);
  122. parentinfo.children[info.childIndex].edit = true;
  123. dataMapAction.set(info.parent, parentinfo);
  124. }
  125. if (info.id) {
  126. editMapAction.set(info.id, info);
  127. } else {
  128. editMapAction.set(`${info.parent}_${info.childIndex}`, info);
  129. }
  130. };
  131. const delInfo = info => {
  132. showDialog({
  133. bodyText: removeTips,
  134. status: "danger",
  135. cancelable: true,
  136. confirmCallback: () => {
  137. if (!info.parent) {
  138. let parent = dataMapAction.get(info.id);
  139. if (parent.children.length > 0) {
  140. showDialog({
  141. bodyText: YMZEFF,
  142. status: "danger",
  143. });
  144. return;
  145. }
  146. dataMapAction.remove(info.id);
  147. } else {
  148. let parent = dataMapAction.get(info.parent);
  149. parent.children.splice(info.childIndex, 1);
  150. dataMapAction.set(info.parent, parent);
  151. }
  152. if (info.id && info.id > 0) {
  153. httpPost(`/goodsSpecification/del/${info.id}`, {}, {}, true);
  154. }
  155. },
  156. });
  157. };
  158. // 取消
  159. const cancelInfo = info => {
  160. // 处理dataMap
  161. if (info.parent) {
  162. let parent = dataMapAction.get(info.parent);
  163. if (info.isNew) {
  164. parent.children = parent.children.filter((item, index) => {
  165. return index !== info.childIndex;
  166. });
  167. } else {
  168. parent.children = parent.children.map((item, index) => {
  169. if (index === info.childIndex) {
  170. return {
  171. ...item,
  172. edit: false,
  173. };
  174. } else {
  175. return item;
  176. }
  177. });
  178. }
  179. dataMapAction.set(info.parent, parent);
  180. } else if (info.isNew) {
  181. dataMapAction.remove(info.id);
  182. } else {
  183. dataMapAction.set(info.id, {
  184. ...info,
  185. edit: true,
  186. });
  187. }
  188. // 处理editMap
  189. if (info.id) {
  190. editMapAction.remove(info.id);
  191. } else {
  192. editMapAction.remove(`${info.parent}_${info.childIndex}`);
  193. }
  194. };
  195. // 保存
  196. const saveInfo = info => {
  197. let saveData = {};
  198. if (info.id) {
  199. saveData = editMapAction.get(info.id);
  200. } else {
  201. saveData = editMapAction.get(`${info.parent}_${info.childIndex}`);
  202. }
  203. delete saveData.isNew;
  204. if (saveData.parent) {
  205. let parent = dataMapAction.get(saveData.parent);
  206. parent.children[saveData.childIndex] = {
  207. ...saveData,
  208. edit: false,
  209. };
  210. dataMapAction.set(saveData.parent, parent);
  211. } else {
  212. dataMapAction.set(info.id, {
  213. ...saveData,
  214. edit: false,
  215. });
  216. }
  217. // 处理editMap
  218. if (info.id) {
  219. editMapAction.remove(info.id);
  220. } else {
  221. editMapAction.remove(`${info.parent}_${info.childIndex}`);
  222. }
  223. if (saveData.id && saveData.id > 0) {
  224. const data = {
  225. ...saveData,
  226. goodsId,
  227. };
  228. delete data.addIndex;
  229. addClassGoods(data);
  230. }
  231. };
  232. function getRandomId() {
  233. const id = 0 - Math.floor(Math.random() * 100 + 1);
  234. if (parentIds.includes(id)) {
  235. return getRandomId();
  236. } else {
  237. return id;
  238. }
  239. }
  240. // 添加新类
  241. const addFullReduction = info => {
  242. if (info) {
  243. // 二级分类
  244. let parentInfo = dataMapAction.get(info.parent);
  245. let hasNew = parentInfo.children.some(item => {
  246. return item.isNew;
  247. });
  248. if (!hasNew) {
  249. info = {
  250. parent: info.parent,
  251. name: "",
  252. amount: "",
  253. edit: true,
  254. isNew: true,
  255. childIndex: parentInfo.children.length,
  256. };
  257. parentInfo.children.push(info);
  258. dataMapAction.set(info.parent, parentInfo);
  259. editMapAction.set(`${info.parent}_${info.childIndex}`, info);
  260. }
  261. } else {
  262. // 一级分类
  263. let hasNew = Array.from(dataMap.values()).some(item => {
  264. return item.isNew;
  265. });
  266. if (!hasNew) {
  267. let newKey = getRandomId();
  268. let newInfo = {
  269. name: "",
  270. multiple: false,
  271. edit: true,
  272. isNew: true,
  273. children: [],
  274. id: newKey,
  275. };
  276. dataMapAction.set(newKey, newInfo);
  277. editMapAction.set(newKey, newInfo);
  278. }
  279. }
  280. };
  281. const saveItem = (info, index) => {
  282. return (
  283. <View Key={index}>
  284. <Layout style={styles.item}>
  285. <Layout style={[styles.text, styles.flexRow]}>
  286. {info.parent ? (
  287. <Text category="c1">添加{info.name}</Text>
  288. ) : (
  289. <Text category="s1">分类名:{info.name}</Text>
  290. )}
  291. {!!info.parent && (
  292. <Layout style={styles.money}>
  293. <Text category="c1">¥{info.amount}</Text>
  294. </Layout>
  295. )}
  296. {!info.parent && (
  297. <Layout style={styles.money}>
  298. <Text category="s1">{info.multiple ? "多选" : "单选"}</Text>
  299. </Layout>
  300. )}
  301. </Layout>
  302. <Button
  303. size="small"
  304. appearance="outline"
  305. onPress={() => editInfo(info)}
  306. >
  307. {editText}
  308. </Button>
  309. <Button
  310. size="small"
  311. status="danger"
  312. style={styles.buttonlast}
  313. onPress={() => delInfo(info)}
  314. >
  315. {delText}
  316. </Button>
  317. </Layout>
  318. {!info.parent && (
  319. <Button
  320. style={styles.addNew2}
  321. onPress={() =>
  322. addFullReduction({ addType: "2", parent: info.id, index })
  323. }
  324. >
  325. 添加规格
  326. </Button>
  327. )}
  328. </View>
  329. );
  330. };
  331. const editItem = info => {
  332. let editData = {};
  333. if (info.id) {
  334. editData = editMapAction.get(info.id);
  335. } else {
  336. editData = editMapAction.get(`${info.parent}_${info.childIndex}`);
  337. }
  338. return (
  339. <Layout style={styles.item}>
  340. <Layout style={[styles.text, styles.flexRow]}>
  341. <Text>{info.parent ? "规格" : "类名"}</Text>
  342. <Input
  343. size="small"
  344. defaultValue={editData.name}
  345. style={styles.input}
  346. key={`${info.id ? info.id : `${info.parent}_${info.childIndex}`}_0`}
  347. onChangeText={text => {
  348. if (info.id) {
  349. editMapAction.set(info.id, {
  350. ...editData,
  351. name: text,
  352. });
  353. } else {
  354. editMapAction.set(`${info.parent}_${info.childIndex}`, {
  355. ...editData,
  356. name: text,
  357. });
  358. }
  359. }}
  360. />
  361. {!!info.parent && (
  362. <>
  363. <Text>价钱</Text>
  364. <Input
  365. size="small"
  366. defaultValue={editData.amount}
  367. style={styles.input}
  368. key={`${
  369. info.id ? info.id : `${info.parent}_${info.childIndex}`
  370. }_1`}
  371. keyboardType="numeric"
  372. onChangeText={text => {
  373. if (info.id) {
  374. editMapAction.set(info.id, {
  375. ...editData,
  376. amount: text.toString(),
  377. });
  378. } else {
  379. editMapAction.set(`${info.parent}_${info.childIndex}`, {
  380. ...editData,
  381. amount: text.toString(),
  382. });
  383. }
  384. }}
  385. />
  386. </>
  387. )}
  388. {!info.parent && (
  389. <>
  390. <Text>是否多选</Text>
  391. <Toggle
  392. key="Toggle"
  393. checked={editData.multiple}
  394. onChange={checked => {
  395. editMapAction.set(info.id, {
  396. ...editData,
  397. multiple: checked,
  398. });
  399. }}
  400. />
  401. </>
  402. )}
  403. </Layout>
  404. <Button
  405. disabled={!editData.name || (!editData.amount && !!editData.parent)}
  406. size="small"
  407. onPress={() => saveInfo(info)}
  408. >
  409. {confirm}
  410. </Button>
  411. <Button
  412. size="small"
  413. appearance="outline"
  414. style={styles.buttonlast}
  415. onPress={() => cancelInfo(info)}
  416. >
  417. {cancel}
  418. </Button>
  419. </Layout>
  420. );
  421. };
  422. const renderItem = ({ item, index }) => {
  423. if (item.edit) {
  424. return editItem(item, index);
  425. }
  426. return saveItem(item, index);
  427. };
  428. return (
  429. <>
  430. <NavHeaderBar title="商品规格编辑" />
  431. <Layout style={[styles.lay]}>
  432. <ListComponent
  433. getInfo={getList}
  434. dataList={dataMap}
  435. renderItem={renderItem}
  436. style={styles.list}
  437. separatorStyle={styles.separatorStyle}
  438. showEmpty
  439. list$={list$}
  440. extraData={{ dataMap, editMap }}
  441. />
  442. <ActionButton
  443. buttonColor={theme["color-primary-500"]}
  444. onPress={addFullReduction}
  445. position="left"
  446. />
  447. </Layout>
  448. </>
  449. );
  450. }