customerServiceRecord.jsx 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  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+')' : ''
  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,
  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'}}><span style={{color:'#f00'}}>*</span>续签时间:</div>
  400. <DatePicker
  401. value={this.state.releaseDate ? moment(this.state.releaseDate) : null}
  402. onChange={(data, dataString) => {
  403. this.setState({ releaseDate: dataString });
  404. }}
  405. />
  406. </div> : null}
  407. {this.state.situation === 6 ? <div style={{paddingBottom:"10px"}}>
  408. <div style={{fontWeight:"bolder",paddingRight:'10px',paddingBottom:'15px',whiteSpace:"nowrap"}}>已签项目:</div>
  409. <Spin spinning={this.state.selectLoading}>
  410. {
  411. this.state.selectUidByprojectList.map((value,key)=>(
  412. <div key={key} style={{
  413. paddingBottom:'10px',
  414. display:'flex',
  415. flexFlow:"row nowrap",
  416. alignItems:'flex-start',
  417. padding:'10px 5px 0 5px',
  418. background:key % 2 === 0 ? '#afacad' : '#fff',
  419. color:key % 2 === 0 ? '#fff' : '#000',
  420. borderRadius: '4px',
  421. }}>
  422. <div style={{whiteSpace:"nowrap",paddingBottom:'10px'}}>{value.orderNo+':'}</div>
  423. <div style={{
  424. flex:1,
  425. display:'flex',
  426. flexFlow:"row wrap",
  427. }}>
  428. {
  429. value.list.map((v,k)=>{
  430. let arr = this.state.signProjectId;
  431. let index = arr.findIndex(d=>d == v.id);
  432. let lv = index >= 0;
  433. return (
  434. <Checkbox checked={lv || v.checked} style={{
  435. padding:"0 10px 10px 10px",
  436. marginLeft:'0px',
  437. whiteSpace: 'nowrap'
  438. }} key={k} onChange={(e)=>{
  439. if(e.target.checked){
  440. this.state.signProjectId.push(v.id);
  441. this.state.signProject.push(v.commodityName);
  442. this.setState({
  443. signProjectId:this.state.signProjectId,
  444. signProject:this.state.signProject,
  445. })
  446. }else{
  447. let index = this.state.signProjectId.findIndex(d=>d == v.id);
  448. this.state.signProjectId.splice(index,1);
  449. this.state.signProject.splice(index,1);
  450. this.setState({
  451. signProjectId:this.state.signProjectId,
  452. signProject:this.state.signProject,
  453. })
  454. }
  455. v.checked=e.target.checked
  456. }}>{v.commodityName}</Checkbox>
  457. )
  458. })
  459. }
  460. </div>
  461. </div>
  462. ))
  463. }
  464. {
  465. this.state.removeSelectList.length !== 0 ? <div style={{marginTop:"15px",borderTop:'1px dashed #000'}}>
  466. <div>已删项目(已签)</div>
  467. {
  468. this.state.removeSelectList.map((v,k)=>(
  469. <Checkbox checked={true} disabled={true} style={{paddingRight:"10px"}} key={k}>{v.name}</Checkbox>
  470. ))
  471. }
  472. </div> : ''
  473. }
  474. </Spin>
  475. </div> : null}
  476. <div style={{display:'flex',paddingBottom:"10px"}}>
  477. <div style={{fontWeight:"bolder",paddingRight:'10px'}}>技术端满意度:</div>
  478. <Radio.Group onChange={(e)=>{
  479. this.setState({
  480. techSatisfaction:e.target.value
  481. })
  482. }} value={this.state.techSatisfaction}>
  483. <Radio value={3}>非常满意</Radio>
  484. <Radio value={2}>一般满意</Radio>
  485. <Radio value={1}>不满意</Radio>
  486. <Radio value={0}>已投诉</Radio>
  487. </Radio.Group>
  488. </div>
  489. <div style={{display:'flex',paddingBottom:"10px"}}>
  490. <div style={{fontWeight:"bolder",paddingRight:'10px'}}>业务端满意度:</div>
  491. <Radio.Group onChange={(e)=>{
  492. this.setState({
  493. businessSatisfaction:e.target.value
  494. })
  495. }} value={this.state.businessSatisfaction}>
  496. <Radio value={3}>非常满意</Radio>
  497. <Radio value={2}>一般满意</Radio>
  498. <Radio value={1}>不满意</Radio>
  499. <Radio value={0}>已投诉</Radio>
  500. </Radio.Group>
  501. </div>
  502. <div style={{display:'flex',paddingBottom:"10px"}}>
  503. <div style={{fontWeight:"bolder",paddingRight:'10px'}}><span style={{color:'#f00'}}>*</span>备注:</div>
  504. <div style={{position:"relative"}}>
  505. <Input
  506. placeholder={'请输入备注'}
  507. type='textarea'
  508. rows={3}
  509. maxLength={64}
  510. style={{
  511. width:"400px"
  512. }}
  513. value={this.state.comment}
  514. onChange={(e) => {
  515. this.setState({ comment: e.target.value });
  516. }}
  517. />
  518. <div style={{position:"absolute",zIndex:9999,color:'#a09f9f',bottom:'8px',right:'21px'}}>{this.state.comment.length+'/'+64}</div>
  519. </div>
  520. </div>
  521. </div>
  522. </Spin>
  523. <div style={{display:'flex',justifyContent:'center'}}>
  524. <Button type="primary" size={'large'} style={{marginTop:"10px"}} loading={this.state.preservationLoading || this.state.listLoading} onClick={this.inquiry}>
  525. 提交保存
  526. </Button>
  527. </div>
  528. </div>
  529. )
  530. }
  531. }
  532. export default CustomerServiceRecord;