create-message.tsx 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. import OPopup from '@/components/o-popup'
  2. import { sendType } from '@/constant'
  3. import request from '@/helpers/request'
  4. import { getOssUploadUrl } from '@/state'
  5. import dayjs from 'dayjs'
  6. import umiRequest from 'umi-request'
  7. import {
  8. ActionSheet,
  9. Button,
  10. Cell,
  11. CellGroup,
  12. closeToast,
  13. DatePicker,
  14. Field,
  15. Icon,
  16. Image,
  17. PickerGroup,
  18. Popup,
  19. showLoadingToast,
  20. showToast,
  21. TimePicker,
  22. Uploader
  23. } from 'vant'
  24. import { computed, defineComponent, onMounted, reactive } from 'vue'
  25. import styles from './index.module.less'
  26. import SelectSned from './select-sned'
  27. import iconStudent from '@common/images/icon_student.png'
  28. import iconTeacher from '@common/images/icon_teacher.png'
  29. import iconJiaoFu from '@common/images/icon_jiaofu.png'
  30. import ODialog from '@/components/o-dialog'
  31. import OSticky from '@/components/o-sticky'
  32. import { useRoute, useRouter } from 'vue-router'
  33. export default defineComponent({
  34. name: 'create-message',
  35. setup() {
  36. const router = useRouter()
  37. const route = useRoute()
  38. const forms = reactive({
  39. id: route.query.id,
  40. type: 'ADD',
  41. bucket: 'i-m',
  42. sendStatus: false,
  43. sendType: 'IMMEDIATELY' as any,
  44. textMessage: null,
  45. sendTime: null as any,
  46. sendTimeStatus: false,
  47. maxDate: dayjs(new Date()).add(60, 'day').toDate(),
  48. currentDate: [],
  49. currentTime: [dayjs().format('HH'), dayjs().format('mm')],
  50. attachments: [] as any, //群发消息附件
  51. receives: [] as any, // 群发消息对象
  52. selectStatus: false,
  53. selectList: {} as any, // 选中发送的信息
  54. delSelectItem: {} as any,
  55. delStatus: false,
  56. sureLoading: false,
  57. updateLoading: false,
  58. closeLoading: false
  59. })
  60. const beforeRead = (file: any) => {
  61. // console.log(file, 'beforeRead')
  62. const isLt2M = file.size / 1024 / 1024 < 5
  63. if (!isLt2M) {
  64. showToast(`上传文件大小不能超过 5MB`)
  65. return false
  66. }
  67. return true
  68. }
  69. const beforeDelete = (file: any, detail: { index: any }) => {
  70. // this.dataModel.splice(detail.index, 1)
  71. return true
  72. }
  73. const afterRead = async (file: any, detail: any) => {
  74. try {
  75. file.status = 'uploading'
  76. file.message = '上传中...'
  77. await uploadFile(file)
  78. } catch (error) {
  79. //
  80. closeToast()
  81. }
  82. }
  83. const uploadFile = async (files: any) => {
  84. // 上传文件
  85. try {
  86. console.log(files, 'files')
  87. const file = files.file
  88. // 获取签名
  89. const signUrl = '/api-school/open/getUploadSign'
  90. const tempName = file.name || ''
  91. const fileName = '/i-m/' + (tempName && tempName.replace(/ /gi, '_'))
  92. const key = new Date().getTime() + fileName
  93. // showLoadingToast({
  94. // message: '加载中...',
  95. // forbidClick: true,
  96. // loadingType: 'spinner',
  97. // duration: 0
  98. // })
  99. const res = await request.post(signUrl, {
  100. hideLoading: true,
  101. data: {
  102. filename: fileName,
  103. bucketName: forms.bucket,
  104. postData: {
  105. filename: fileName,
  106. acl: 'public-read',
  107. key: key,
  108. unknowValueField: []
  109. }
  110. }
  111. })
  112. // setTimeout(() => {
  113. // }, 100)
  114. const obj = {
  115. policy: res.data.policy,
  116. signature: res.data.signature,
  117. key: key,
  118. KSSAccessKeyId: res.data.kssAccessKeyId,
  119. acl: 'public-read',
  120. name: fileName
  121. }
  122. const formData = new FormData()
  123. for (const key in obj) {
  124. formData.append(key, obj[key])
  125. }
  126. formData.append('file', file, fileName)
  127. await umiRequest(getOssUploadUrl(forms.bucket), {
  128. method: 'POST',
  129. data: formData
  130. })
  131. // console.log(getOssUploadUrl(state.bucket) + key)
  132. const uploadUrl = getOssUploadUrl(forms.bucket) + key
  133. // closeToast()
  134. // state.fileList.push({ url: uploadUrl })
  135. files.url = uploadUrl
  136. files.status = 'done'
  137. } catch (error) {
  138. files.status = 'failed'
  139. // closeToast()
  140. console.log(error, 'uploadFile')
  141. }
  142. }
  143. const onSubmit = async () => {
  144. try {
  145. if (!forms.sendType) {
  146. showToast('请选择发送方式')
  147. return
  148. }
  149. if (!forms.textMessage) {
  150. showToast('请输入发送内容')
  151. return
  152. }
  153. if (forms.receives.length <= 0) {
  154. showToast('请选择发送对象')
  155. return
  156. }
  157. const tempAttachments: any = []
  158. forms.attachments.forEach((item: any) => {
  159. tempAttachments.push({
  160. imgUrl: item.url,
  161. imgMessage: item.url
  162. })
  163. })
  164. const tempReceives: any = []
  165. forms.receives.forEach((item: any) => {
  166. tempReceives.push({
  167. receiveType: item.receiveType,
  168. receiveId: item.receiveId
  169. })
  170. })
  171. const params: any = {
  172. sendType: forms.sendType,
  173. textMessage: forms.textMessage,
  174. attachments: tempAttachments,
  175. receives: tempReceives,
  176. sendTime: forms.sendTime
  177. }
  178. console.log(params, 'params')
  179. if (forms.id) {
  180. forms.updateLoading = true
  181. } else {
  182. forms.sureLoading = true
  183. }
  184. if (forms.id) {
  185. params.id = forms.id
  186. await request.post('/api-school/imMessageBatchSending/update', {
  187. hideLoading: false,
  188. data: params
  189. })
  190. } else {
  191. await request.post('/api-school/imMessageBatchSending/save', {
  192. hideLoading: false,
  193. data: params
  194. })
  195. }
  196. setTimeout(() => {
  197. showToast(forms.id ? '修改成功' : '添加成功')
  198. }, 100)
  199. setTimeout(() => {
  200. router.replace('/mass-message')
  201. forms.sureLoading = false
  202. forms.updateLoading = false
  203. }, 1100)
  204. } catch {
  205. //
  206. forms.sureLoading = false
  207. forms.updateLoading = false
  208. }
  209. }
  210. const getDetails = async () => {
  211. try {
  212. if (!forms.id) return
  213. const { data } = await request.get('/api-school/imMessageBatchSending/detail/' + forms.id)
  214. forms.sendType = data.sendType
  215. forms.textMessage = data.textMessage
  216. forms.sendTime = data.sendTime
  217. forms.type = data.sendStatus
  218. const receives = data.receives || []
  219. const tempList: any = {
  220. class: [] as any,
  221. teacher: [] as any,
  222. student: [] as any,
  223. school: [] as any
  224. }
  225. receives.forEach((item: any) => {
  226. const temp = {
  227. receiveType: item.receiveType,
  228. receiveId: item.receiveId,
  229. receiveName: item.receiveName,
  230. avatar: item.avatar
  231. }
  232. forms.receives.push(temp)
  233. const temp2 = {
  234. id: item.receiveId,
  235. value: item.receiveName,
  236. avatar: item.avatar
  237. }
  238. if (item.receiveType === 'CLASS') {
  239. tempList.class.push(temp2)
  240. } else if (item.receiveType === 'STUDENT') {
  241. tempList.student.push(temp2)
  242. } else if (item.receiveType === 'TEACHER') {
  243. tempList.teacher.push(temp2)
  244. } else if (item.receiveType === 'SCHOOL') {
  245. tempList.school.push(temp2)
  246. }
  247. })
  248. forms.selectList = tempList
  249. const attachments = data.attachments || []
  250. const tempAtt: any = []
  251. attachments.forEach((item: any) => {
  252. tempAtt.push({
  253. url: item.imgUrl || item.imgMessage
  254. })
  255. })
  256. forms.attachments = tempAtt
  257. } catch (e: any) {
  258. //
  259. console.log(e, 'e')
  260. }
  261. }
  262. // 判断是否是查看
  263. const formDisabled = computed(() => forms.type === 'SEND')
  264. const onClose = async () => {
  265. try {
  266. forms.closeLoading = true
  267. await request.post('/api-school/imMessageBatchSending/remove', {
  268. requestType: 'form',
  269. hideLoading: false,
  270. data: {
  271. id: forms.id
  272. }
  273. })
  274. setTimeout(() => {
  275. showToast('撤销成功')
  276. }, 100)
  277. setTimeout(() => {
  278. router.replace('/mass-message')
  279. forms.closeLoading = false
  280. }, 1100)
  281. } catch {
  282. //
  283. forms.closeLoading = false
  284. }
  285. }
  286. onMounted(() => {
  287. getDetails()
  288. })
  289. return () => (
  290. <div class={styles['create-message']}>
  291. {/* <OHeader /> */}
  292. <CellGroup inset class={styles.cellGroup}>
  293. <Field
  294. inputAlign="right"
  295. label="发送方式"
  296. modelValue={sendType[forms.sendType]}
  297. placeholder="请选择发送方式"
  298. onClick={() => {
  299. if (formDisabled.value) return
  300. forms.sendStatus = true
  301. }}
  302. readonly
  303. isLink={!formDisabled.value}
  304. class={styles.inputForm}
  305. />
  306. {/* 定时发送才会有时间 */}
  307. {forms.sendType === 'SCHEDULED' && (
  308. <Field
  309. inputAlign="right"
  310. label="发送时间"
  311. modelValue={forms.sendTime}
  312. placeholder="请选择发送时间"
  313. onClick={() => {
  314. if (formDisabled.value) return
  315. forms.sendTimeStatus = true
  316. }}
  317. readonly
  318. isLink
  319. class={styles.inputForm}
  320. />
  321. )}
  322. <Cell title="发送内容">
  323. {{
  324. label: () => (
  325. <Field
  326. style={{ padding: '0', marginTop: '12px' }}
  327. placeholder="请输入发送内容"
  328. v-model={forms.textMessage}
  329. type="textarea"
  330. rows={3}
  331. showWordLimit
  332. maxlength={400}
  333. readonly={formDisabled.value}
  334. />
  335. )
  336. }}
  337. </Cell>
  338. <Cell title="上传附件">
  339. {{
  340. label: () => (
  341. <Uploader
  342. style={{ marginTop: '12px' }}
  343. v-model={forms.attachments}
  344. afterRead={afterRead}
  345. beforeRead={beforeRead}
  346. beforeDelete={beforeDelete}
  347. accept="image/*"
  348. maxCount={9}
  349. disabled={formDisabled.value}
  350. />
  351. )
  352. }}
  353. </Cell>
  354. <Field
  355. label="发送对象"
  356. readonly
  357. inputAlign="right"
  358. class={styles.sendObjPlaceholder}
  359. placeholder={formDisabled.value ? '' : '请选择发送对象'}
  360. isLink={!formDisabled.value}
  361. border={false}
  362. onClick={() => {
  363. if (formDisabled.value) return
  364. forms.selectStatus = true
  365. }}
  366. />
  367. {forms.receives.map((item: any) => {
  368. let img: any = iconStudent
  369. if (item.receiveType === 'CLASS') {
  370. img = iconJiaoFu
  371. } else if (item.receiveType === 'STUDENT') {
  372. img = iconStudent
  373. } else if (item.receiveType === 'TEACHER' || item.receiveType === 'SCHOOL') {
  374. img = iconTeacher
  375. }
  376. return (
  377. <Cell class={styles.receives} title={item.receiveName} center border={false}>
  378. {{
  379. icon: () => <Image class={styles.img} src={item.avatar || img} />,
  380. extra: () =>
  381. !formDisabled.value && (
  382. <Icon
  383. name="clear"
  384. color="#d7d7d7"
  385. size={20}
  386. onClick={() => {
  387. forms.delSelectItem = item
  388. forms.delStatus = true
  389. }}
  390. />
  391. )
  392. }}
  393. </Cell>
  394. )
  395. })}
  396. </CellGroup>
  397. <OSticky position="bottom">
  398. {forms.type === 'ADD' && (
  399. <div class={'btnGroup'}>
  400. <Button round block type="primary" onClick={onSubmit} disabled={forms.sureLoading}>
  401. 确认发送
  402. </Button>
  403. </div>
  404. )}
  405. {forms.type === 'WAIT' && (
  406. <div class={['btnGroup', 'btnMore']}>
  407. <Button round type="primary" onClick={onSubmit} disabled={forms.updateLoading}>
  408. 修改
  409. </Button>
  410. <Button round color="#64A9FF" onClick={onClose} disabled={forms.closeLoading}>
  411. 撤销
  412. </Button>
  413. </div>
  414. )}
  415. </OSticky>
  416. <ActionSheet
  417. v-model:show={forms.sendStatus}
  418. cancelText="取消"
  419. actions={
  420. [
  421. { name: '即时发送', value: 'IMMEDIATELY' },
  422. { name: '定时发送', value: 'SCHEDULED' }
  423. ] as any
  424. }
  425. onSelect={(val: any) => {
  426. console.log(val)
  427. forms.sendType = val.value
  428. forms.sendStatus = false
  429. }}
  430. />
  431. <Popup v-model:show={forms.sendTimeStatus} position="bottom" round>
  432. <PickerGroup
  433. title="发送时间"
  434. tabs={['选择日期', '选择时间']}
  435. onCancel={() => (forms.sendTimeStatus = false)}
  436. onConfirm={(val: any) => {
  437. const first = val[0].selectedValues.join('-')
  438. const second = val[1].selectedValues.join(':')
  439. forms.sendTime = dayjs(first + ' ' + second).format('YYYY-MM-DD HH:mm:ss')
  440. forms.sendTimeStatus = false
  441. }}
  442. >
  443. <DatePicker minDate={new Date()} maxDate={forms.maxDate} v-model={forms.currentDate} />
  444. <TimePicker v-model={forms.currentTime} />
  445. </PickerGroup>
  446. </Popup>
  447. <OPopup v-model:modelValue={forms.selectStatus}>
  448. <SelectSned
  449. v-model:selectList={forms.selectList}
  450. onClose={() => (forms.selectStatus = false)}
  451. onConfirm={(val: any) => {
  452. const classList = val.class || []
  453. const studentList = val.student || []
  454. const teacherList = val.teacher || []
  455. const schoolList = val.school || []
  456. const tempList: any = []
  457. classList.forEach((item: any) => {
  458. tempList.push({
  459. receiveType: 'CLASS',
  460. receiveId: item.id,
  461. receiveName: item.value,
  462. avatar: item.avatar
  463. })
  464. })
  465. studentList.forEach((item: any) => {
  466. tempList.push({
  467. receiveType: 'STUDENT',
  468. receiveId: item.id,
  469. receiveName: item.value,
  470. avatar: item.avatar
  471. })
  472. })
  473. teacherList.forEach((item: any) => {
  474. tempList.push({
  475. receiveType: 'TEACHER',
  476. receiveId: item.id,
  477. receiveName: item.value,
  478. avatar: item.avatar
  479. })
  480. })
  481. schoolList.forEach((item: any) => {
  482. tempList.push({
  483. receiveType: 'SCHOOL',
  484. receiveId: item.id,
  485. receiveName: item.value,
  486. avatar: item.avatar
  487. })
  488. })
  489. forms.receives = tempList
  490. }}
  491. />
  492. </OPopup>
  493. <ODialog
  494. v-model:show={forms.delStatus}
  495. showCancelButton
  496. message="您是否删除该数据"
  497. onConfirm={() => {
  498. const selectList = forms.selectList
  499. if (forms.delSelectItem.receiveType === 'CLASS') {
  500. const tempClass = selectList.class || []
  501. const sIndex = tempClass.findIndex(
  502. (item: any) => item.id === forms.delSelectItem.receiveId
  503. )
  504. tempClass.splice(sIndex, 1)
  505. } else if (forms.delSelectItem.receiveType === 'SCHOOL') {
  506. const tempSchool = selectList.school || []
  507. const sIndex = tempSchool.findIndex(
  508. (item: any) => item.id === forms.delSelectItem.receiveId
  509. )
  510. tempSchool.splice(sIndex, 1)
  511. } else if (forms.delSelectItem.receiveType === 'TEACHER') {
  512. const tempTeacher = selectList.teacher || []
  513. const sIndex = tempTeacher.findIndex(
  514. (item: any) => item.id === forms.delSelectItem.receiveId
  515. )
  516. tempTeacher.splice(sIndex, 1)
  517. } else if (forms.delSelectItem.receiveType === 'STUDENT') {
  518. const tempStudent = selectList.student || []
  519. const sIndex = tempStudent.findIndex(
  520. (item: any) => item.id === forms.delSelectItem.receiveId
  521. )
  522. tempStudent.splice(sIndex, 1)
  523. }
  524. forms.selectList = selectList
  525. console.log(forms.selectList, 'forms.selectList')
  526. const index = forms.receives.findIndex(
  527. (item: any) => item.receiveId === forms.delSelectItem.receiveId
  528. )
  529. forms.receives.splice(index, 1)
  530. }}
  531. />
  532. </div>
  533. )
  534. }
  535. })