customerServiceRecord.jsx 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. import React,{Component} from "react";
  2. import {DatePicker, Input, Radio, Select, Table, Checkbox, Button, message, Spin, Tooltip, Modal} from "antd";
  3. import $ from "jquery";
  4. import moment from "moment";
  5. const RadioGroup = Radio.Group;
  6. const confirm = Modal.confirm;
  7. class CustomerServiceRecord extends Component{
  8. constructor(props) {
  9. super(props);
  10. this.state={
  11. columns:[
  12. {
  13. title: "跟进时间",
  14. dataIndex: "createTimes",
  15. key: "createTimes",
  16. width: 100,
  17. },
  18. {
  19. title: "跟进人",
  20. dataIndex: "adminName",
  21. key: "adminName",
  22. width: 130,
  23. },
  24. {
  25. title: "是否已添微信",
  26. dataIndex: "addWechat",
  27. key: "addWechat",
  28. width: 100,
  29. render: (text,record) => {
  30. let str = text === 1 ? '是('+record.wechat+')' : text === 0 ? '否' : '';
  31. return (
  32. <Tooltip placement="topLeft" title={str}>
  33. <div style={{
  34. maxWidth:'100px',
  35. overflow:'hidden',
  36. textOverflow: "ellipsis",
  37. whiteSpace:'nowrap',
  38. }}>{str}</div>
  39. </Tooltip>
  40. )
  41. }
  42. },
  43. {
  44. title: "续签情况",
  45. dataIndex: "renewal",
  46. key: "renewal",
  47. width: 150,
  48. render: (text,record) => {
  49. let str = text === 0 ? '未联系上当前联系人' :
  50. text === 1 ? '企业已签其他机构' :
  51. text === 2 ? '企业自己申报' :
  52. text === 3 ? '企业不打算申报/注销' :
  53. text === 4 ? '待续签,未报价(客服维护中)' :
  54. text === 5 ? '待续签,已报价(客服维护中)' :
  55. text === 6 ? ('已续签/复审、续签时间、续签项目' + (record.renewalTimes ? '('+record.renewalTimes+')' : '')): ''
  56. return (
  57. <Tooltip placement="topLeft" title={str}>
  58. <div style={{
  59. maxWidth:'150px',
  60. overflow:'hidden',
  61. textOverflow: "ellipsis",
  62. whiteSpace:'nowrap',
  63. }}>{str}</div>
  64. </Tooltip>
  65. )
  66. }
  67. },
  68. {
  69. title: "已签项目",
  70. dataIndex: "signProject",
  71. key: "signProject",
  72. width: 150,
  73. render: (text) => {
  74. return (
  75. <Tooltip placement="topLeft" title={text}>
  76. <div style={{
  77. maxWidth:'150px',
  78. overflow:'hidden',
  79. textOverflow: "ellipsis",
  80. whiteSpace:'nowrap',
  81. }}>{text}</div>
  82. </Tooltip>)
  83. }
  84. },
  85. {
  86. title: "技术端满意度",
  87. dataIndex: "techSatisfaction",
  88. key: "techSatisfaction",
  89. render: (text) => {
  90. //0 已投诉 1不满意 2一般满意 3非常满意
  91. return (
  92. <span>
  93. {
  94. text === 0 ? '已投诉' :
  95. text === 1 ? '不满意' :
  96. text === 2 ? '一般满意' :
  97. text === 3 ? '非常满意' : ''
  98. }
  99. </span>
  100. )
  101. }
  102. },
  103. {
  104. title: "业务端满意度",
  105. dataIndex: "businessSatisfaction",
  106. key: "businessSatisfaction",
  107. render: (text) => {
  108. return (
  109. <span>
  110. {
  111. text === 0 ? '已投诉' :
  112. text === 1 ? '不满意' :
  113. text === 2 ? '一般满意' :
  114. text === 3 ? '非常满意' : ''
  115. }
  116. </span>
  117. )
  118. }
  119. },
  120. {
  121. title: "备注",
  122. dataIndex: "remarks",
  123. key: "remarks",
  124. width: 150,
  125. render: (text) => {
  126. return (
  127. <Tooltip placement="topLeft" title={text}>
  128. <div style={{
  129. maxWidth:'150px',
  130. overflow:'hidden',
  131. textOverflow: "ellipsis",
  132. whiteSpace:'nowrap',
  133. }}>{text}</div>
  134. </Tooltip>)
  135. }
  136. },
  137. ],
  138. dataSource:[],
  139. releaseDate:'',
  140. techSatisfaction:'',
  141. businessSatisfaction:'',
  142. addWechat:'',
  143. wx:'',
  144. situation:'',
  145. comment:'',
  146. selectUidByprojectList:[],
  147. signProjectId:[],
  148. signProject:[],
  149. removeSelectList:[],
  150. }
  151. this.preservation = this.preservation.bind(this);
  152. this.loadData = this.loadData.bind(this);
  153. this.selectUidByprojectList = this.selectUidByprojectList.bind(this);
  154. this.inquiry = this.inquiry.bind(this);
  155. }
  156. componentDidMount() {
  157. this.loadData();
  158. }
  159. inquiry(){
  160. let _this = this;
  161. confirm({
  162. title: '确定要保存提交吗?',
  163. content: '请再次确定您填写的客服信息,客服信息提交后,不能修改或删除!',
  164. okText: '确定',
  165. okType: 'primary',
  166. cancelText: '取消',
  167. onOk() {
  168. _this.preservation();
  169. },
  170. });
  171. }
  172. preservation(){
  173. if(isNaN(parseInt(this.state.addWechat))){
  174. message.warning('请选择是否添加客服微信');
  175. return;
  176. }
  177. if(this.state.addWechat === 1 && !this.state.wx){
  178. message.warning('请填写微信号');
  179. return;
  180. }
  181. if(isNaN(parseInt(this.state.situation))){
  182. message.warning('请选择续签情况');
  183. return;
  184. }
  185. // if(this.state.situation === 6 && !this.state.releaseDate){
  186. // message.warning('请选择续签时间');
  187. // return;
  188. // }
  189. if(!this.state.comment){
  190. message.warning('请填写备注');
  191. return;
  192. }
  193. let hide = message.loading('提交中...',0);
  194. this.setState({
  195. preservationLoading: true
  196. });
  197. $.ajax({
  198. url: globalConfig.context + '/api/admin/addUseService',
  199. method: 'post',
  200. data: {
  201. uid:this.props.uid,
  202. addWechat:this.state.addWechat,
  203. wechat:this.state.wx,
  204. renewal:this.state.situation,
  205. renewalTimes:this.state.releaseDate || undefined,
  206. techSatisfaction:this.state.techSatisfaction,
  207. businessSatisfaction:this.state.businessSatisfaction,
  208. remarks:this.state.comment,
  209. signProjectId:this.state.signProjectId.join(','),
  210. signProject:this.state.signProject.join(','),
  211. }
  212. }).done((res) => {
  213. if (!res.error.length) {
  214. message.success("提交成功");
  215. this.loadData();
  216. } else {
  217. message.error(res.error[0].message);
  218. }
  219. }).always(() => {
  220. hide();
  221. this.setState({
  222. preservationLoading: false
  223. });
  224. })
  225. }
  226. loadData() {
  227. let _this = this;
  228. this.setState({
  229. listLoading: true,
  230. });
  231. $.ajax({
  232. method: "get",
  233. dataType: "json",
  234. crossDomain: false,
  235. url: globalConfig.context + "/api/admin/listUseServiceFollow",
  236. data: {
  237. uid:this.props.uid
  238. },
  239. success: function (data) {
  240. if (data.error && data.error.length) {
  241. message.warning(data.error[0].message);
  242. }else {
  243. if(data.data.length !== 0){
  244. let info = data.data[0];
  245. let signProjectId = info.signProjectId ? info.signProjectId.split(',') : [];
  246. let signProject = info.signProject ? info.signProject.split(',') : [];
  247. this.setState({
  248. releaseDate:info.renewalTimes,
  249. techSatisfaction:info.techSatisfaction,
  250. businessSatisfaction:info.businessSatisfaction,
  251. addWechat:info.addWechat,
  252. wx:info.wechat,
  253. situation:info.renewal,
  254. comment:info.remarks,
  255. signProjectId:signProjectId,
  256. signProject:signProject,
  257. },()=>{
  258. _this.selectUidByprojectList(signProjectId,signProject);
  259. })
  260. }else{
  261. _this.selectUidByprojectList();
  262. }
  263. this.setState({
  264. dataSource: data.data,
  265. });
  266. }
  267. }.bind(this),
  268. }).always(
  269. function () {
  270. this.setState({
  271. listLoading: false,
  272. });
  273. }.bind(this)
  274. );
  275. }
  276. selectUidByprojectList(signProjectId = [],signProject=[]) {
  277. this.setState({
  278. selectLoading: true,
  279. });
  280. $.ajax({
  281. method: "get",
  282. dataType: "json",
  283. crossDomain: false,
  284. url: globalConfig.context + "/api/admin/orderProject/selectUidByproject",
  285. data: {
  286. uid:this.props.uid
  287. },
  288. success: function (data) {
  289. if (data.error && data.error.length) {
  290. message.warning(data.error[0].message);
  291. }else{
  292. let removeArr = [];
  293. if(signProjectId.length > 0){
  294. let info = data.data;
  295. let arr = [];
  296. for(let i of info){
  297. for(let v of i.list){
  298. arr.push(v);
  299. }
  300. }
  301. for(let i of signProjectId){
  302. let arr1 = arr.filter(v=>{
  303. return i==v.id;
  304. });
  305. if(arr1.length < 1){
  306. let index = signProjectId.findIndex(d=>d == i);
  307. removeArr.push({
  308. name:signProject[index],
  309. id:signProjectId[index],
  310. })
  311. }
  312. }
  313. }
  314. this.setState({
  315. selectUidByprojectList:data.data,
  316. removeSelectList:removeArr
  317. })
  318. }
  319. }.bind(this),
  320. }).always(
  321. function () {
  322. this.setState({
  323. selectLoading: false,
  324. });
  325. }.bind(this)
  326. );
  327. }
  328. render() {
  329. return (
  330. <div style={{padding:"15px"}}>
  331. <Spin spinning={this.state.listLoading}>
  332. <Table
  333. pagination={false}
  334. bordered
  335. size="small"
  336. columns={this.state.columns}
  337. dataSource={this.state.dataSource}
  338. />
  339. </Spin>
  340. <Spin spinning={this.state.listLoading}>
  341. <div style={{paddingTop:"20px"}}>
  342. <div style={{display:'flex',alignItems:"center",paddingBottom:"10px"}}>
  343. <div style={{fontWeight:"bolder",paddingRight:'10px'}}><span style={{color:'#f00'}}>*</span>添加客服微信:</div>
  344. <RadioGroup
  345. value={this.state.addWechat}
  346. onChange={(e) => {
  347. this.setState({ addWechat: e.target.value });
  348. if(e.target.value === 0){
  349. this.setState({
  350. wx:''
  351. })
  352. }
  353. }}
  354. >
  355. <Radio value={0}>否,暂未添加</Radio>
  356. <Radio value={1}>
  357. <span>
  358. </span>
  359. </Radio>
  360. </RadioGroup>
  361. </div>
  362. {this.state.addWechat === 1 ? <div style={{display:'flex',alignItems:"center",paddingBottom:"10px"}}>
  363. <div style={{fontWeight:"bolder",paddingRight:'10px'}}><span style={{color:'#f00'}}>*</span>微信号</div>
  364. <Input
  365. placeholder='请输入微信号'
  366. style={{ width: 150, marginRight: 10 }}
  367. value={this.state.wx}
  368. onChange={(e)=>{
  369. this.setState({wx:e.target.value})
  370. }}/>
  371. </div> : null}
  372. <div style={{display:'flex',alignItems:"center",paddingBottom:"10px"}}>
  373. <div style={{fontWeight:"bolder",paddingRight:'10px'}}><span style={{color:'#f00'}}>*</span>续签情况:</div>
  374. <Select
  375. placeholder="续签情况"
  376. style={{ width: 250, marginRight: 10 }}
  377. value={this.state.situation}
  378. onChange={(e) => {
  379. this.setState({ situation: e });
  380. if(e !== 6){
  381. this.setState({
  382. releaseDate:'',
  383. signProjectId:[],
  384. signProject:[],
  385. })
  386. }
  387. }}
  388. >
  389. <Option value={6}>已续签/复审、续签时间、续签项目</Option>
  390. <Option value={5}>待续签,已报价(客服维护中)</Option>
  391. <Option value={4}>待续签,未报价(客服维护中)</Option>
  392. <Option value={3}>企业不打算申报/注销</Option>
  393. <Option value={2}>企业自己申报</Option>
  394. <Option value={1}>企业已签其他机构</Option>
  395. <Option value={0}>未联系上当前联系人</Option>
  396. </Select>
  397. </div>
  398. {this.state.situation === 6 ? <div style={{display:'flex',alignItems:"center",paddingBottom:"10px"}}>
  399. <div style={{fontWeight:"bolder",paddingRight:'10px'}}>
  400. {/*<span style={{color:'#f00'}}>*</span>*/}
  401. 续签时间:
  402. </div>
  403. <DatePicker
  404. value={this.state.releaseDate ? moment(this.state.releaseDate) : null}
  405. onChange={(data, dataString) => {
  406. this.setState({ releaseDate: dataString });
  407. }}
  408. />
  409. </div> : null}
  410. {this.state.situation === 6 ? <div style={{paddingBottom:"10px"}}>
  411. <div style={{fontWeight:"bolder",paddingRight:'10px',paddingBottom:'15px',whiteSpace:"nowrap"}}>已签项目:</div>
  412. <Spin spinning={this.state.selectLoading}>
  413. {
  414. this.state.selectUidByprojectList.map((value,key)=>(
  415. <div key={key} style={{
  416. paddingBottom:'10px',
  417. display:'flex',
  418. flexFlow:"row nowrap",
  419. alignItems:'flex-start',
  420. padding:'10px 5px 0 5px',
  421. background:key % 2 === 0 ? '#afacad' : '#fff',
  422. color:key % 2 === 0 ? '#fff' : '#000',
  423. borderRadius: '4px',
  424. }}>
  425. <div style={{whiteSpace:"nowrap",paddingBottom:'10px'}}>{value.orderNo+':'}</div>
  426. <div style={{
  427. flex:1,
  428. display:'flex',
  429. flexFlow:"row wrap",
  430. }}>
  431. {
  432. value.list.map((v,k)=>{
  433. let arr = this.state.signProjectId;
  434. let index = arr.findIndex(d=>d == v.id);
  435. let lv = index >= 0;
  436. return (
  437. <Checkbox checked={lv || v.checked} style={{
  438. padding:"0 10px 10px 10px",
  439. marginLeft:'0px',
  440. whiteSpace: 'nowrap'
  441. }} key={k} onChange={(e)=>{
  442. if(e.target.checked){
  443. this.state.signProjectId.push(v.id);
  444. this.state.signProject.push(v.commodityName);
  445. this.setState({
  446. signProjectId:this.state.signProjectId,
  447. signProject:this.state.signProject,
  448. })
  449. }else{
  450. let index = this.state.signProjectId.findIndex(d=>d == v.id);
  451. this.state.signProjectId.splice(index,1);
  452. this.state.signProject.splice(index,1);
  453. this.setState({
  454. signProjectId:this.state.signProjectId,
  455. signProject:this.state.signProject,
  456. })
  457. }
  458. v.checked=e.target.checked
  459. }}>{v.commodityName}</Checkbox>
  460. )
  461. })
  462. }
  463. </div>
  464. </div>
  465. ))
  466. }
  467. {
  468. this.state.removeSelectList.length !== 0 ? <div style={{marginTop:"15px",borderTop:'1px dashed #000'}}>
  469. <div>已删项目(已签)</div>
  470. {
  471. this.state.removeSelectList.map((v,k)=>(
  472. <Checkbox checked={true} disabled={true} style={{paddingRight:"10px"}} key={k}>{v.name}</Checkbox>
  473. ))
  474. }
  475. </div> : ''
  476. }
  477. </Spin>
  478. </div> : null}
  479. <div style={{display:'flex',paddingBottom:"10px"}}>
  480. <div style={{fontWeight:"bolder",paddingRight:'10px'}}>技术端满意度:</div>
  481. <Radio.Group onChange={(e)=>{
  482. this.setState({
  483. techSatisfaction:e.target.value
  484. })
  485. }} value={this.state.techSatisfaction}>
  486. <Radio value={3}>非常满意</Radio>
  487. <Radio value={2}>一般满意</Radio>
  488. <Radio value={1}>不满意</Radio>
  489. <Radio value={0}>已投诉</Radio>
  490. </Radio.Group>
  491. </div>
  492. <div style={{display:'flex',paddingBottom:"10px"}}>
  493. <div style={{fontWeight:"bolder",paddingRight:'10px'}}>业务端满意度:</div>
  494. <Radio.Group onChange={(e)=>{
  495. this.setState({
  496. businessSatisfaction:e.target.value
  497. })
  498. }} value={this.state.businessSatisfaction}>
  499. <Radio value={3}>非常满意</Radio>
  500. <Radio value={2}>一般满意</Radio>
  501. <Radio value={1}>不满意</Radio>
  502. <Radio value={0}>已投诉</Radio>
  503. </Radio.Group>
  504. </div>
  505. <div style={{display:'flex',paddingBottom:"10px"}}>
  506. <div style={{fontWeight:"bolder",paddingRight:'10px'}}><span style={{color:'#f00'}}>*</span>备注:</div>
  507. <div style={{position:"relative"}}>
  508. <Input
  509. placeholder={'请输入备注'}
  510. type='textarea'
  511. rows={4}
  512. maxLength={200}
  513. style={{
  514. width:"400px"
  515. }}
  516. value={this.state.comment}
  517. onChange={(e) => {
  518. this.setState({ comment: e.target.value });
  519. }}
  520. />
  521. <div style={{position:"absolute",zIndex:9999,color:'#a09f9f',bottom:'8px',right:'21px'}}>{this.state.comment.length+'/'+200}</div>
  522. </div>
  523. </div>
  524. </div>
  525. </Spin>
  526. <div style={{display:'flex',justifyContent:'center'}}>
  527. <Button type="primary" size={'large'} style={{marginTop:"10px"}} loading={this.state.preservationLoading || this.state.listLoading} onClick={this.inquiry}>
  528. 提交保存
  529. </Button>
  530. </div>
  531. </div>
  532. )
  533. }
  534. }
  535. export default CustomerServiceRecord;