schedules_edit.tsx 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. import { View, Text, Image, Switch, Input, ScrollView } from "@tarojs/components";
  2. import './schedules_edit.scss'
  3. import { useEffect, useState } from "react";
  4. import { useSelector } from "react-redux";
  5. import { createSchedule, getLabelsEvent, getSchedules } from "@/services/health";
  6. import { rpxToPx } from "@/utils/tools";
  7. import { getThemeColor } from "@/features/health/hooks/health_hooks";
  8. import Modal from "@/components/layout/Modal.weapp";
  9. import TimePicker from "@/features/common/TimePicker";
  10. import { AtSwipeAction } from "taro-ui"
  11. import Taro, { useRouter } from "@tarojs/taro";
  12. import showAlert from "@/components/basic/Alert";
  13. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  14. import StatusIndicator, { StatusType } from "../base/status_indicator";
  15. import NewButton, { NewButtonType } from "../base/new_button";
  16. import { MainColorType } from "@/context/themes/color";
  17. import { IconNotification, IconNotificationOff } from "@/components/basic/Icons";
  18. import NewHeader, { NewHeaderType } from "../components/new_header";
  19. let useRoute;
  20. let useNavigation;
  21. let scenario = '';
  22. if (process.env.TARO_ENV == 'rn') {
  23. useRoute = require("@react-navigation/native").useRoute
  24. useNavigation = require("@react-navigation/native").useNavigation
  25. }
  26. export default function SchedulesEdit() {
  27. let navigation, showActionSheetWithOptions;
  28. let router
  29. if (useNavigation) {
  30. navigation = useNavigation()
  31. }
  32. if (process.env.TARO_ENV == 'rn') {
  33. router = useRoute()
  34. }
  35. else {
  36. router = useRouter()
  37. }
  38. const selMode = router.params.mode;
  39. const [list, setList] = useState<any>([])
  40. const [labels, setLabels] = useState<any>([])
  41. const [showDel, setShowDel] = useState(false)
  42. const health = useSelector((state: any) => state.health);
  43. const [showTimePicker, setShowTimePicker] = useState(false)
  44. const [selItem, setSelItem] = useState<any>(null)
  45. const [editIndex, setEditIndex] = useState({ row: -1, index: -1 })
  46. const [delIds, setDelIds] = useState<any>([])
  47. useEffect(() => {
  48. schedules()
  49. }, [])
  50. global.refreshSchedules = () => {
  51. schedules()
  52. }
  53. function schedules() {
  54. let windows = ''
  55. switch (selMode) {
  56. case 'FAST':
  57. windows = 'FAST,EAT';
  58. break
  59. case 'EAT':
  60. windows = 'EAT,FAST';
  61. break
  62. case 'SLEEP':
  63. windows = 'SLEEP,ACTIVE';
  64. break
  65. case 'ACTIVE':
  66. windows = 'ACTIVE,SLEEP';
  67. break
  68. case 'DAY':
  69. windows = 'DAY,NIGHT';
  70. break
  71. case 'NIGHT':
  72. windows = 'NIGHT,DAY';
  73. break
  74. }
  75. getSchedules({ window: windows }).then(res => {
  76. if ((res as any).data && (res as any).data.length > 0) {
  77. // setList((res as any).data)
  78. let grouped: any = {};
  79. (res as any).data.forEach(item => {
  80. const window = item.window;
  81. if (!grouped[window]) {
  82. grouped[window] = { window: window, list: [] };
  83. }
  84. grouped[window].list.push(item);
  85. });
  86. // console.log(Object.values(grouped))
  87. setList(Object.values(grouped))
  88. }
  89. }).catch(e => {
  90. })
  91. getLabelsEvent({ window: health.mode }).then(res => {
  92. setLabels((res as any).labels)
  93. })
  94. }
  95. function changeTime(item) {
  96. setSelItem(item)
  97. setShowTimePicker(true)
  98. }
  99. function modalContent() {
  100. const strTime = selItem.time
  101. var title = selItem.title
  102. var color = getThemeColor(selItem.window)
  103. return <TimePicker time={strTime}
  104. color={color}
  105. title={title}
  106. confirm={(e) => {
  107. selItem.time = e
  108. setSelItem(selItem)
  109. setShowTimePicker(false)
  110. orderList(list)
  111. // confirmPickerTime(e)
  112. }}
  113. cancel={() => {
  114. setShowTimePicker(false)
  115. }} />
  116. }
  117. function orderList(list) {
  118. var array = JSON.parse(JSON.stringify(list))
  119. array.map(item => {
  120. if (item.window == 'EAT' || item.window == 'ACTIVE') {
  121. // 自定义排序函数
  122. const sortedArray = item.list.sort((a, b) => {
  123. // 如果 a 没有 time 字段,排在前面
  124. if (!a.time && !b.time) return 0; // 都没有时,返回相等
  125. if (!a.time) return -1; // a 没有 time,排在前面
  126. if (!b.time) return 1; // b 没有 time,排在前面
  127. // 比较时间
  128. return a.time.localeCompare(b.time);
  129. });
  130. item.list = sortedArray
  131. }
  132. })
  133. setList(array)
  134. }
  135. function tapDone() {
  136. var array: any = []
  137. list.map((obj) => {
  138. obj.list.map(item => {
  139. array.push({
  140. id: item.id,
  141. time: item.time,
  142. event: item.event,
  143. title: item.title,
  144. reminder: item.reminder
  145. })
  146. })
  147. })
  148. createSchedule({
  149. schedules: array,
  150. delete_ids: delIds
  151. }).then(res => {
  152. if ((res as any).result) {
  153. global.refreshWindow()
  154. if (global.refreshSchedules) {
  155. global.refreshSchedules()
  156. }
  157. if (global.tempRefresh) {
  158. global.tempRefresh()
  159. }
  160. if (global.refreshSchedules2) {
  161. global.refreshSchedules2()
  162. }
  163. if (process.env.TARO_ENV == 'weapp') {
  164. Taro.navigateBack()
  165. }
  166. }
  167. else {
  168. showAlert({
  169. title: '弹窗标题',
  170. content: '冲突描述',
  171. showCancel: false,
  172. confirm: () => {
  173. jumpPage(`./schedules_conflict?schedules=${JSON.stringify((res as any).schedules)}&errors=${JSON.stringify((res as any).error_messages)}`)
  174. }
  175. })
  176. }
  177. })
  178. }
  179. function delItem(index, i) {
  180. var array = JSON.parse(JSON.stringify(list))
  181. var ids = JSON.parse(JSON.stringify(delIds))
  182. ids.push(array[index].list[i].id)
  183. array[index].list.splice(i, 1)
  184. setList(array)
  185. setDelIds(ids)
  186. }
  187. function reminder(obj) {
  188. if (obj.specific_time || health.mode == 'DAY' || health.mode == 'NIGHT') {
  189. return <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
  190. {
  191. obj.reminder ? <IconNotification color={MainColorType.g03} width={rpxToPx(28)} /> : <IconNotificationOff color={MainColorType.g03} width={rpxToPx(28)} />
  192. }
  193. <View style={{ width: rpxToPx(12) }} />
  194. <Switch checked={obj.reminder}
  195. color={getThemeColor(obj.window)}
  196. onChange={e => {
  197. if (process.env.TARO_ENV == 'weapp') {
  198. e.stopPropagation()
  199. }
  200. obj.reminder = e.detail.value;
  201. setList([...list])
  202. }} />
  203. </View>
  204. }
  205. return <View />
  206. }
  207. function editName(item, obj, index, i) {
  208. if ((item.window == 'EAT' || item.window == 'ACTIVE') &&
  209. !(editIndex.row == index && editIndex.index == i)) {
  210. return <View>
  211. <NewButton type={NewButtonType.link}
  212. title="更改"
  213. onClick={() => {
  214. setSelItem(obj)
  215. setEditIndex({
  216. row: index,
  217. index: i
  218. })
  219. }}
  220. />
  221. </View>
  222. }
  223. return <View />
  224. }
  225. return <View className='schedule_list_bg'>
  226. <ScrollView enableFlex style={{ height: Taro.getWindowInfo().screenHeight - 220 }} scrollY>
  227. <NewHeader title="日程设置" type={NewHeaderType.left} />
  228. <View style={{ display: 'flex', flexDirection: 'column' }}>
  229. {
  230. list.map((item, index) => {
  231. return <View key={index} style={{ display: 'flex', flexDirection: 'column', marginBottom: rpxToPx(36) }}>
  232. {
  233. item.list.map((obj, i) => {
  234. return <AtSwipeAction key={i * 100}
  235. isOpened={false}
  236. autoClose
  237. disabled={item.window != 'EAT' && item.window != 'ACTIVE'}
  238. options={[
  239. {
  240. text: '删除',
  241. style: {
  242. backgroundColor: '#FF4949'
  243. }
  244. }
  245. ]}
  246. onClick={() => {
  247. if (item.window == 'ACTIVE' || item.window == 'EAT') {
  248. if (item.list.length == 1) {
  249. Taro.showToast({
  250. title: '至少保留一项',
  251. icon: 'none'
  252. })
  253. return;
  254. }
  255. }
  256. showAlert({
  257. title: '删除',
  258. content: '确认删除此计划',
  259. showCancel: true,
  260. cancel: () => {
  261. console.log('cancel')
  262. },
  263. confirm: () => {
  264. delItem(index, i)
  265. }
  266. })
  267. }}
  268. >
  269. <View className='schedule_item' style={{ width: rpxToPx(750), boxSizing: 'border-box' }}>
  270. <View style={{ display: 'flex', flexDirection: 'column', justifyContent: 'flex-start', flex: 1 }}>
  271. <View className='item_left2'>
  272. <StatusIndicator type={StatusType.normal} color={getThemeColor(obj.window)} />
  273. {
  274. editIndex.row == index && editIndex.index == i ?
  275. <Input className='item_name' style={{ flex: 1 }}
  276. value={selItem.title}
  277. autoFocus={true}
  278. focus={true}
  279. onBlur={() => {
  280. setEditIndex({
  281. row: -1,
  282. index: -1
  283. })
  284. }}
  285. onInput={(e) => {
  286. var temp = JSON.parse(JSON.stringify(selItem))
  287. temp.title = e.detail.value
  288. obj.title = e.detail.value
  289. setSelItem(temp)
  290. }} /> : <Text className='item_name'>{obj.title}</Text>
  291. }
  292. {/* {
  293. (item.window == 'EAT' || item.window == 'ACTIVE') &&
  294. !(editIndex.row == index && editIndex.index == i) &&
  295. <Image src={require('@assets/_health/edit.png')}
  296. className="edit_icon"
  297. onClick={(e) => {
  298. if (process.env.TARO_ENV == 'weapp') {
  299. e.stopPropagation()
  300. }
  301. setSelItem(obj)
  302. setEditIndex({
  303. row: index,
  304. index: i
  305. })
  306. }}
  307. />
  308. } */}
  309. </View>
  310. {
  311. obj.specific_time && <View className="h22" style={{ color: MainColorType.g02 }}>{obj.time}</View>
  312. }
  313. </View>
  314. {
  315. router.params.type == 'reminder' ? reminder(obj) : editName(item, obj, index, i)
  316. }
  317. {/* {router.params.type == 'reminder' && (obj.specific_time || health.mode == 'DAY' || health.mode == 'NIGHT') && <Switch checked={obj.reminder}
  318. color={getThemeColor(obj.window)}
  319. onChange={e => {
  320. if (process.env.TARO_ENV == 'weapp') {
  321. e.stopPropagation()
  322. }
  323. obj.reminder = e.detail.value;
  324. setList([...list])
  325. }} />} */}
  326. {
  327. i < item.list.length - 1 && <View className='border_footer_line' />
  328. }
  329. </View>
  330. </AtSwipeAction>
  331. })
  332. }
  333. </View>
  334. })
  335. }
  336. </View>
  337. </ScrollView>
  338. <View className="main_footer">
  339. <NewButton
  340. type={NewButtonType.fill}
  341. title="完成"
  342. color={getThemeColor(health.mode)}
  343. width={rpxToPx(670)}
  344. height={rpxToPx(96)}
  345. onClick={tapDone}
  346. />
  347. </View>
  348. {/* <View className="edit_footer_btn" style={{ color: getThemeColor(health.mode), backgroundColor: getThemeColor(health.mode) + '33' }} onClick={tapDone}>完成</View> */}
  349. {
  350. showTimePicker && <Modal
  351. testInfo={null}
  352. dismiss={() => {
  353. setShowTimePicker(false)
  354. }}
  355. confirm={() => { }}>
  356. {
  357. modalContent()
  358. }
  359. </Modal>
  360. }
  361. </View>
  362. }