create-message.tsx 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  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: 'gyt',
  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. data: params
  188. })
  189. } else {
  190. await request.post('/api-school/imMessageBatchSending/save', {
  191. data: params
  192. })
  193. }
  194. setTimeout(() => {
  195. showToast(forms.id ? '修改成功' : '添加成功')
  196. }, 100)
  197. setTimeout(() => {
  198. router.replace('/mass-message')
  199. forms.sureLoading = false
  200. forms.updateLoading = false
  201. }, 1100)
  202. } catch {
  203. //
  204. forms.sureLoading = false
  205. forms.updateLoading = false
  206. }
  207. }
  208. const getDetails = async () => {
  209. try {
  210. if (!forms.id) return
  211. const { data } = await request.get('/api-school/imMessageBatchSending/detail/' + forms.id)
  212. forms.sendType = data.sendType
  213. forms.textMessage = data.textMessage
  214. forms.sendTime = data.sendTime
  215. forms.type = data.sendStatus
  216. const receives = data.receives || []
  217. const tempList: any = {
  218. class: [] as any,
  219. teacher: [] as any,
  220. student: [] as any,
  221. school: [] as any
  222. }
  223. receives.forEach((item: any) => {
  224. const temp = {
  225. receiveType: item.receiveType,
  226. receiveId: item.receiveId,
  227. receiveName: item.receiveName,
  228. avatar: item.avatar
  229. }
  230. forms.receives.push(temp)
  231. const temp2 = {
  232. id: item.receiveId,
  233. value: item.receiveName,
  234. avatar: item.avatar
  235. }
  236. if (item.receiveType === 'CLASS') {
  237. tempList.class.push(temp2)
  238. } else if (item.receiveType === 'STUDENT') {
  239. tempList.student.push(temp2)
  240. } else if (item.receiveType === 'TEACHER') {
  241. tempList.teacher.push(temp2)
  242. } else if (item.receiveType === 'SCHOOL') {
  243. tempList.school.push(temp2)
  244. }
  245. })
  246. forms.selectList = tempList
  247. const attachments = data.attachments || []
  248. const tempAtt: any = []
  249. attachments.forEach((item: any) => {
  250. tempAtt.push({
  251. url: item.imgUrl || item.imgMessage
  252. })
  253. })
  254. forms.attachments = tempAtt
  255. } catch (e: any) {
  256. //
  257. console.log(e, 'e')
  258. }
  259. }
  260. // 判断是否是查看
  261. const formDisabled = computed(() => forms.type === 'SEND')
  262. const onClose = async () => {
  263. try {
  264. forms.closeLoading = true
  265. await request.post('/api-school/imMessageBatchSending/remove', {
  266. requestType: 'form',
  267. data: {
  268. id: forms.id
  269. }
  270. })
  271. setTimeout(() => {
  272. showToast('撤销成功')
  273. }, 100)
  274. setTimeout(() => {
  275. router.replace('/mass-message')
  276. forms.closeLoading = false
  277. }, 1100)
  278. } catch {
  279. //
  280. forms.closeLoading = false
  281. }
  282. }
  283. onMounted(() => {
  284. getDetails()
  285. })
  286. return () => (
  287. <div class={styles['create-message']}>
  288. {/* <OHeader /> */}
  289. <CellGroup inset class={styles.cellGroup}>
  290. <Field
  291. inputAlign="right"
  292. label="发送方式"
  293. modelValue={sendType[forms.sendType]}
  294. placeholder="请选择发送方式"
  295. onClick={() => {
  296. if (formDisabled.value) return
  297. forms.sendStatus = true
  298. }}
  299. readonly
  300. isLink={!formDisabled.value}
  301. class={styles.inputForm}
  302. />
  303. {/* 定时发送才会有时间 */}
  304. {forms.sendType === 'SCHEDULED' && (
  305. <Field
  306. inputAlign="right"
  307. label="发送时间"
  308. modelValue={forms.sendTime}
  309. placeholder="请选择发送时间"
  310. onClick={() => {
  311. if (formDisabled.value) return
  312. forms.sendTimeStatus = true
  313. }}
  314. readonly
  315. isLink
  316. class={styles.inputForm}
  317. />
  318. )}
  319. <Cell title="发送内容">
  320. {{
  321. label: () => (
  322. <Field
  323. style={{ padding: '0', marginTop: '12px' }}
  324. placeholder="请输入发送内容"
  325. v-model={forms.textMessage}
  326. type="textarea"
  327. rows={3}
  328. showWordLimit
  329. maxlength={400}
  330. readonly={formDisabled.value}
  331. />
  332. )
  333. }}
  334. </Cell>
  335. <Cell title="上传附件">
  336. {{
  337. label: () => (
  338. <Uploader
  339. style={{ marginTop: '12px' }}
  340. v-model={forms.attachments}
  341. afterRead={afterRead}
  342. beforeRead={beforeRead}
  343. beforeDelete={beforeDelete}
  344. accept="image/*"
  345. maxCount={9}
  346. disabled={formDisabled.value}
  347. />
  348. )
  349. }}
  350. </Cell>
  351. <Field
  352. label="发送对象"
  353. readonly
  354. inputAlign="right"
  355. class={styles.sendObjPlaceholder}
  356. placeholder={formDisabled.value ? '' : '请选择发送对象'}
  357. isLink={!formDisabled.value}
  358. border={false}
  359. onClick={() => {
  360. if (formDisabled.value) return
  361. forms.selectStatus = true
  362. }}
  363. />
  364. {forms.receives.map((item: any) => {
  365. let img: any = iconStudent
  366. if (item.receiveType === 'CLASS') {
  367. img = iconJiaoFu
  368. } else if (item.receiveType === 'STUDENT') {
  369. img = iconStudent
  370. } else if (item.receiveType === 'TEACHER' || item.receiveType === 'SCHOOL') {
  371. img = iconTeacher
  372. }
  373. return (
  374. <Cell class={styles.receives} title={item.receiveName} center border={false}>
  375. {{
  376. icon: () => <Image class={styles.img} src={item.avatar || img} />,
  377. extra: () =>
  378. !formDisabled.value && (
  379. <Icon
  380. name="clear"
  381. color="#d7d7d7"
  382. size={20}
  383. onClick={() => {
  384. forms.delSelectItem = item
  385. forms.delStatus = true
  386. }}
  387. />
  388. )
  389. }}
  390. </Cell>
  391. )
  392. })}
  393. </CellGroup>
  394. <OSticky position="bottom">
  395. {forms.type === 'ADD' && (
  396. <div class={'btnGroup'}>
  397. <Button round block type="primary" onClick={onSubmit} disabled={forms.sureLoading}>
  398. 确认发送
  399. </Button>
  400. </div>
  401. )}
  402. {forms.type === 'WAIT' && (
  403. <div class={['btnGroup', 'btnMore']}>
  404. <Button round type="primary" onClick={onSubmit} disabled={forms.updateLoading}>
  405. 修改
  406. </Button>
  407. <Button round color="#64A9FF" onClick={onClose} disabled={forms.closeLoading}>
  408. 撤销
  409. </Button>
  410. </div>
  411. )}
  412. </OSticky>
  413. <ActionSheet
  414. v-model:show={forms.sendStatus}
  415. cancelText="取消"
  416. actions={
  417. [
  418. { name: '即时发送', value: 'IMMEDIATELY' },
  419. { name: '定时发送', value: 'SCHEDULED' }
  420. ] as any
  421. }
  422. onSelect={(val: any) => {
  423. console.log(val)
  424. forms.sendType = val.value
  425. forms.sendStatus = false
  426. }}
  427. />
  428. <Popup v-model:show={forms.sendTimeStatus} position="bottom" round>
  429. <PickerGroup
  430. title="发送时间"
  431. tabs={['选择日期', '选择时间']}
  432. onCancel={() => (forms.sendTimeStatus = false)}
  433. onConfirm={(val: any) => {
  434. const first = val[0].selectedValues.join('-')
  435. const second = val[1].selectedValues.join(':')
  436. forms.sendTime = dayjs(first + ' ' + second).format('YYYY-MM-DD HH:mm:ss')
  437. forms.sendTimeStatus = false
  438. }}
  439. >
  440. <DatePicker minDate={new Date()} maxDate={forms.maxDate} v-model={forms.currentDate} />
  441. <TimePicker v-model={forms.currentTime} />
  442. </PickerGroup>
  443. </Popup>
  444. <OPopup v-model:modelValue={forms.selectStatus}>
  445. <SelectSned
  446. v-model:selectList={forms.selectList}
  447. onClose={() => (forms.selectStatus = false)}
  448. onConfirm={(val: any) => {
  449. const classList = val.class || []
  450. const studentList = val.student || []
  451. const teacherList = val.teacher || []
  452. const schoolList = val.school || []
  453. const tempList: any = []
  454. classList.forEach((item: any) => {
  455. tempList.push({
  456. receiveType: 'CLASS',
  457. receiveId: item.id,
  458. receiveName: item.value,
  459. avatar: item.avatar
  460. })
  461. })
  462. studentList.forEach((item: any) => {
  463. tempList.push({
  464. receiveType: 'STUDENT',
  465. receiveId: item.id,
  466. receiveName: item.value,
  467. avatar: item.avatar
  468. })
  469. })
  470. teacherList.forEach((item: any) => {
  471. tempList.push({
  472. receiveType: 'TEACHER',
  473. receiveId: item.id,
  474. receiveName: item.value,
  475. avatar: item.avatar
  476. })
  477. })
  478. schoolList.forEach((item: any) => {
  479. tempList.push({
  480. receiveType: 'SCHOOL',
  481. receiveId: item.id,
  482. receiveName: item.value,
  483. avatar: item.avatar
  484. })
  485. })
  486. forms.receives = tempList
  487. }}
  488. />
  489. </OPopup>
  490. <ODialog
  491. v-model:show={forms.delStatus}
  492. showCancelButton
  493. message="您是否删除该数据"
  494. onConfirm={() => {
  495. const selectList = forms.selectList
  496. if (forms.delSelectItem.receiveType === 'CLASS') {
  497. const tempClass = selectList.class || []
  498. const sIndex = tempClass.findIndex(
  499. (item: any) => item.id === forms.delSelectItem.receiveId
  500. )
  501. tempClass.splice(sIndex, 1)
  502. } else if (forms.delSelectItem.receiveType === 'SCHOOL') {
  503. const tempSchool = selectList.school || []
  504. const sIndex = tempSchool.findIndex(
  505. (item: any) => item.id === forms.delSelectItem.receiveId
  506. )
  507. tempSchool.splice(sIndex, 1)
  508. } else if (forms.delSelectItem.receiveType === 'TEACHER') {
  509. const tempTeacher = selectList.teacher || []
  510. const sIndex = tempTeacher.findIndex(
  511. (item: any) => item.id === forms.delSelectItem.receiveId
  512. )
  513. tempTeacher.splice(sIndex, 1)
  514. } else if (forms.delSelectItem.receiveType === 'STUDENT') {
  515. const tempStudent = selectList.student || []
  516. const sIndex = tempStudent.findIndex(
  517. (item: any) => item.id === forms.delSelectItem.receiveId
  518. )
  519. tempStudent.splice(sIndex, 1)
  520. }
  521. forms.selectList = selectList
  522. console.log(forms.selectList, 'forms.selectList')
  523. const index = forms.receives.findIndex(
  524. (item: any) => item.receiveId === forms.delSelectItem.receiveId
  525. )
  526. forms.receives.splice(index, 1)
  527. }}
  528. />
  529. </div>
  530. )
  531. }
  532. })