list.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <template>
  2. <div class="app-container">
  3. <div class="title-container">
  4. <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
  5. </div>
  6. <y-page-list-layout :page-list="pageData" :page-para="listQuery" :get-page-list="getList">
  7. <template slot="left">
  8. <PermissionButton menu-code="_views_market_business_add" class-name="filter-item" type="primary" name size="mini"
  9. :page-jump="true" round style="float: left" />
  10. <el-input v-model="listQuery.keyword" placeholder="客户名字/客户经理" clearable
  11. style="margin-left: 20px;width: 320px;float: left;">
  12. </el-input>
  13. <el-input v-model="listQuery.opportunityName" placeholder="商机名称" clearable
  14. style="margin-left: 20px;width: 320px;float: left;">
  15. </el-input>
  16. <el-select clearable style="margin-left: 20px;width: 200px;float: left;" v-model="listQuery.state"
  17. placeholder="状态">
  18. <el-option key="0" label="跟进中" value="跟进中" />
  19. <el-option key="1" label="签约" value="签约" />
  20. <el-option key="2" label="终止" value="终止" />
  21. </el-select>
  22. <el-button class="filter-item" style="margin-left: 10px;float: left;" type="primary" @click="searchList" round>搜索
  23. </el-button>
  24. <el-button class="filter-item" style="float: left;" round type="warning" @click="resetSearch()">重置
  25. </el-button>
  26. </template>
  27. <parentTable v-loading="listLoading" :data="pageData.records" slot="table" style="width: 100%;">
  28. <el-table-column label="客户名字" align="center" width="210">
  29. <template slot-scope="{row}">
  30. <span>{{ row.customerName }}</span>
  31. </template>
  32. </el-table-column>
  33. <el-table-column label="商机名称" align="center" width="210">
  34. <template slot-scope="{row}">
  35. <span>{{ row.opportunityName }}</span>
  36. </template>
  37. </el-table-column>
  38. <el-table-column label="预计金额" align="center" width="210">
  39. <template slot-scope="{row}">
  40. <span>{{ row.estimateAmount }}</span>
  41. </template>
  42. </el-table-column>
  43. <el-table-column label="预计开展日期" align="center" width="210">
  44. <template slot-scope="{row}">
  45. <span>{{ row.estimateDate }}</span>
  46. </template>
  47. </el-table-column>
  48. <el-table-column label="状态" align="center" width="120">
  49. <template slot-scope="{row}">
  50. <el-tag>{{ row.state }}</el-tag>
  51. </template>
  52. </el-table-column>
  53. <el-table-column label="终止原因" align="center" width="210">
  54. <template slot-scope="{row}">
  55. <span>{{ row.offReason }}</span>
  56. </template>
  57. </el-table-column>
  58. <el-table-column label="客户经理" align="center" width="210">
  59. <template slot-scope="{row}">
  60. <span>{{ row.userName }}</span>
  61. </template>
  62. </el-table-column>
  63. <el-table-column label="备注" align="center" width="210">
  64. <template slot-scope="{row}">
  65. <span>{{ row.remark }}</span>
  66. </template>
  67. </el-table-column>
  68. <el-table-column label="操作" align="center" width="300" fixed="right">
  69. <template slot-scope="{row}">
  70. <PermissionButton menu-code="_views_market_business_detail" class-name="filter-item" name="" type="primary"
  71. :page-jump="true" :page-query="{ id: row.id, listQuery: listQuery }" round size="mini" />
  72. <PermissionButton menu-code="_views_market_business_state" class-name="filter-item" name="" type="danger"
  73. round size="mini" @click="handleState(row)" />
  74. <PermissionButton menu-code="_views_market_business_transfer" class-name="filter-item" name="" type="success"
  75. round size="mini" @click="openTransferDialog(row)" />
  76. </template>
  77. </el-table-column>
  78. </parentTable>
  79. </y-page-list-layout>
  80. <el-dialog width="600px" title="状态流转" :visible.sync="dialogFormVisible" :close-on-click-modal="false">
  81. <el-form ref="dataForm" v-loading="dialogLoading" :model="temp" label-position="right" label-width="110px"
  82. style="width: 400px; margin-left:50px;">
  83. <el-form-item label="商机名称:" prop="name">
  84. <el-input v-model="temp.opportunityName" class="filter-item" readonly disabled />
  85. </el-form-item>
  86. <el-form-item label="流转状态:" filterable prop="departmentId">
  87. <el-select v-model="temp.state" filterable class="filter-item" style="float: left;width: 100%;"
  88. placeholder="请选择">
  89. <el-option key="0" label="跟进中" value="跟进中" />
  90. <el-option key="1" label="签约" value="签约" />
  91. <el-option key="2" label="终止" value="终止" />
  92. </el-select>
  93. </el-form-item>
  94. <el-form-item label="终止原因:">
  95. <el-input v-model="temp.offReason" class="filter-item" type="text" />
  96. </el-form-item>
  97. <el-form-item label="">
  98. <el-button @click="dialogFormVisible = false">
  99. 取消
  100. </el-button>
  101. <el-button type="primary" @click="updateState()">
  102. 保存
  103. </el-button>
  104. </el-form-item>
  105. </el-form>
  106. </el-dialog>
  107. <el-dialog :visible.sync="dialogFormVisibleX" :close-on-click-modal="false" custom-class="tansferDialog">
  108. <div class="detail">
  109. <el-divider content-position="left">项目信息</el-divider>
  110. <el-descriptions :column="4" size="lager" border>
  111. <el-descriptions-item label="客户名字">{{ detail.customerName }}</el-descriptions-item>
  112. <el-descriptions-item label="商机名称">{{ detail.opportunityName }}</el-descriptions-item>
  113. <el-descriptions-item label="预计金额">{{ detail.estimateAmount }}</el-descriptions-item>
  114. <el-descriptions-item label="预计开展日期">{{ detail.estimateDate }}</el-descriptions-item>
  115. <el-descriptions-item label="状态">{{ detail.state }}</el-descriptions-item>
  116. <el-descriptions-item label="客户经理">
  117. <el-select v-model="detail.userId">
  118. <el-option v-for="(item, index) in managers" :key="index" :label="item.name" :value="item.id"></el-option>
  119. </el-select>
  120. <el-tooltip class="item" effect="dark" content="点击转交" placement="bottom-start">
  121. <el-button type="success" icon="el-icon-check" circle style="margin-left: 20px;" placeholder="转交"
  122. @click="saveManager"></el-button>
  123. </el-tooltip>
  124. </el-descriptions-item>
  125. <el-descriptions-item label="终止原因">{{ detail.offReason }}</el-descriptions-item>
  126. </el-descriptions>
  127. </div>
  128. <div class="histroy">
  129. <el-divider content-position="left">转交记录</el-divider>
  130. <el-collapse v-model="activeNames">
  131. <el-collapse-item name="1">
  132. <el-timeline>
  133. <el-timeline-item v-for="item in historys" :key="item.id" :timestamp="item.created" placement="top">
  134. <el-card>
  135. <el-descriptions :column="3" border>
  136. <el-descriptions-item label="前客户经理"><el-tag type="info">{{ item.originalUserName
  137. }}</el-tag></el-descriptions-item>
  138. <el-descriptions-item label="后客户经理"><el-tag type="success">{{ item.currentUserName
  139. }}</el-tag></el-descriptions-item>
  140. <el-descriptions-item label="操作人"><el-tag>{{ item.operatorName }}</el-tag></el-descriptions-item>
  141. </el-descriptions>
  142. </el-card>
  143. </el-timeline-item>
  144. </el-timeline>
  145. </el-collapse-item>
  146. </el-collapse>
  147. </div>
  148. </el-dialog>
  149. </div>
  150. </template>
  151. <script>
  152. import YPageListLayout from '@/components/YPageListLayout'
  153. import Breadcrumb from '@/components/Breadcrumb'
  154. import PermissionButton from '@/components/PermissionButton/PermissionButton'
  155. export default {
  156. name: 'ViewsMarketBusinessList',
  157. components: {
  158. Breadcrumb,
  159. YPageListLayout,
  160. PermissionButton,
  161. },
  162. filters: {
  163. statusFilter(status) {
  164. const statusMap = {
  165. published: 'success',
  166. draft: 'info',
  167. deleted: 'danger',
  168. }
  169. return statusMap[status]
  170. },
  171. },
  172. data() {
  173. return {
  174. isDisable: false,
  175. tableKey: 0,
  176. pageData: { records: [] },
  177. total: 20,
  178. dialogLoading: false,
  179. listLoading: true,
  180. listQuery: {
  181. page: 1,
  182. size: 10,
  183. descs: 'id',
  184. keyword: null
  185. },
  186. listQueryKey: 'keyword',
  187. importLoading: false,
  188. AllEnum: [],
  189. dialogFormVisible: false,
  190. temp: {},
  191. dialogFormVisibleX: false,
  192. detail: {},
  193. activeNames: ['1'],
  194. historys: [],
  195. managers: [],
  196. }
  197. },
  198. created() {
  199. const that = this;
  200. if (that.$route.query.current && !isNaN(that.$route.query.current)) {
  201. that.listQuery.current = parseInt(that.$route.query.current);
  202. }
  203. if (that.$route.query.customerName) {
  204. that.listQuery.customerName = that.$route.query.customerName;
  205. }
  206. if (that.$route.query.opportunityName) {
  207. that.listQuery.opportunityName = that.$route.query.opportunityName;
  208. }
  209. if (that.$route.query.state) {
  210. that.listQuery.state = that.$route.query.state;
  211. }
  212. that.getAllEnum();
  213. that.getList();
  214. },
  215. methods: {
  216. handleState(row) {
  217. this.temp = row;
  218. // that.temp.id = row.businessId;
  219. // that.temp.opportunityName = row.businessName;
  220. // that.temp.state = row.state;
  221. // that.temp.offReason = row.offReason;
  222. this.dialogFormVisible = true;
  223. },
  224. updateState() {
  225. if (this.temp.id) {
  226. this.$api.business.edit(Object.assign({}, this.temp, {
  227. })).then(res => {
  228. if (res.code === 200) {
  229. this.$notify({
  230. title: '成功',
  231. message: '状态流转成功',
  232. type: 'success',
  233. duration: 2000
  234. });
  235. this.dialogFormVisible = false;
  236. if (this.temp.state === "签约") {
  237. this.temp.id = null;
  238. this.$router.push({ path: "/item/transfer", query: this.temp })
  239. }
  240. }
  241. }).catch(() => {
  242. this.dialogFormVisible = false;
  243. })
  244. }
  245. },
  246. getAllEnum() {
  247. const that = this;
  248. that.$api.globalConfig.getAllEnum().then(data => {
  249. if (data.code === 200) {
  250. that.AllEnum = data.data
  251. } else {
  252. this.$message({
  253. type: 'error',
  254. message: data.msg
  255. })
  256. }
  257. })
  258. },
  259. resetSearch() {
  260. this.$router.push({ query: {} });
  261. this.listQuery = {
  262. current: 1,
  263. size: 10,
  264. descs: 'id',
  265. }
  266. this.getList()
  267. },
  268. removeHandle(row) {
  269. // console.log(data)
  270. const that = this
  271. that
  272. .$confirm('确认删除当前记录吗?', '警告', {
  273. confirmButtonText: '确认',
  274. cancelButtonText: '取消',
  275. type: 'warning',
  276. })
  277. .then(async () => {
  278. this.$api.business.delete(row.id).then((res) => {
  279. if (res.code === 200) {
  280. this.$message({
  281. type: 'success',
  282. message: '删除成功',
  283. })
  284. this.getList()
  285. }
  286. })
  287. })
  288. .catch((err) => {
  289. console.error(err)
  290. })
  291. },
  292. searchList() {
  293. // 重置分页
  294. this.listQuery.page = 1
  295. this.listQuery.size = 10
  296. this.getList()
  297. },
  298. getList() {
  299. const that = this
  300. this.listLoading = true
  301. // console.log(that.listQuery)
  302. this.$api.business
  303. .list(Object.assign({}, that.listQuery))
  304. .then((res) => {
  305. that.pageData = res.data
  306. setTimeout(() => {
  307. that.listLoading = false
  308. }, 200)
  309. })
  310. .catch(() => {
  311. that.listLoading = false
  312. })
  313. },
  314. deleteInfo(id) {
  315. const that = this
  316. that.$confirm('请确认是否删除该数据?', '提示', {
  317. confirmButtonText: '确定',
  318. cancelButtonText: '取消',
  319. type: 'warning',
  320. center: true
  321. }).then(() => {
  322. that.$api.business.delete(id).then(data => {
  323. that.loading = false
  324. if (data.code === 200) {
  325. that.getList()
  326. } else {
  327. this.$message({
  328. type: 'error',
  329. message: data.msg
  330. })
  331. }
  332. })
  333. }).catch(() => {
  334. })
  335. },
  336. openTransferDialog(row) {
  337. const originalUserId = row.userId;
  338. this.dialogFormVisibleX = true;
  339. this.detail = row;
  340. this.detail.originalUserId = originalUserId;
  341. this.getHistroyList(row.id);
  342. this.getManagers();
  343. },
  344. getManagers() {
  345. this.$api.user.usersByDepartment("市场部").then(res => {
  346. this.managers = res.data
  347. })
  348. },
  349. getHistroyList(id) {
  350. this.$api.resourceTransfer.history({ "resourceType": "BUSINESS_OPPORTUNITY", "resourceId": id }).then(res => {
  351. if (res.code === 200) {
  352. this.historys = res.data;
  353. }
  354. })
  355. },
  356. saveManager() {
  357. if (this.detail.userId === this.detail.originalUserId) {
  358. this.$message({
  359. type: 'error',
  360. message: '抱歉,不能转交给本人。'
  361. });
  362. return;
  363. }
  364. this.$api.business.changeManager(this.detail).then(res => {
  365. if (res.code === 200 && res.data === true) {
  366. this.$message({
  367. type: 'success',
  368. message: '转交成功'
  369. });
  370. this.getHistroyList(this.detail.id);
  371. }
  372. }
  373. );
  374. },
  375. },
  376. }
  377. </script>
  378. <style lang="scss" scoped>
  379. .right {
  380. flex: 1;
  381. .title {
  382. font-size: 16px;
  383. font-weight: 500;
  384. color: rgba(51, 51, 51, 1);
  385. line-height: 35px;
  386. margin-bottom: 8px;
  387. }
  388. .menu-2-box {
  389. display: flex;
  390. flex-wrap: wrap;
  391. width: 100%;
  392. }
  393. .menu-2-item {
  394. display: flex;
  395. align-items: center;
  396. color: #656565;
  397. font-size: 12px;
  398. width: 230px;
  399. height: 101px;
  400. background: rgb(255, 185, 129);
  401. border-radius: 3px;
  402. padding-left: 20px;
  403. margin-right: 10px;
  404. margin-bottom: 10px;
  405. cursor: pointer;
  406. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  407. .text {
  408. margin-left: 16px;
  409. }
  410. }
  411. }
  412. /deep/ .tansferDialog {
  413. width: 60%;
  414. border-radius: 10px;
  415. }
  416. .el-dropdown-link {
  417. cursor: pointer;
  418. color: red;
  419. }
  420. .el-icon-arrow-down {
  421. font-size: 12px;
  422. }
  423. </style>