vip.jsx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. import React, { Component } from "react";
  2. import { AutoComplete, Button, Form, Input, message, Modal, Select, Spin } from "antd";
  3. import $ from "jquery";
  4. import ImgList from "../../common/imgList";
  5. import { splitUrl } from "../../tools";
  6. import { vipYear } from "../../dataDic";
  7. const FormItem = Form.Item;
  8. const Option = Select.Option;
  9. const formItemLayout = {
  10. labelCol: { span: 8 },
  11. wrapperCol: { span: 14 },
  12. };
  13. const PicturesWall = React.createClass({
  14. getInitialState() {
  15. return {
  16. previewVisible: false,
  17. previewImage: "",
  18. fileList: this.props.pictureUrl,
  19. };
  20. },
  21. getDefaultProps() {
  22. return {
  23. changeClick: this.modifyChange,
  24. };
  25. },
  26. handleCancel() {
  27. this.setState({ previewVisible: false });
  28. },
  29. handlePreview(file) {
  30. this.setState({
  31. previewImage: file.url || file.thumbUrl,
  32. previewVisible: true,
  33. });
  34. },
  35. handleChange(info) {
  36. let fileList = info.fileList;
  37. this.setState({ fileList });
  38. this.props.fileList(fileList);
  39. },
  40. componentWillReceiveProps(nextProps) {
  41. this.state.fileList = nextProps.pictureUrl;
  42. },
  43. render() {
  44. const { fileList } = this.state;
  45. return (
  46. <div style={{ display: "inline-block" }}>
  47. <ImgList
  48. domId={this.props.domId}
  49. uploadConfig={{
  50. action: globalConfig.context + "/api/admin/orderProject/uploadMemberFile",
  51. data: { sign: "order_invoice_file" },
  52. multiple: true,
  53. listType: "picture-card",
  54. }}
  55. onChange={(infor) => {
  56. this.handleChange(infor);
  57. }}
  58. fileList={fileList}
  59. />
  60. </div>
  61. );
  62. },
  63. });
  64. class ProjectOperationVip extends Component {
  65. constructor(props) {
  66. super(props);
  67. this.state = {
  68. commodityName: '',
  69. commodityQuantity: 1,
  70. patentType: 0,
  71. officialCost: '',
  72. costReduction: '',
  73. commodityPrice: '',
  74. main: '',
  75. taskComment: '',
  76. declarationBatch: '',
  77. ifCertificationFee: '',
  78. displayFees: "none",
  79. customerArr: [],
  80. patentTypeList: [],
  81. loading: false,
  82. patentTransfer: props.dataInfor ? props.dataInfor.patentTransfer : 0, //收否为专利转让 0 否 1 是
  83. orgCodeUrl: [],
  84. serviceLife: [],
  85. histYear: [],
  86. }
  87. this.onSubmit = this.onSubmit.bind(this);
  88. this.httpChange = this.httpChange.bind(this);
  89. this.selectAuto = this.selectAuto.bind(this);
  90. this.setValue = this.setValue.bind(this);
  91. this.getOrgCodeUrl = this.getOrgCodeUrl.bind(this);
  92. }
  93. componentDidMount() {
  94. this.setValue();
  95. }
  96. setValue() {
  97. const { dataInfor } = this.props;
  98. if (!(dataInfor && Object.keys(dataInfor).length > 0)) {
  99. } else {
  100. this.setState({
  101. fid: dataInfor.id,
  102. commodityId: dataInfor.commodityId, //项目ID
  103. commodityName: dataInfor.commodityName, //项目名称
  104. commodityQuantity: dataInfor.commodityQuantity, // 数量
  105. memberType: dataInfor.memberType.toString(),// 付款情况
  106. taskComment: dataInfor.taskComment, // 备注
  107. orgCodeUrl: dataInfor.pictureUrl ? splitUrl(dataInfor.pictureUrl, ",", globalConfig.avatarHost + "/upload") : [],// 附件
  108. yearSum: dataInfor.yearSum,//会员总服务年限
  109. serviceLife: JSON.parse(dataInfor.serviceLife) || [],//会员服务年限
  110. serviceYear: dataInfor.serviceYear,//本次派单
  111. });
  112. }
  113. }
  114. //
  115. getOrgCodeUrl(e) {
  116. this.setState({ orgCodeUrl: e });
  117. }
  118. // 新建会员项目
  119. onSubmit() {
  120. let pictureUrl = [];
  121. if (this.state.orgCodeUrl.length) {
  122. let picArr = [];
  123. this.state.orgCodeUrl.map(function (item) {
  124. if (
  125. item.response &&
  126. item.response.data &&
  127. item.response.data.length
  128. ) {
  129. picArr.push(item.response.data);
  130. }
  131. });
  132. pictureUrl = picArr.join(",");
  133. }
  134. if (this.state.commodityId === undefined || !this.state.commodityId) {
  135. message.warning("服务名称不匹配!");
  136. return
  137. }
  138. let reg = /^([0]|[1-9][0-9]*)$/;
  139. if (
  140. !this.state.commodityQuantity ||
  141. !reg.test(this.state.commodityQuantity)
  142. ) {
  143. message.warning("请输入正确商品数量!");
  144. return
  145. }
  146. if (this.state.memberType === undefined) {
  147. message.warning("请选择付款情况!");
  148. return
  149. }
  150. if (this.state.yearSum === undefined) {
  151. message.warning("请选择会员总服务年限!");
  152. return
  153. }
  154. if (this.state.serviceLife.length === 0) {
  155. message.warning("请添加会员服务年限!");
  156. return
  157. }
  158. if (this.state.serviceLife.length != this.state.yearSum) {
  159. message.warning("会员服务年限与总年限不符合!");
  160. return
  161. }
  162. if (this.state.serviceYear === undefined) {
  163. message.warning("请选择本次派单年份!");
  164. return
  165. }
  166. if (this.state.memberType == "1" || this.state.memberType == "2") {
  167. if (typeof pictureUrl !== "string") {
  168. message.warning("请上传附件!");
  169. return
  170. }
  171. }
  172. this.setState({
  173. loading: true,
  174. });
  175. let infor = {
  176. orderNo: this.props.orderNo, //订单编号
  177. commodityId: this.state.commodityId, //项目编号
  178. commodityName: this.state.commodityName, //项目名称
  179. commodityQuantity: this.state.commodityQuantity, //商品数量
  180. commodityPrice: 0, //签单总价
  181. taskComment: this.state.taskComment, //服务说明
  182. memberType: this.state.memberType,//会员付款状态
  183. yearSum: this.state.yearSum,//会员总服务年限
  184. serviceLife: JSON.stringify(this.state.serviceLife),//会员服务年限
  185. serviceYear: this.state.serviceYear,//本次派单
  186. pictureUrl: pictureUrl.length ? pictureUrl : "",//附件
  187. }
  188. $.ajax({
  189. method: "POST",
  190. dataType: "json",
  191. crossDomain: false,
  192. url: globalConfig.context + "/api/admin/orderProject/addMemberProject",
  193. data: infor,
  194. }).done(
  195. function (data) {
  196. this.setState({
  197. loading: false,
  198. });
  199. if (!data.error.length) {
  200. Modal.success({
  201. title: '保存成功!',
  202. content: (
  203. <div>
  204. 已提出会员项目申请!请在
  205. <span style={{ color: "red" }}>“订单管理-我的会员项目“</span>
  206. 跟进查看会员项目的审核状态,审核通过,即表示添加会员项目完成!!!
  207. </div>),
  208. });
  209. this.props.onCancel();
  210. } else {
  211. message.warning(data.error[0].message);
  212. }
  213. }.bind(this)
  214. );
  215. }
  216. // 修改会员项目
  217. onChange() {
  218. let pictureUrl = [];
  219. if (this.state.orgCodeUrl.length) {
  220. let picArr = [];
  221. this.state.orgCodeUrl.map(function (item) {
  222. if (
  223. item.response &&
  224. item.response.data &&
  225. item.response.data.length
  226. ) {
  227. picArr.push(item.response.data);
  228. }
  229. });
  230. pictureUrl = picArr.join(",");
  231. }
  232. if (this.state.commodityId === undefined || !this.state.commodityId) {
  233. message.warning("服务名称不匹配!");
  234. return
  235. }
  236. let reg = /^([0]|[1-9][0-9]*)$/;
  237. if (
  238. !this.state.commodityQuantity ||
  239. !reg.test(this.state.commodityQuantity)
  240. ) {
  241. message.warning("请输入正确商品数量!");
  242. return false;
  243. }
  244. if (this.state.memberType === undefined) {
  245. message.warning("请选择付款情况!");
  246. return
  247. }
  248. if (this.state.yearSum === undefined) {
  249. message.warning("请选择会员总服务年限!");
  250. return
  251. }
  252. if (this.state.serviceLife.length === 0) {
  253. message.warning("请添加会员服务年限!");
  254. return
  255. }
  256. if (this.state.serviceLife.length != this.state.yearSum) {
  257. message.warning("会员服务年限与总年限不符合!");
  258. return
  259. }
  260. if (this.state.serviceYear === undefined) {
  261. message.warning("请选择本次派单年份!");
  262. return
  263. }
  264. if (this.state.memberType == "1" || this.state.memberType == "2") {
  265. if (typeof pictureUrl !== "string") {
  266. message.warning("请上传附件!");
  267. return
  268. }
  269. }
  270. this.setState({
  271. loading: true,
  272. });
  273. $.ajax({
  274. method: "POST",
  275. dataType: "json",
  276. crossDomain: false,
  277. url: globalConfig.context + "/api/admin/orderProject/updateMemberProject",
  278. data: {
  279. id: this.state.fid, //任务ID
  280. commodityId: this.state.commodityId, //项目ID
  281. commodityName: this.state.commodityName, //项目名称
  282. orderNo: this.props.orderNo, //订单编号
  283. commodityQuantity: this.state.commodityQuantity, //数量
  284. taskComment: this.state.taskComment, //备注
  285. memberType: this.state.memberType,//会员付款状态
  286. yearSum: this.state.yearSum,//会员总服务年限
  287. serviceLife: JSON.stringify(this.state.serviceLife),//会员服务年限
  288. serviceYear: this.state.serviceYear,//本次派单
  289. pictureUrl: pictureUrl.length ? pictureUrl : "",//附件
  290. },
  291. }).done(
  292. function (data) {
  293. this.setState({
  294. loading: false,
  295. });
  296. if (!data.error.length) {
  297. message.success("保存成功!");
  298. this.props.onCancel();
  299. } else {
  300. message.warning(data.error[0].message);
  301. }
  302. }.bind(this)
  303. );
  304. }
  305. //
  306. httpChange(e) {
  307. this.setState({
  308. commodityName: e,
  309. });
  310. if (e.length >= 1) {
  311. this.supervisor(e);
  312. }
  313. }
  314. //加载(自动补全)
  315. supervisor(e) {
  316. //服务名称自动补全
  317. let api = "/api/admin/order/getBusinessProjectByName";
  318. $.ajax({
  319. method: "get",
  320. dataType: "json",
  321. crossDomain: false,
  322. url: globalConfig.context + api,
  323. data: {
  324. businessName: e,
  325. cname: "高新会员服务",
  326. },
  327. success: function (data) {
  328. let thedata = data.data;
  329. if (!thedata) {
  330. if (data.error && data.error.length) {
  331. message.warning(data.error[0].message);
  332. }
  333. thedata = {};
  334. }
  335. this.setState({
  336. customerArr: thedata,
  337. });
  338. }.bind(this),
  339. }).always(
  340. function () {
  341. }.bind(this)
  342. );
  343. }
  344. //上级主管输入框失去焦点是判断客户是否存在
  345. selectAuto(value) {
  346. const { customerArr } = this.state;
  347. const { newData } = this.props
  348. const newdataSources = JSON.stringify(customerArr) == "{}" ? [] : customerArr;
  349. let cid = newdataSources.find((item) => item.bname == value).id
  350. this.setState({
  351. commodityName: value,
  352. commodityId: cid,
  353. histYear: [],
  354. });
  355. if (newData && newData.length > 0) {
  356. let llist = []
  357. for (var i = 0; i < newData.length; i++) {
  358. if (newData[i].commodityId == cid) {
  359. llist.push(newData[i].serviceYear)
  360. }
  361. }
  362. this.setState({
  363. histYear: llist
  364. })
  365. for (var i = newData.length - 1; i >= 0; i--) {
  366. if (newData[i].commodityId == cid) {
  367. this.setState({
  368. yearSum: newData[i].yearSum.toString(), // 会员总服务年限
  369. serviceLife: JSON.parse(newData[i].serviceLife) || [], // 会员服务年限
  370. })
  371. } else {
  372. this.setState({
  373. yearSum: undefined,
  374. serviceLife: [],
  375. })
  376. }
  377. return
  378. }
  379. }
  380. }
  381. render() {
  382. let options = this.state.customerArr.map((group, index) => (
  383. <Select.Option key={index} value={group.bname}>
  384. {group.bname}
  385. </Select.Option>
  386. ));
  387. let children = vipYear.map(its => (
  388. <Option key={its}>{its}</Option>
  389. ));
  390. const { readOnly } = this.props;
  391. const { histYear } = this.state
  392. return (
  393. <Modal
  394. maskClosable={false}
  395. visible={this.props.visible}
  396. onOk={this.props.onCancel}
  397. onCancel={this.props.onCancel}
  398. width="900px"
  399. title={readOnly ? "会员详情" : !this.state.fid ? "添加会员项目" : "编辑会员项目"}
  400. footer=""
  401. className="admin-desc-content"
  402. >
  403. <Form
  404. layout="horizontal"
  405. >
  406. <Spin spinning={this.state.loading}>
  407. <div className="clearfix">
  408. <FormItem
  409. className="half-item"
  410. {...formItemLayout}
  411. label="服务名称"
  412. >
  413. {readOnly ? this.state.commodityName :
  414. <AutoComplete
  415. className="certain-category-search"
  416. dropdownClassName="certain-category-search-dropdown"
  417. dropdownMatchSelectWidth={false}
  418. style={{ width: "200px" }}
  419. dataSource={options}
  420. placeholder="输入服务名称"
  421. value={this.state.commodityName}
  422. onChange={this.httpChange}
  423. filterOption={true}
  424. onSelect={this.selectAuto}
  425. >
  426. <Input />
  427. </AutoComplete>}
  428. {!readOnly && <span className="mandatory">*</span>}
  429. </FormItem>
  430. <FormItem
  431. className="half-item"
  432. {...formItemLayout}
  433. label="服务数量"
  434. >
  435. {readOnly ? this.state.commodityQuantity :
  436. <Input
  437. placeholder="请输入服务数量"
  438. value={this.state.commodityQuantity}
  439. style={{ width: "200px" }}
  440. disabled={true}
  441. onChange={(e) => {
  442. this.setState({ commodityQuantity: e.target.value });
  443. }}
  444. ref="commodityQuantity"
  445. />}
  446. {!readOnly && <span className="mandatory">*</span>}
  447. <div
  448. style={{
  449. color: "red",
  450. position: "relative",
  451. left: "0"
  452. }}
  453. >注:会员项目单次限制,只能派一年</div>
  454. </FormItem>
  455. <FormItem
  456. className="half-item"
  457. {...formItemLayout}
  458. label="付款情况"
  459. >
  460. {readOnly ?
  461. [
  462. { value: "0", key: "已付会员节点全款" },
  463. { value: "1", key: "已付部分期款,需特批" },
  464. { value: "2", key: "未付款,需特批" }][this.state.memberType] :
  465. <Select
  466. placeholder="选择付款情况"
  467. style={{ width: "200px" }}
  468. value={this.state.memberType}
  469. onChange={(e) => {
  470. this.setState({ memberType: e });
  471. }}
  472. >
  473. {[
  474. { value: "0", key: "已付会员节点全款" },
  475. { value: "1", key: "已付部分期款,需特批" },
  476. { value: "2", key: "未付款,需特批" }].map(function (item) {
  477. return (
  478. <Select.Option key={item.value}>
  479. {item.key}
  480. </Select.Option>
  481. );
  482. })}
  483. </Select>}
  484. {!readOnly && <span className="mandatory">*</span>}
  485. </FormItem>
  486. <FormItem
  487. className="half-item"
  488. {...formItemLayout}
  489. label="会员总服务年限"
  490. >
  491. {readOnly ?
  492. this.state.yearSum == null ? "" :
  493. [
  494. { value: "0", key: "" },
  495. { value: "1", key: "一年" },
  496. { value: "2", key: "二年" },
  497. { value: "3", key: "三年" },
  498. { value: "4", key: "四年" },
  499. { value: "5", key: "五年" },
  500. ][this.state.yearSum]["key"] :
  501. <Select
  502. placeholder="请选择会员总服务年限"
  503. style={{ width: "200px" }}
  504. value={this.state.yearSum}
  505. onChange={(e) => {
  506. this.setState({ yearSum: e });
  507. }}
  508. >
  509. {[
  510. { value: "1", key: "一年" },
  511. { value: "2", key: "二年" },
  512. { value: "3", key: "三年" },
  513. { value: "4", key: "四年" },
  514. { value: "5", key: "五年" },
  515. ].map(function (item) {
  516. return (
  517. <Select.Option key={item.value}>
  518. {item.key}
  519. </Select.Option>
  520. );
  521. })}
  522. </Select>}
  523. {!readOnly && <span className="mandatory">*</span>}
  524. </FormItem>
  525. <FormItem
  526. className="half-item"
  527. {...formItemLayout}
  528. label="会员服务年限"
  529. >
  530. {
  531. readOnly ?
  532. this.state.serviceLife.toString() :
  533. <Select
  534. mode="multiple"
  535. style={{ width: '200px' }}
  536. placeholder="请选择服务年限"
  537. value={this.state.serviceLife}
  538. onChange={e => {
  539. this.setState({
  540. serviceLife: e,
  541. serviceYear: undefined,
  542. })
  543. }}
  544. >
  545. {children}
  546. </Select>
  547. }
  548. {!readOnly && <span className="mandatory">*</span>}
  549. </FormItem>
  550. <FormItem
  551. className="half-item"
  552. {...formItemLayout}
  553. label="本次派单"
  554. >
  555. {readOnly ?
  556. this.state.serviceYear :
  557. <Select
  558. placeholder="请选择本次派单年份"
  559. style={{ width: "200px" }}
  560. value={this.state.serviceYear}
  561. onChange={(e) => {
  562. this.setState({ serviceYear: e });
  563. }}
  564. >
  565. {this.state.serviceLife.length > 0 && this.state.serviceLife.map(function (item) {
  566. return (
  567. <Select.Option key={item} disabled={histYear.includes(item)}>
  568. {item}
  569. </Select.Option>
  570. );
  571. })}
  572. </Select>}
  573. {!readOnly && <span className="mandatory">*</span>}
  574. </FormItem>
  575. {
  576. (this.state.memberType == "1" || this.state.memberType == "2") &&
  577. <div className="clearfix">
  578. <FormItem
  579. labelCol={{ span: 4 }}
  580. wrapperCol={{ span: 16 }}
  581. label="上传附件"
  582. >
  583. <PicturesWall
  584. domId={'vip'}
  585. fileList={this.getOrgCodeUrl}
  586. pictureUrl={this.state.orgCodeUrl}
  587. />
  588. {!readOnly && <span className="mandatory">*</span>}
  589. </FormItem>
  590. <div style={{ color: "red", marginLeft: 144, marginBottom: 15 }}>
  591. 特批需上传附件图,请上传客户同意我方继续服务并安排给我司付款的聊天记录截图,
  592. <p>若没有客户同意继续服务及会安排付款的截图,特派流程将无法走下去,以免造成派单耽搁</p>
  593. </div>
  594. </div>
  595. }
  596. <div className="clearfix">
  597. <FormItem
  598. labelCol={{ span: 4 }}
  599. wrapperCol={{ span: 16 }}
  600. label="项目说明"
  601. >
  602. {readOnly ? this.state.taskComment :
  603. <Input
  604. type="textarea"
  605. placeholder="如:派2022年会员服务,总会员服务三年,客户付款情况说明"
  606. autosize={{ minRows: 4 }}
  607. value={this.state.taskComment}
  608. onChange={(e) => {
  609. this.setState({ taskComment: e.target.value });
  610. }}
  611. />}
  612. </FormItem>
  613. <div style={{ color: "red", marginLeft: 144 }}>
  614. 请详细说明项目服务时间,总服务时间及付款情况,如:<span style={{ color: "#333" }}>派2022年会员服务,总会员服务三年,客户付款情况说明</span>
  615. <p>未付款时,需进行特批审核,请详细说明预计付款时间等详细情况</p>
  616. </div>
  617. </div>
  618. {readOnly ? null : <FormItem
  619. wrapperCol={{ span: 12, offset: 4 }}
  620. className="half-middle"
  621. >
  622. <Button
  623. className="submitSave"
  624. type="primary"
  625. onClick={() => {
  626. if (!this.state.fid) {
  627. this.onSubmit()
  628. } else {
  629. this.onChange()
  630. }
  631. }}
  632. >
  633. 保存
  634. </Button>
  635. <Button
  636. className="submitSave"
  637. type="ghost"
  638. onClick={this.props.onCancel}
  639. >
  640. 取消
  641. </Button>
  642. </FormItem>}
  643. </div>
  644. </Spin>
  645. </Form>
  646. </Modal>
  647. )
  648. }
  649. }
  650. export default ProjectOperationVip;