Miniapp.jsx 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. import React, { useState, useEffect } from 'react';
  2. import { Button, Row, Col, Input, InputNumber, Modal, notification, Select, Tooltip } from 'antd';
  3. import createForm from '@zjxpcyc/xrc-form2';
  4. import Style from '../style.less';
  5. import { fetch, apis } from '../../../utils/request';
  6. const XForm = createForm();
  7. const saveMiniapp = fetch(apis.member.miniapp.edit);
  8. const checkMiniapp = fetch(apis.member.miniapp.check);
  9. const getEventValue = e => {
  10. return Object.prototype.hasOwnProperty.call(e, 'checked') ?
  11. e.checked : (e.target ? e.target.value : e)
  12. }
  13. const TplItem = React.forwardRef((props, ref) => {
  14. const [val, setVal] = useState(props.value)
  15. const [isSubs, setIsSubs] = useState(props.value.isSubscribe)
  16. const handleChange = field => e => {
  17. const fv = getEventValue(e);
  18. const newVal = { ...val, [`${field}`]: fv }
  19. setVal(newVal)
  20. if (field === 'isSubscribe') {
  21. setIsSubs(fv)
  22. }
  23. if (typeof props.onChange === 'function') {
  24. props.onChange(newVal)
  25. }
  26. }
  27. return (
  28. <div ref={ref}>
  29. <Input.Group compact>
  30. <Tooltip title="消息类型">
  31. <Select style={{ width: '15%' }} value={!!val.isSubscribe} onChange={handleChange('isSubscribe')}>
  32. <Option value={true}>订阅</Option>
  33. <Option value={false}>服务</Option>
  34. </Select>
  35. </Tooltip>
  36. <Tooltip title="消息模板ID">
  37. <Input style={{ width: '45%' }} value={val.tplId} placeholder="消息模板ID" onChange={handleChange('tplId')}></Input>
  38. </Tooltip>
  39. {
  40. !isSubs ?
  41. (<Tooltip title="消息字段数"><InputNumber style={{ width: '40%' }} value={val.fieldNum} placeholder="字段数" onChange={handleChange('fieldNum')}></InputNumber></Tooltip>) :
  42. (<Tooltip title="消息字段, 多字段用 | 分隔"><Input style={{ width: '40%' }} value={val.tplFields} placeholder="字段内容" onChange={handleChange('tplFields')}></Input></Tooltip>)
  43. }
  44. </Input.Group>
  45. </div>
  46. );
  47. });
  48. const Miniapp = (props) => {
  49. const [ visible, changeVisible ] = useState(false);
  50. const [ path, changePath ] = useState('/pages/project/index');
  51. const [ qrCode, setQrCode ] = useState();
  52. const user = props.data || {}
  53. const appdata = user.miniapp || {};
  54. const tpls = appdata.tpls || [];
  55. useEffect(() => {
  56. setQrCode(appdata.qrCode)
  57. }, [])
  58. const showModal = () => {
  59. changeVisible(true);
  60. }
  61. let form = undefined;
  62. const handleForm = f => {
  63. if (f) {
  64. form = f.props.form
  65. }
  66. }
  67. const handleModalOk = () => {
  68. const values = form.getFieldsValue()
  69. const data = { ...values, path }
  70. checkMiniapp({ data }).then(dt => {
  71. setQrCode(dt.qrCode)
  72. changeVisible(false)
  73. notification.success({ message: '校验成功' });
  74. }).catch();
  75. }
  76. const tplFields = (props.tplTyps || []).map((x) => {
  77. console.log(props.tplTyps)
  78. console.log('tpls: ', tpls)
  79. console.log('appdata: ', appdata)
  80. console.log('tpls.filter: ', tpls.filter(y => y.tplType === x.code)[0] || {})
  81. return {
  82. label: x.name,
  83. name: `tpl.${x.code}`,
  84. node: TplItem,
  85. value: tpls.filter(y => y.tplType === x.code)[0] || {},
  86. hidden: vals => vals.isSubscribe,
  87. }
  88. })
  89. const fields = [
  90. {
  91. label: '名称',
  92. name: 'name',
  93. node: Input,
  94. value: appdata.name,
  95. rules: [{required: true, message: '请填写小程序名称'}]
  96. },
  97. {
  98. label: 'APPID',
  99. name: 'miniappId',
  100. node: Input,
  101. value: appdata.miniappId,
  102. props: {
  103. disabled: !!appdata.miniappId,
  104. },
  105. rules: [
  106. { required: true, message: '请填写 APPID' },
  107. { pattern: /^[a-zA-Z0-9]+$/, message: 'APPID 只能由字母与数字组成' }
  108. ]
  109. },
  110. {
  111. label: 'Secret',
  112. name: 'secret',
  113. node: Input,
  114. value: appdata.secret,
  115. rules: [
  116. { required: true, message: '请填写 Secret' },
  117. { pattern: /^[a-zA-Z0-9]+$/, message: 'APPID 只能由字母与数字组成' }
  118. ]
  119. },
  120. {
  121. label: 'Token',
  122. name: 'token',
  123. node: Input,
  124. value: appdata.token,
  125. rules: [
  126. { pattern: /^[a-zA-Z0-9]+$/, message: 'token 只能由字母与数字组成' }
  127. ]
  128. },
  129. {
  130. label: 'AES_KEY',
  131. name: 'aesKey',
  132. node: Input,
  133. value: appdata.aesKey,
  134. rules: [
  135. { pattern: /^[a-zA-Z0-9]+$/, message: 'AES_KEY 只能由字母与数字组成' }
  136. ]
  137. },
  138. ...tplFields,
  139. {
  140. label: '小程序码',
  141. name: 'qrCode',
  142. render: () => <img src={qrCode} style={{ width: '240px' }} alt=""/>,
  143. value: qrCode,
  144. },
  145. {
  146. action: true,
  147. render: () => {
  148. return (
  149. <div className={Style['flex-box']}>
  150. <div className={Style['flex-item']}>
  151. <img src="" alt="" style={{ width: '128px' }}/>
  152. </div>
  153. <div className={Style['flex-auto']}>
  154. <Button type="primary" ghost onClick={showModal}>验证</Button>
  155. </div>
  156. <Modal
  157. title="填写首页地址"
  158. visible={visible}
  159. onOk={handleModalOk}
  160. onCancel={() => changeVisible(false)}
  161. >
  162. <Input value={path} onChange={e => changePath(e.target.value)}></Input>
  163. </Modal>
  164. </div>
  165. )
  166. }
  167. },
  168. ]
  169. const checkTPLData = (submitData) => {
  170. let errors = []
  171. const tplData = Object.keys(submitData).map((key) => {
  172. const { tplId, fieldNum, tplFields, isSubscribe, ...left } = submitData[key]
  173. const tplType = (props.tplTyps || []).filter(x => x.code === key)[0] || {}
  174. if (isSubscribe) {
  175. if (tplId && !tplFields) {
  176. errors.push(`请填写${tplType.name}模板字段内容`)
  177. return
  178. }
  179. } else if (tplId && !fieldNum) {
  180. errors.push(`请填写${tplType.name}模板字段数`)
  181. return
  182. }
  183. return submitData[key]
  184. })
  185. return [tplData, errors]
  186. }
  187. const handleSubmit = val => {
  188. // 校验字段
  189. const { tpl, ...otherData} = val
  190. const [tplData, errors] = checkTPLData(tpl)
  191. if (errors.length > 0) {
  192. notification.error({ message: errors[0] })
  193. return
  194. }
  195. const data = {
  196. ...appdata,
  197. ...otherData,
  198. qrCode: qrCode || appdata.appdata,
  199. orgId: user.orgId,
  200. tpls: tplData,
  201. }
  202. saveMiniapp({ data }).then((miniapp) => {
  203. if (typeof props.onChange === 'function') {
  204. props.onChange({ ...user, miniapp })
  205. }
  206. notification.success({ message: '保存小程序信息成功' })
  207. }).catch(x => x)
  208. }
  209. const handleCancel = () => {
  210. if (typeof props.onCancel === 'function') {
  211. props.onCancel()
  212. }
  213. }
  214. return (<XForm wrappedComponentRef={handleForm} onSubmit={handleSubmit} onCancel={handleCancel} fields={fields}></XForm>)
  215. }
  216. export default Miniapp;