memoManageMixin.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. import {
  2. getMemoList,
  3. getMemoDetail,
  4. addMemo,
  5. updateMemo,
  6. deleteMemo,
  7. deleteMemoBatch,
  8. getMemoMonth,
  9. } from '@/api/memoManage.js'
  10. import { getAuditTaskList } from '@/api/auditInitiation.js'
  11. import moment from 'moment'
  12. export const memoManageMixin = {
  13. data() {
  14. // 表格列配置
  15. const tableColumns = [
  16. {
  17. prop: 'reminderType',
  18. label: '提醒',
  19. width: 80,
  20. headerAlign: 'center',
  21. align: 'center',
  22. slotName: 'reminder-type',
  23. },
  24. {
  25. prop: 'task',
  26. label: '成本监审任务',
  27. width: 160,
  28. headerAlign: 'center',
  29. align: 'center',
  30. },
  31. {
  32. prop: 'memoDate',
  33. label: '日期',
  34. width: 120,
  35. headerAlign: 'center',
  36. align: 'center',
  37. },
  38. {
  39. prop: 'title',
  40. label: '标题',
  41. width: 120,
  42. headerAlign: 'center',
  43. align: 'center',
  44. },
  45. {
  46. prop: 'content',
  47. label: '内容',
  48. minWidth: 200,
  49. headerAlign: 'center',
  50. align: 'center',
  51. },
  52. {
  53. prop: 'action',
  54. label: '操作',
  55. width: 150,
  56. headerAlign: 'center',
  57. align: 'center',
  58. slotName: 'action-buttons',
  59. showOverflowTooltip: false,
  60. },
  61. ]
  62. // 按项目查询标签页的表格列配置(项目名称列宽更大)
  63. const projectTableColumns = [
  64. ...tableColumns.map((col) => {
  65. if (col.prop === 'projectName') {
  66. return { ...col, width: 220 }
  67. } else if (col.prop === 'title') {
  68. return { ...col, width: 200 }
  69. } else if (col.prop === 'content') {
  70. return { ...col, minWidth: 300 }
  71. }
  72. return col
  73. }),
  74. ]
  75. return {
  76. type: 'index', // 列表类型:index-首页列表,memoManage-备忘录列表
  77. dictData: {
  78. reminderType: [],
  79. },
  80. activeTab: 'calendar',
  81. selectedDate: new Date(),
  82. today: new Date(),
  83. // 表格配置
  84. tableColumns,
  85. projectTableColumns,
  86. searchParams: {
  87. year: '',
  88. projectId: '',
  89. content: '',
  90. startTime: '',
  91. endTime: '',
  92. page: 1,
  93. pageSize: 50,
  94. },
  95. listTotal: 0,
  96. calendarData: {},
  97. memoList: [],
  98. formTitle: '',
  99. formDisabled: false,
  100. formRules: {
  101. projectId: [
  102. {
  103. required: true,
  104. message: '请选择成本监审项目',
  105. trigger: 'change',
  106. },
  107. ],
  108. title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
  109. content: [{ required: true, message: '请输入内容', trigger: 'blur' }],
  110. memoDate: [
  111. { required: true, message: '请选择日期', trigger: 'change' },
  112. ],
  113. startTime: [
  114. { required: true, message: '请选择开始时间', trigger: 'change' },
  115. ],
  116. endTime: [
  117. { required: true, message: '请选择结束时间', trigger: 'change' },
  118. ],
  119. reminderType: [
  120. { required: true, message: '请选择提醒方式', trigger: 'change' },
  121. ],
  122. // attachmentName: [
  123. // { required: true, message: '请上传附件', trigger: 'change' },
  124. // ],
  125. },
  126. editForm: {
  127. attachmentName: '',
  128. attachmentSize: 0,
  129. attachmentUrl: '',
  130. content: '',
  131. memoDate: '',
  132. projectId: 0,
  133. reminderType: '0',
  134. task: '',
  135. startTime: '',
  136. endTime: '',
  137. title: '',
  138. },
  139. // 时间数据字段已移除,改为直接使用editForm中的startTime和endTime
  140. fileList: [],
  141. isEditDialogOpen: false,
  142. auditTaskList: [],
  143. lunarInfo: {},
  144. }
  145. },
  146. computed: {
  147. // 获取指定日期的任务列表
  148. getTasksByDate() {
  149. return (date) => {
  150. const dateStr = moment(date).format('YYYY-MM-DD')
  151. // return this.memoList.filter((task) => task.memoDate === dateStr)
  152. return this.calendarData[dateStr] || []
  153. }
  154. },
  155. },
  156. watch: {
  157. // // 监听选中日期变化,更新搜索参数
  158. selectedDate: {
  159. handler(newVal) {
  160. if (newVal) {
  161. this.lunarInfo = this.getLunarInfo(this.selectedDate)
  162. this.searchParams.memoDate = moment(newVal).format('YYYY-MM-DD')
  163. this.handleSearch()
  164. }
  165. },
  166. deep: true,
  167. },
  168. },
  169. methods: {
  170. getMemoMonth() {
  171. let _url = ''
  172. if (this.type === 'memoManage') {
  173. _url = '/api/costProjectMemo/v1/getDataMonth'
  174. } else {
  175. _url = '/api/costProjectMemo/v1/getIndexDataMonth'
  176. }
  177. //将 month 设置为当前月的第一天
  178. let month = moment().startOf('month').format('YYYY-MM-DD')
  179. getMemoMonth(_url, {
  180. month,
  181. }).then((res) => {
  182. this.calendarData = res.value || {}
  183. })
  184. },
  185. // 优化后的获取详情方法,不再接收单个item参数
  186. async getTasksByDateList() {
  187. if (this.memoList.length > 0) {
  188. try {
  189. // 使用Promise.all并行获取所有备忘录的详情
  190. const detailPromises = this.memoList.map(async (memo, index) => {
  191. try {
  192. const params = {
  193. id: memo.id,
  194. }
  195. const res = await getMemoDetail(params)
  196. if (res.code === 200 && res.value) {
  197. // 更新原数组中的数据
  198. const memoIndex = this.memoList.findIndex(
  199. (item) => item.id === memo.id
  200. )
  201. if (memoIndex !== -1) {
  202. this.memoList[memoIndex] = {
  203. ...this.memoList[memoIndex],
  204. ...res.value,
  205. }
  206. }
  207. // 返回更新后的数据
  208. return {
  209. ...memo,
  210. ...res.value,
  211. }
  212. }
  213. return memo // 如果获取失败,返回原数据
  214. } catch (err) {
  215. console.error('获取备忘录详情失败:', memo.id, err)
  216. return memo // 发生错误时返回原数据
  217. }
  218. })
  219. // 等待所有详情请求完成
  220. this.memoList = await Promise.all(detailPromises)
  221. } catch (error) {
  222. console.error('批量获取备忘录详情失败:', error)
  223. // 发生错误时返回原始列表
  224. }
  225. }
  226. },
  227. // 根据提醒类型获取对应的颜色
  228. getReminderTypeColor(type) {
  229. const colorMap = {
  230. 1: '#c0c4cc', // 不提醒 - 浅灰色
  231. 2: '#f56c6c', // 提前1小时 - 红色
  232. 3: '#e6a23c', // 提前2小时 - 橙色
  233. 4: '#e6a23c', // 提前3小时 - 橙色
  234. 5: '#73c0de', // 提前1天 - 天蓝色
  235. 6: '#98fb98', // 提前2天 - 浅绿色
  236. 7: '#c0c4cc', // 提前3天 - 浅灰色
  237. }
  238. return colorMap[type] || '#c0c4cc'
  239. },
  240. // 时间处理逻辑已移除,改为直接使用editForm中的startTime和endTime
  241. // 优化 saveFiles 方法
  242. saveFiles(data) {
  243. console.log('saveFiles', data)
  244. this.fileList = data
  245. this.editForm.attachmentName = data[0].fileName
  246. this.editForm.attachmentSize = data[0].fileSize
  247. this.editForm.attachmentUrl = data[0].savePath
  248. },
  249. // 优化 removeFile 方法
  250. removeFile(index, removedFile, currentFiles) {
  251. this.fileList = []
  252. this.editForm.attachmentName = ''
  253. this.editForm.attachmentSize = 0
  254. this.editForm.attachmentUrl = ''
  255. },
  256. // 获取监审任务列表
  257. async getAuditTaskList() {
  258. try {
  259. let params = {
  260. projectName: '',
  261. }
  262. const res = await getAuditTaskList(params)
  263. console.log('监审任务列表数据:', res)
  264. if (res.code == 200) {
  265. this.auditTaskList = res.value || []
  266. }
  267. } catch (error) {
  268. console.error('获取监审任务列表数据失败:', error)
  269. }
  270. },
  271. // 日历选择日期
  272. handleDateClick(date, data) {
  273. const dateStr = moment(date).format('YYYY-MM-DD')
  274. // const tasks = this.memoList.filter((task) => task.memoDate === dateStr)
  275. this.searchParams.memoDate = dateStr
  276. this.handleSearch()
  277. // if (tasks.length > 0) {
  278. // this.searchParams.startTime = dateStr
  279. // this.searchParams.endTime = dateStr
  280. // }
  281. },
  282. // 获取提醒类型的文本描述
  283. getReminderTypeText(type) {
  284. const textMap = {
  285. 0: '不提醒',
  286. 1: '提前1小时',
  287. 2: '提前2小时',
  288. 3: '提前3小时',
  289. 4: '提前1天',
  290. 5: '提前2天',
  291. 6: '提前3天',
  292. }
  293. return textMap[type] || '不提醒'
  294. },
  295. /**
  296. * 获取指定日期的农历信息,包括节日和节气信息
  297. * @param {Date} date - 日期对象
  298. * @returns {Object|null} 包含公历农历详细信息的对象,如果超出范围则返回基本信息对象
  299. */
  300. getLunarInfo(date) {
  301. try {
  302. // 从日期对象获取年月日
  303. const year = date.getFullYear()
  304. const month = date.getMonth() + 1 // 月份从1开始
  305. const day = date.getDate()
  306. // 检查是否在solar2lunar支持的范围内 (1900.1.31~3000.12.31)
  307. const isInRange =
  308. (year > 1900 ||
  309. (year === 1900 && month > 1) ||
  310. (year === 1900 && month === 1 && day >= 31)) &&
  311. (year < 3000 ||
  312. (year === 3000 && month < 12) ||
  313. (year === 3000 && month === 12 && day <= 31))
  314. if (window.calendar && window.calendar.solar2lunar && isInRange) {
  315. // 在范围内,调用calendar-converter.js中的solar2lunar函数
  316. const lunarDate = window.calendar.solar2lunar(year, month, day)
  317. if (lunarDate !== -1) {
  318. return lunarDate || { IDayCn: '' }
  319. }
  320. }
  321. // 超出范围时,返回基本日期信息
  322. console.warn(
  323. `日期 ${year}-${month}-${day} 超出了农历转换支持的范围(1900.1.31~3000.12.31)`
  324. )
  325. return this._getBasicDateInfo(year, month, day)
  326. } catch (error) {
  327. // 出错时也返回基本日期信息
  328. return this._getBasicDateInfo(
  329. date.getFullYear(),
  330. date.getMonth() + 1,
  331. date.getDate()
  332. )
  333. }
  334. },
  335. /**
  336. * 获取基本的日期信息,当超出solar2lunar范围时使用
  337. * @private
  338. * @param {number} year - 阳历年
  339. * @param {number} month - 阳历月
  340. * @param {number} day - 阳历日
  341. * @returns {Object} 基本日期信息对象
  342. */
  343. _getBasicDateInfo(year, month, day) {
  344. const dateStr = `${year}-${month}-${day}`
  345. // 创建基本信息对象,格式尽量与solar2lunar返回的一致
  346. return {
  347. date: dateStr,
  348. lunarDate: '超出转换范围',
  349. festival: null,
  350. lunarFestival: null,
  351. lYear: year,
  352. lMonth: month,
  353. lDay: day,
  354. Animal: null,
  355. IMonthCn: '',
  356. IDayCn: '',
  357. cYear: year,
  358. cMonth: month,
  359. cDay: day,
  360. gzYear: '',
  361. gzMonth: '',
  362. gzDay: '',
  363. isToday: false,
  364. isLeap: false,
  365. nWeek: new Date(year, month - 1, day).getDay() || 7, // 周日为7
  366. ncWeek: `星期${
  367. ['日', '一', '二', '三', '四', '五', '六'][
  368. new Date(year, month - 1, day).getDay()
  369. ]
  370. }`,
  371. isTerm: false,
  372. Term: null,
  373. astro: '',
  374. outOfRange: true, // 标记为超出范围
  375. }
  376. },
  377. // 上一个月
  378. handlePrevMonth() {
  379. this.selectedDate = moment(this.selectedDate)
  380. .subtract(1, 'month')
  381. .toDate()
  382. },
  383. // 下一个月
  384. handleNextMonth() {
  385. this.selectedDate = moment(this.selectedDate).add(1, 'month').toDate()
  386. },
  387. // 获取备忘录列表
  388. async handleSearch() {
  389. try {
  390. let params = {
  391. ...this.searchParams,
  392. // memoDate:''
  393. }
  394. let _url = ''
  395. if (this.type === 'memoManage') {
  396. _url = '/api/costProjectMemo/v1/pageList'
  397. } else {
  398. _url = '/api/costProjectMemo/v1/pageIndexList'
  399. // _url = '/api/costProjectMemo/v1/getDataMonth'
  400. }
  401. if (this.activeTab == 'project') {
  402. delete params.memoDate
  403. } else if (this.activeTab == 'calendar') {
  404. params.memoDate = this.searchParams.memoDate
  405. delete params.year
  406. }
  407. const res = await getMemoList(_url, params)
  408. if (res.value && res.value.records.length > 0) {
  409. this.memoList = res.value.records || []
  410. // 只处理day字段,不调用详情接口
  411. this.memoList.forEach((item) => {
  412. const date = new Date(item.memoDate)
  413. item.day = date.getDate()
  414. })
  415. // 在列表数据设置完成后,只调用一次详情接口获取所有需要的详情
  416. await this.getTasksByDateList()
  417. this.listTotal = res.value.total || 0
  418. } else {
  419. this.memoList = []
  420. this.listTotal = 0
  421. }
  422. } catch (error) {
  423. console.error('获取数据失败:', error)
  424. }
  425. },
  426. handleReset() {
  427. this.searchParams = {
  428. page: 1,
  429. pageSize: 10,
  430. startTime: '',
  431. endTime: '',
  432. year: '',
  433. projectId: '',
  434. content: '',
  435. }
  436. this.handleSearch()
  437. },
  438. handleCurrentChange(val) {
  439. this.searchParams.pageNum = val
  440. this.handleSearch()
  441. },
  442. handleSizeChange(val) {
  443. this.searchParams.pageSize = val
  444. this.handleSearch()
  445. },
  446. // 处理分页变化
  447. handlePaginationChange({ currentPage, pageSize }) {
  448. this.searchParams.page = currentPage
  449. this.searchParams.pageSize = pageSize
  450. this.handleSearch()
  451. },
  452. // 初始化日历相关数据
  453. initCalendarData(type) {
  454. this.type = type
  455. this.selectedDate = new Date()
  456. this.lunarInfo = this.getLunarInfo(this.selectedDate)
  457. this.getMemoMonth()
  458. // this.handleSearch(num)
  459. },
  460. onTabChange(tab) {
  461. this.searchParams.startTime = ''
  462. this.searchParams.endTime = ''
  463. this.searchParams.year = ''
  464. this.searchParams.projectId = ''
  465. this.searchParams.content = ''
  466. this.searchParams.page = 1
  467. if (tab.name == 'calendar') {
  468. this.setCalendarTitle()
  469. this.handleSearch()
  470. } else {
  471. this.handleSearch()
  472. }
  473. },
  474. // prevMonth() {
  475. // console.log('日历切换:上一个月')
  476. // if (this.currentMonth === 1) {
  477. // this.currentYear--
  478. // this.currentMonth = 12
  479. // } else {
  480. // this.currentMonth--
  481. // }
  482. // this.setCalendarTitle()
  483. // },
  484. // nextMonth() {
  485. // console.log('日历切换:下一个月')
  486. // if (this.currentMonth === 12) {
  487. // this.currentYear++
  488. // this.currentMonth = 1
  489. // } else {
  490. // this.currentMonth++
  491. // }
  492. // this.setCalendarTitle()
  493. // },
  494. handleAdd() {
  495. this.getAuditTaskList()
  496. this.formTitle = '添加备忘录'
  497. this.formDisabled = false
  498. this.editForm = {
  499. attachmentName: '',
  500. attachmentSize: 0,
  501. attachmentUrl: '',
  502. content: '',
  503. memoDate: '',
  504. projectId: '',
  505. reminderType: '0',
  506. task: '',
  507. startTime: '',
  508. endTime: '',
  509. title: '',
  510. }
  511. this.fileList = []
  512. this.isEditDialogOpen = true
  513. },
  514. // 获取备忘录详情
  515. async getMemoDetail(row) {
  516. this.getAuditTaskList()
  517. try {
  518. let params = {
  519. id: row.id,
  520. }
  521. const res = await getMemoDetail(params)
  522. if (res.code == 200) {
  523. // 处理时间范围
  524. let startTime = ''
  525. let endTime = ''
  526. const data = { ...row, ...res.value }
  527. if (data.timePeriod) {
  528. const timeRange = data.timePeriod.split('-')
  529. if (timeRange.length === 2) {
  530. startTime = timeRange[0]
  531. endTime = timeRange[1]
  532. }
  533. }
  534. this.editForm = {
  535. ...data,
  536. startTime: startTime,
  537. endTime: endTime,
  538. }
  539. // 删除timePeriod字段避免混淆
  540. delete this.editForm.timePeriod
  541. this.fileList = this.editForm.attachmentUrl
  542. ? [res.value.attachmentUrl]
  543. : []
  544. this.isEditDialogOpen = true
  545. }
  546. } catch (error) {
  547. console.error('获取详情数据失败:', error)
  548. }
  549. },
  550. handleView(row) {
  551. this.formTitle = '查看备忘录详情'
  552. this.formDisabled = true
  553. this.getMemoDetail(row)
  554. },
  555. handleEdit(row) {
  556. this.formTitle = '编辑备忘录'
  557. this.formDisabled = false
  558. this.getMemoDetail(row)
  559. },
  560. handleDelete(row) {
  561. this.$confirm('确定要删除该数据吗?', '提示', {
  562. confirmButtonText: '确定',
  563. cancelButtonText: '取消',
  564. type: 'warning',
  565. })
  566. .then(async () => {
  567. const response = await deleteMemo(row.id)
  568. this.$message.success('删除成功')
  569. // 重新加载数据
  570. this.handleSearch()
  571. })
  572. .catch(() => {
  573. this.$message.info('已取消删除')
  574. })
  575. },
  576. handleSave() {
  577. this.$refs['ruleForm'].validate((valid) => {
  578. if (valid) {
  579. let task = this.auditTaskList.find(
  580. (item) => item.projectId === this.editForm.projectId
  581. )
  582. const formData = {
  583. ...this.editForm,
  584. areaCode: task.areaCode,
  585. }
  586. // 合并开始时间和结束时间为timePeriod格式
  587. formData.timePeriod = `${formData.startTime}-${formData.endTime}`
  588. // 删除单独的时间字段,避免后端接收多余数据
  589. delete formData.startTime
  590. delete formData.endTime
  591. if (formData.id) {
  592. this.updateMemo(formData)
  593. } else {
  594. this.addMemo(formData)
  595. }
  596. } else {
  597. console.log('表单验证失败')
  598. }
  599. })
  600. },
  601. // 添加备忘录
  602. async addMemo(formData) {
  603. try {
  604. const res = await addMemo(formData)
  605. if (res.code == 200) {
  606. this.$message.success('添加成功')
  607. this.handleSearch()
  608. this.isEditDialogOpen = false
  609. }
  610. } catch (error) {
  611. console.error('添加失败:', error)
  612. this.$message.error('添加失败')
  613. }
  614. },
  615. // 更新备忘录
  616. async updateMemo(formData) {
  617. delete formData.day
  618. delete formData.projectName
  619. try {
  620. const res = await updateMemo(formData)
  621. if (res.code == 200) {
  622. this.$message.success('更新成功')
  623. this.handleSearch()
  624. this.isEditDialogOpen = false
  625. }
  626. } catch (error) {
  627. console.error('更新失败:', error)
  628. this.$message.error('更新失败')
  629. }
  630. },
  631. // 设置日历标题
  632. setCalendarTitle() {
  633. // 可以在这里添加设置日历标题的逻辑
  634. let lunarInfo = this.lunarInfo
  635. return `${lunarInfo.cYear}年${lunarInfo.cMonth}月 农历${lunarInfo.gzYear}年【${lunarInfo.Animal}】`
  636. },
  637. },
  638. }