customer.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. <template>
  2. <div class="hui-flex hui-content">
  3. <div class="customer-test">
  4. <div class="test-item" v-for="(item,index) in $field.field.customerType" :key="item.id">
  5. <div class="name">{{item.name}}</div>
  6. <div class="label alibaba color-cyan">{{countItem(item)}}</div>
  7. </div>
  8. </div>
  9. <div class="customer-line"></div>
  10. <div class="hui-content-title">
  11. <div class="hui-title-item active">客户列表</div>
  12. </div>
  13. <div class="hui-flex-box hui-flex hui-table">
  14. <list-filter type="customer" @filter="filterInit"></list-filter>
  15. <div class="hui-content-insert">
  16. <el-button type="primary" size="medium" @click="insertCustomer">新增客户</el-button>
  17. <el-button type="info" size="medium" @click="downloadFile">标准模板下载</el-button>
  18. <el-button type="info" size="medium" @click="$refs.upload.reloadUpload()">批量导入</el-button>
  19. <customer-upload ref="upload" v-show="false" @changeFile="init"></customer-upload>
  20. </div>
  21. <div class="hui-flex-box">
  22. <el-table :data="tableData" row-key="id" border height="100%">
  23. <el-table-column label="序号" width="50">
  24. <template slot-scope="scope">
  25. <div style="text-align: center;">{{scope.$index + 1}}</div>
  26. </template>
  27. </el-table-column>
  28. <el-table-column label="客户类型">
  29. <template slot-scope="scope">
  30. <span>{{$field.findTypeName('customerType',scope.row.type)}}</span>
  31. </template>
  32. </el-table-column>
  33. <el-table-column label="客户名称" prop="name"></el-table-column>
  34. <el-table-column label="客户行业" prop="customerIndustry"></el-table-column>
  35. <el-table-column label="需求区间" prop="demand"></el-table-column>
  36. <el-table-column label="公海客户">
  37. <template slot-scope="scope">
  38. <div class="hui-table-operation">
  39. <el-switch v-model="scope.row.highSeas" :active-value="1" :inactive-value="2"
  40. @change="val=>putHighSeas(val,scope.row)">
  41. </el-switch>
  42. </div>
  43. </template>
  44. </el-table-column>
  45. <el-table-column label="跟进记录">
  46. <template slot-scope="scope">
  47. <div class="hui-table-operation">
  48. <span class="table-operation" @click="lookCustomer(scope.row,'followUpRecord')">
  49. 查看
  50. </span>
  51. </div>
  52. </template>
  53. </el-table-column>
  54. <el-table-column label="邀请项目">
  55. <template slot-scope="scope">
  56. <div class="hui-table-operation" v-if="!scope.row.status">
  57. <span class="table-operation" @click="inviteCustomer(scope.row)">发送邀请</span>
  58. </div>
  59. <div class="hui-table-operation" v-if="scope.row.status === 3">
  60. <span class="table-operation" @click="inviteCustomer(scope.row)">重新邀请</span>
  61. </div>
  62. </template>
  63. </el-table-column>
  64. <el-table-column label="邀请状态" width="150">
  65. <template slot-scope="scope">
  66. <div v-if="!scope.row.status" class="hui-state">
  67. <span class="hui-state-bage hui-state-primary"></span>
  68. <span class="hui-state-label">待邀请</span>
  69. </div>
  70. <div v-if="scope.row.status == 1" class="hui-state">
  71. <span class="hui-state-bage hui-state-info"></span>
  72. <span class="hui-state-label">邀请中</span>
  73. </div>
  74. <div v-if="scope.row.status == 2" class="hui-state">
  75. <span class="hui-state-bage hui-state-success"></span>
  76. <span class="hui-state-label">通过邀请</span>
  77. </div>
  78. <div v-if="scope.row.status == 3" class="hui-state">
  79. <span class="hui-state-bage hui-state-error"></span>
  80. <span class="hui-state-label">拒绝邀请</span>
  81. </div>
  82. </template>
  83. </el-table-column>
  84. <el-table-column label="操作" width="200">
  85. <template slot-scope="scope">
  86. <div class="hui-table-operation">
  87. <span class="table-operation" @click="lookCustomer(scope.row,'customer')">详情</span>
  88. <span class="table-operation" @click="updateCustomer(scope.row)">编辑</span>
  89. <span class="table-operation" @click="deleteCustomer(scope.row)">删除</span>
  90. </div>
  91. </template>
  92. </el-table-column>
  93. <template slot="empty">
  94. <empty description="暂无数据"></empty>
  95. </template>
  96. </el-table>
  97. </div>
  98. <div class="hui-content-pagination">
  99. <el-pagination :page-size="pageSize" :pager-count="9" layout="prev, pager, next" :total="totalCount"
  100. @current-change="currentChange">
  101. </el-pagination>
  102. </div>
  103. </div>
  104. <el-dialog :close-on-click-modal="false" :title="isUpdate?'编辑':'新增'" :visible.sync="visible" width="900px"
  105. :append-to-body="true">
  106. <edit v-if="visible" @callback="callback" :isUpdate="isUpdate" :detailId="detailId"></edit>
  107. </el-dialog>
  108. <el-drawer :title="type === 'customer'?'客户详情':'跟进列表'" :visible.sync="drawer" :size="400" :append-to-body="true">
  109. <detail v-if="drawer && type === 'customer'" :detailId="detailId"></detail>
  110. <follow-up-record-detail v-if="drawer && type === 'followUpRecord'" :detailId="detailId">
  111. </follow-up-record-detail>
  112. </el-drawer>
  113. </div>
  114. </template>
  115. <script>
  116. import {
  117. getCustomerListByPage,
  118. deleteCustomerById,
  119. updateCustomer,
  120. getCustomerCount
  121. } from '@/httpApi/crm'
  122. import {
  123. testPhone,
  124. bindProjectDetail,
  125. putBindProject
  126. } from '@/httpApi/organization'
  127. import edit from '@/components/work/crm/customer/edit'
  128. import detail from '@/components/work/crm/customer/detail'
  129. import followUpRecordDetail from '@/components/work/crm/customer/followUpRecordDetail'
  130. import listFilter from '@/components/common/listFilter'
  131. import customerUpload from '@/components/work/crm/customer/customerUpload'
  132. import config from '@/config'
  133. export default {
  134. data() {
  135. return {
  136. tableData: [],
  137. currPage: 1,
  138. pageSize: 10,
  139. totalCount: 0,
  140. visible: false,
  141. detailId: '',
  142. isUpdate: false,
  143. drawer: false,
  144. type: 'customer',
  145. filterOption: {},
  146. countBox: []
  147. }
  148. },
  149. created() {
  150. this.init();
  151. },
  152. methods: {
  153. init() {
  154. let postData = {
  155. currPage: this.currPage,
  156. pageSize: this.pageSize,
  157. organizationId: this.$store.getters.organization.id,
  158. projectId: this.$store.getters.project.id,
  159. userId: this.$store.getters.user.userId
  160. }
  161. postData = Object.assign(postData, this.filterOption);
  162. getCustomerListByPage(postData).then(res => {
  163. if (res.state) {
  164. this.tableData = res.data.dataList;
  165. this.totalCount = res.data.totalCount;
  166. }
  167. })
  168. getCustomerCount({
  169. organizationId: this.$store.getters.organization.id,
  170. projectId: this.$store.getters.project.id,
  171. userId: this.$store.getters.user.userId
  172. }).then(res => {
  173. if (res.state) {
  174. this.countBox = res.data;
  175. }
  176. })
  177. },
  178. downloadFile() {
  179. window.location.href = config.baseURL + '/manager/client/downloadModel';
  180. },
  181. countItem(item) {
  182. let list = this.countBox.filter(node => node.type === item.id);
  183. if (list.length === 0) return 0;
  184. return list[0].number;
  185. },
  186. filterInit(option) {
  187. this.filterOption = option;
  188. this.currPage = 1;
  189. this.init();
  190. },
  191. currentChange(currPage) {
  192. this.currPage = currPage;
  193. this.init();
  194. },
  195. insertCustomer() {
  196. this.isUpdate = false;
  197. this.visible = true;
  198. },
  199. updateCustomer(val) {
  200. this.detailId = val.id;
  201. this.isUpdate = true;
  202. this.visible = true;
  203. },
  204. lookCustomer(val, type) {
  205. this.detailId = val.id;
  206. this.type = type;
  207. this.drawer = true;
  208. },
  209. putHighSeas(val, item) {
  210. updateCustomer({
  211. id: item.id,
  212. highSeas: val
  213. }).then(res => {
  214. if (res.state) {
  215. this.init();
  216. this.$message.success('操作成功');
  217. }
  218. })
  219. },
  220. inviteCustomer(user) {
  221. let _self = this;
  222. testPhone(user.phone).then(res => {
  223. if (res.state) {
  224. bindProjectDetail({
  225. organizationId: _self.$store.getters.organization.id,
  226. projectId: _self.$store.getters.project.id,
  227. userId: res.data.id,
  228. identityId: 1
  229. }).then(node => {
  230. if (node.state) {
  231. if (node.data.length > 0) return _self.$message
  232. .warning('该客户已被绑定,不能再次绑定');
  233. _self.$confirm('是否邀请该客户至当前项目?', () => {
  234. _self.$msg.send({
  235. dataId: user.id,
  236. identityId: 1
  237. }, {
  238. messageType: 6,
  239. userIds: res.data.id
  240. }).then(node => {
  241. if (node.state) {
  242. updateCustomer({
  243. id: user.id,
  244. status: 1
  245. }).then(res => {
  246. if (res.state) {
  247. _self.init();
  248. _self.$message.success('邀请成功');
  249. }
  250. })
  251. }
  252. })
  253. });
  254. }
  255. })
  256. } else {
  257. _self.$message.warning('用户不存在,无法邀请');
  258. }
  259. })
  260. },
  261. deleteCustomer(val) {
  262. let _self = this;
  263. _self.$confirm('确定要删除该客户?', () => {
  264. if (val.status == 2) {
  265. bindProjectDetail({
  266. organizationId: _self.$store.getters.organization.id,
  267. projectId: _self.$store.getters.project.id,
  268. clientId: val.id,
  269. identityId: 1
  270. }).then(node => {
  271. if (node.state) {
  272. let data = node.data;
  273. if (data.length === 0) return _self.deleteCustomerFunc(val.id);
  274. putBindProject({
  275. id: data[0].id,
  276. clientId: 0,
  277. userId: 0
  278. }).then(res => {
  279. if (res.state) _self.deleteCustomerFunc(val.id);
  280. })
  281. }
  282. })
  283. } else {
  284. _self.deleteCustomerFunc(val.id);
  285. }
  286. });
  287. },
  288. deleteCustomerFunc(id) {
  289. deleteCustomerById(id).then(res => {
  290. if (res.state) {
  291. this.init();
  292. this.$message.success('操作成功');
  293. }
  294. })
  295. },
  296. callback(type) {
  297. if (type === 'init') this.init();
  298. this.visible = false;
  299. }
  300. },
  301. components: {
  302. edit,
  303. detail,
  304. followUpRecordDetail,
  305. listFilter,
  306. customerUpload
  307. },
  308. }
  309. </script>
  310. <style lang="scss">
  311. .customer-test {
  312. padding: 15px 20px;
  313. display: flex;
  314. .test-item {
  315. border-right: 1px solid $--color-border;
  316. width: 160px;
  317. margin-right: 20px;
  318. .name {
  319. font-size: 12px;
  320. opacity: 0.8;
  321. }
  322. .label {
  323. font-size: 16px;
  324. font-weight: 600;
  325. padding-top: 5px;
  326. }
  327. }
  328. }
  329. .customer-line {
  330. height: 12px;
  331. background: $--background;
  332. }
  333. </style>