足力健前端,vue版本

index.vue 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. <template>
  2. <div class="app-container">
  3. <search-filter :search-datas.sync="searchDatas" :selected-id="selectedId" showadd @transfer="btn_transfer" @search="btn_search" @delorders="btn_deletes" @export="btn_export" @merge="btn_file_merge" @split="btn_file_split" />
  4. <el-tabs v-model="activeName" type="card" @tab-click="handleTabClick">
  5. <el-tab-pane label="全部" name="0" />
  6. <el-tab-pane label="已联系客户" name="1" />
  7. <el-tab-pane label="未联系客户" name="2" />
  8. </el-tabs>
  9. <el-table v-loading="loading" :data="dataLists" border stripe @selection-change="changeSelects">
  10. <el-table-column type="selection" width="40" fixed />
  11. <el-table-column prop="F_Name" label="客户姓名" align="center" width="" />
  12. <el-table-column prop="F_Sex" label="客户性别" align="center" width="" />
  13. <el-table-column prop="F_Age" label="客户年龄" align="center" width="" />
  14. <el-table-column label="主号码" align="center" width="100px">
  15. <template slot-scope="scope">
  16. {{ scope.row.F_Phone | phoneFilter }}
  17. <i v-if="scope.row.F_Phone" class="el-icon-tickets phoneIcon" @click="clickCut(scope.row.F_ID)" />
  18. <i v-if="scope.row.F_Phone" class="el-icon-phone phoneIcon" @click="clickCallOut(scope.row.F_Phone)" />
  19. </template>
  20. </el-table-column>
  21. <el-table-column label="备用号码" align="center" width="">
  22. <template slot-scope="scope">
  23. {{ scope.row.F_Mobile | mobileFilter }}
  24. <i v-if="scope.row.F_Mobile" class="el-icon-tickets phoneIcon" @click="clickCut2(scope.row.F_ID)" />
  25. <i v-if="scope.row.F_Mobile" class="el-icon-phone phoneIcon" @click="clickMobile(scope.row.F_Mobile)" />
  26. </template>
  27. </el-table-column>
  28. <el-table-column prop="F_Label" label="会员标签" align="center" width="" />
  29. <el-table-column prop="F_Membership" label="会员类型" align="center" width="" />
  30. <el-table-column prop="F_Class" label="会员分类" align="center" width="" />
  31. <el-table-column prop="F_ShoeSize" label="鞋码" align="center" width="" />
  32. <el-table-column prop="Birthday" label="会员生日" align="center" width="100px" />
  33. <el-table-column prop="F_Score" label="会员积分" align="center" width="" />
  34. <el-table-column prop="F_Recommender" label="推荐人" align="center" width="" />
  35. <el-table-column prop="F_Saleperson" label="销售负责人" align="center" width="90px" />
  36. <el-table-column prop="F_Money" label="累计消费金额" align="center" width="" />
  37. <el-table-column prop="F_Firstcalltime" label="首次通话记录" align="center" width="" />
  38. <el-table-column prop="F_Lastholetime" label="末联通话记录" align="center" width="" />
  39. <el-table-column prop="F_TotalScore" label="累计积分" align="center" width="" />
  40. <el-table-column prop="F_Money" label="总金额" align="center" width="" />
  41. <el-table-column label="地址" align="center" min-width="180">
  42. <template slot-scope="scope">{{ scope.row | judgmentAddress }}</template>
  43. </el-table-column>
  44. <el-table-column prop="F_Count" label="购买次数" align="center" width="" />
  45. <el-table-column prop="F_CreateOn" label="建档日期" align="center" width="" />
  46. <el-table-column label="操作" width="180" align="center" class-name="oparate_btn" fixed="right">
  47. <template slot-scope="scope">
  48. <el-button v-permission="'HY_add_order'" type="text" @click="btn_add_order(scope.row.F_ID)">添加订单</el-button>
  49. <el-button v-permission="'HY_addTodo'" type="text" @click="btn_addTodo(scope.row.F_Phone, scope.row.F_Name)">添加待办</el-button>
  50. <el-button v-permission="'HY_detail'" type="text" @click="btn_detail(scope.row.F_ID.toString())">详情</el-button>
  51. <el-button v-permission="'HY_edit'" type="text" @click="btn_edit(scope.row.F_ID)">编辑</el-button>
  52. <el-button v-permission="'HY_add_remark'" type="text" @click="btn_add_remark(scope.row.F_ID)">备注</el-button>
  53. <el-button v-permission="'HY_delete'" type="text" @click="btn_delete(scope.row.F_ID)">删除</el-button>
  54. </template>
  55. </el-table-column>
  56. </el-table>
  57. <pagination v-show="pageParams.total > 0" :total="pageParams.total" :pageindex.sync="pageParams.pageindex" :pagesize.sync="pageParams.pagesize" class="pagination" @pagination="getList" />
  58. </div>
  59. </template>
  60. <script>
  61. import { mapGetters } from "vuex"
  62. import { getOrderLists, deleteOrder, deletesMember, encryptphone, split } from "@/api/memberManagement/memberList"
  63. import searchFilter from "./components/searchFilter"
  64. import addOrEdit from "./components/addOrEdit"
  65. import addTodo from "./components/addTodo"
  66. import callOut from "./components/callOut"
  67. import detail from "./components/detail"
  68. import transfer from "./components/transfer"
  69. import addOrder from "./components/addOrder"
  70. import addOrEditRemark from "./components/addOrEditRemark"
  71. import { formatterContent } from "@/utils"
  72. import Pagination from "@/components/Pagination" // 对el-pagination 二次封装
  73. import mergeId from "./components/mergeId"
  74. import { getCallOutprefix } from "@/api/teloperation"
  75. import { Send } from "@/utils/telWebsocket"
  76. import store from "@/store"
  77. export default {
  78. name: "MemberLabel",
  79. components: {
  80. Pagination,
  81. searchFilter,
  82. },
  83. filters: {
  84. phoneFilter(status) {
  85. if (status) {
  86. const mtel = status.substr(0, 3) + "****" + status.substr(7)
  87. return mtel
  88. }
  89. },
  90. mobileFilter(status) {
  91. if (status) {
  92. const arr = status.split(",")
  93. var mtel = ""
  94. for (let i = 0; i < arr.length; i++) {
  95. mtel += arr[i].substr(0, 3) + "****" + arr[i].substr(7) + ","
  96. }
  97. return mtel.substr(0, mtel.length - 1)
  98. }
  99. },
  100. judgmentAddress(data) {
  101. const addProvince = data.F_Province === null ? "" : data.F_Province // 省
  102. const addCity = data.F_City === null ? "" : data.F_City // 市
  103. const addArea = data.F_Area === null ? "" : data.F_Area // 县/区
  104. const addTown = data.F_Town === null ? "" : data.F_Town // 乡/镇
  105. const address = data.F_Address === null ? "" : data.F_Address // 详细地址
  106. const addressStr = addProvince + addCity + addArea + addTown + address // 地址
  107. return addressStr
  108. },
  109. },
  110. data() {
  111. return {
  112. phoneOne: "", // 加密主号码
  113. phoneOne2: "", // 加密备用号码
  114. phoneNumOne: "",
  115. searchDatas: {
  116. VIPCode: "", // 会员卡编号
  117. customerName: "", // 客户姓名
  118. phoneNumber: "", // 手机号码
  119. labelList: "", // 会员标签
  120. province: "", // 省份
  121. city: "", // 市
  122. county: "", // 县区
  123. township: "", // 乡镇
  124. address: "", // 详细地址
  125. birthday: "", // 会员生日
  126. referrer: "", // 推荐人
  127. saleperson: "", // 销售负责人
  128. // contactFrequency: '', //联系频次
  129. provinceCity: [], // 省市下拉绑定的值
  130. provinceCityText: [], // 省市下拉绑定文本值
  131. memberBirthday: [], // 会员生日
  132. contactTime: [],
  133. membership: "", //会员类型
  134. class: "", // 会员分类
  135. searchTime: [], //建档日期
  136. firstcalltime: [], // 首次通话时间
  137. lastholetime: [], // 末联通话时间
  138. },
  139. loading: false,
  140. pageParams: {
  141. pageindex: 1, // 当前第几页
  142. pagesize: Number(this.$store.getters.serverConfig.PAGESIZE), // 每页几条数据
  143. total: 0, // 总共多少数据
  144. },
  145. dataLists: [], // 列表数据
  146. multipleSelection: [], // 选中的数据
  147. selectedId: [], // 选中的id
  148. namesData: [],
  149. activeName: "0",
  150. }
  151. },
  152. created() {
  153. this.getList()
  154. document.onkeyup = (e) => {
  155. if (e.keyCode === 13) {
  156. this.getList()
  157. }
  158. }
  159. },
  160. computed: {
  161. ...mapGetters([
  162. "token",
  163. "usercode", // 工号
  164. "extension", // 分机号
  165. "sidebar",
  166. "avatar",
  167. "telCallType", // 通话类型
  168. "telIsVisCallout", // 外呼面板是否显示
  169. ]),
  170. },
  171. methods: {
  172. getList() {
  173. this.loading = true
  174. return new Promise((resolve) => {
  175. const params = {
  176. pageindex: this.pageParams.pageindex, // int 第几页
  177. pagesize: this.pageParams.pagesize, // int 每页几条信息
  178. name: this.searchDatas.customerName.trim(), // 客户姓名
  179. phone: this.searchDatas.phoneNumber.trim(), // 手机号码
  180. label: this.searchDatas.labelList, // 会员标签
  181. province: this.searchDatas.provinceCityText && this.searchDatas.provinceCityText[0], // 省份
  182. city: this.searchDatas.provinceCityText[1] && this.searchDatas.provinceCityText[1], // 市
  183. area: this.searchDatas.provinceCityText[2] && this.searchDatas.provinceCityText[2], // 县区
  184. town: this.searchDatas.provinceCityText[3] && this.searchDatas.provinceCityText[3], // 乡镇
  185. address: this.searchDatas.address.trim(), // 详细地址
  186. SearchStartTime: this.searchDatas.memberBirthday && this.searchDatas.memberBirthday[0], // 会员生日
  187. SearchEndTime: this.searchDatas.memberBirthday && this.searchDatas.memberBirthday[1], // 会员生日
  188. recommender: this.searchDatas.referrer.trim(), // 推荐人
  189. saleperson: this.searchDatas.saleperson.trim(), // 销售负责人
  190. laststartholetime: this.searchDatas.contactTime[0] == undefined ? "" : this.searchDatas.contactTime[0],
  191. Lastendholetime: this.searchDatas.contactTime[1] == undefined ? "" : this.searchDatas.contactTime[1],
  192. F_Membership: this.searchDatas.membership, // 会员类型
  193. F_Class: this.searchDatas.class, // 会员分类
  194. AddStartTime: this.searchDatas.searchTime && this.searchDatas.searchTime[0], // 建档日期
  195. AddEndTime: this.searchDatas.searchTime && this.searchDatas.searchTime[1], // 建档日期
  196. Firststartcalltime: this.searchDatas.firstcalltime && this.searchDatas.firstcalltime[0], // 首次通话时间
  197. Firstendcalltime: this.searchDatas.firstcalltime && this.searchDatas.firstcalltime[1], // 首次通话时间
  198. laststartholetime: this.searchDatas.lastholetime && this.searchDatas.lastholetime[0], // 末联通话时间
  199. lastendholetime: this.searchDatas.lastholetime && this.searchDatas.lastholetime[1], // 末联通话时间
  200. // contact: this.searchDatas.contactFrequency.trim(), //联系频次
  201. }
  202. getOrderLists(params).then((response) => {
  203. this.loading = false
  204. if (response.state.toLowerCase() === "success") {
  205. this.pageParams.total = response.rows.Totals
  206. this.dataLists = response.rows.Rows
  207. }
  208. })
  209. resolve()
  210. })
  211. },
  212. handleTabClick() {
  213. this.pageParams.pageindex = 1
  214. let date = new Date()
  215. date.setTime(date.getTime() - 24 * 60 * 60 * 1000)
  216. const year = date.getFullYear()
  217. let month = date.getMonth() + 1
  218. const day = date.getDate()
  219. const hour = "00:00:00"
  220. month = month.toString().padStart(2, "0")
  221. date = date.toString().padStart(2, "0")
  222. const defaultDate = `${year}-${month}-${day} ${hour}`
  223. if (this.activeName == 2) {
  224. this.searchDatas.contactTime = ["", defaultDate]
  225. } else if (this.activeName == 1) {
  226. this.searchDatas.contactTime = ["1970-01-01 00:00:00", defaultDate]
  227. } else {
  228. this.searchDatas.contactTime = ["", ""]
  229. }
  230. this.getList()
  231. },
  232. btn_search(val, data) {
  233. this.searchDatas.provinceCityText = data
  234. this.pageParams.pageindex = 1
  235. this.getList()
  236. },
  237. btn_export(val, data) {
  238. this.searchDatas.provinceCityText = data
  239. window.location.href =
  240. this.$store.getters.serverConfig.BASE_API +
  241. "api/vipinfo/exportexcel?name=" +
  242. this.searchDatas.customerName +
  243. "&phone=" +
  244. this.searchDatas.phoneNumber + // 手机号码
  245. "&province=" +
  246. (this.searchDatas.provinceCityText.length > 0 ? this.searchDatas.provinceCityText[0] : "") +
  247. "&city=" +
  248. (this.searchDatas.provinceCityText.length > 1 ? this.searchDatas.provinceCityText[1] : "") +
  249. "&area=" +
  250. (this.searchDatas.provinceCityText.length > 2 ? this.searchDatas.provinceCityText[2] : "") +
  251. "&town=" +
  252. (this.searchDatas.provinceCityText.length > 3 ? this.searchDatas.provinceCityText[3] : "") +
  253. "&label=" +
  254. this.searchDatas.labelList + // 会员类型
  255. "&address=" +
  256. this.searchDatas.address + // 地址
  257. "&recommender=" +
  258. this.searchDatas.referrer + // 推荐人
  259. "&saleperson=" +
  260. this.searchDatas.saleperson + // 销售负责人
  261. // '&token=' + this.token +
  262. "&birthday=" +
  263. this.searchDatas.birthday
  264. },
  265. clickMobile(number) {
  266. this.$layer.iframe({
  267. content: {
  268. content: callOut, // 传递的组件对象
  269. parent: this, // 当前的vue对象
  270. data: { rowid: number }, // props
  271. },
  272. area: ["30%", "30%"],
  273. title: "外呼",
  274. })
  275. },
  276. btn_detail(editId) {
  277. this.$layer.iframe({
  278. content: {
  279. content: detail, // 传递的组件对象
  280. parent: this, // 当前的vue对象
  281. data: { rowid: editId }, // props
  282. },
  283. area: ["80%", "90%"],
  284. title: "详情",
  285. })
  286. },
  287. btn_edit(editId) {
  288. this.$layer.iframe({
  289. content: {
  290. content: addOrEdit, // 传递的组件对象
  291. parent: this, // 当前的vue对象
  292. data: { rowid: editId.toString() }, // props
  293. },
  294. area: ["80%", "90%"],
  295. title: "编辑会员信息",
  296. })
  297. },
  298. // 添加订单
  299. btn_add_order(id) {
  300. this.$layer.iframe({
  301. content: {
  302. content: addOrder, // 传递的组件对象
  303. parent: this, // 当前的vue对象
  304. data: { rowid: id.toString() }, // props
  305. },
  306. area: ["80%", "90%"],
  307. title: "添加订单",
  308. })
  309. },
  310. // 添加待办
  311. btn_addTodo(phone, name) {
  312. this.$layer.iframe({
  313. content: {
  314. content: addTodo, // 传递的组件对象
  315. parent: this, // 当前的vue对象
  316. data: { rowPhone: phone, rowName: name }, // props
  317. },
  318. area: ["40%", "70%"],
  319. title: "添加待办信息",
  320. })
  321. },
  322. // 批量删除
  323. btn_deletes() {
  324. if (this.selectedId.length == 0) {
  325. this.$message("请选择一个选项")
  326. return
  327. } else {
  328. this.$confirm("您确定要删除吗?", "提示", {
  329. confirmButtonText: "确定",
  330. cancelButtonText: "取消",
  331. type: "warning",
  332. })
  333. .then(() => {
  334. deletesMember(this.selectedId).then((response) => {
  335. if (response.state.toLowerCase() === "success") {
  336. this.getList()
  337. this.$message.success("删除成功!")
  338. }
  339. })
  340. })
  341. .catch(() => {
  342. this.$message.info("已取消删除")
  343. })
  344. }
  345. },
  346. // 档案合并
  347. btn_file_merge() {
  348. if (this.selectedId.length <= 1 || this.selectedId.length > 2) {
  349. this.$message("请选择两个选项")
  350. return
  351. } else {
  352. this.$layer.iframe({
  353. content: {
  354. content: mergeId, // 传递的组件对象
  355. parent: this, // 当前的vue对象
  356. data: { name: this.namesData, ids: this.selectedId }, // props
  357. },
  358. area: ["40%", "70%"],
  359. title: "选择主档案",
  360. })
  361. }
  362. },
  363. // 档案拆分
  364. btn_file_split() {
  365. if (this.selectedId.length == 0) {
  366. this.$message("请选择一个选项")
  367. return
  368. } else {
  369. this.$confirm("您确定要拆分吗?", "提示", {
  370. confirmButtonText: "确定",
  371. cancelButtonText: "取消",
  372. type: "warning",
  373. })
  374. .then(() => {
  375. const params = {
  376. id: this.selectedId[0],
  377. }
  378. split(params).then((response) => {
  379. if (response.state.toLowerCase() === "success") {
  380. this.getList()
  381. this.$message.success("拆分成功!")
  382. }
  383. })
  384. })
  385. .catch(() => {
  386. this.$message.info("已取消拆分")
  387. })
  388. }
  389. },
  390. // 转移
  391. btn_transfer() {
  392. if (this.selectedId.length == 0) {
  393. this.$message("请选择一个选项")
  394. return
  395. } else {
  396. this.$layer.iframe({
  397. content: {
  398. content: transfer, // 传递的组件对象
  399. parent: this, // 当前的vue对象
  400. data: { rowid: this.selectedId }, // props
  401. },
  402. area: ["40%", "40%"],
  403. title: "转移档案",
  404. })
  405. }
  406. },
  407. btn_delete(editId) {
  408. this.$confirm("您确定要将此会员删除吗?", "提示", {
  409. confirmButtonText: "确定",
  410. cancelButtonText: "取消",
  411. type: "warning",
  412. })
  413. .then(() => {
  414. deletesMember(editId).then((response) => {
  415. if (response.state.toLowerCase() === "success") {
  416. this.getList()
  417. this.$message.success("删除成功!")
  418. }
  419. })
  420. })
  421. .catch(() => {
  422. this.$message.info("已取消删除")
  423. })
  424. },
  425. // 添加备注
  426. btn_add_remark(id) {
  427. this.$layer.iframe({
  428. content: {
  429. content: addOrEditRemark, // 传递的组件对象
  430. parent: this, // 当前的vue对象
  431. data: { rowid: id }, // props
  432. },
  433. area: ["40%", "50%"],
  434. title: "添加备注",
  435. })
  436. },
  437. changeSelects(val) {
  438. const ids = []
  439. const names = []
  440. this.multipleSelection = val
  441. for (let i = 0; i < this.multipleSelection.length; i++) {
  442. ids.push(this.multipleSelection[i].F_ID)
  443. names.push(this.multipleSelection[i].F_Name)
  444. }
  445. this.selectedId = ids
  446. this.namesData = names
  447. },
  448. // 主号码加密
  449. clickCut(id) {
  450. const params = {
  451. id: id,
  452. type: 0,
  453. }
  454. encryptphone(params)
  455. .then((response) => {
  456. if (response.state.toLowerCase() === "success") {
  457. this.phoneOne = response.data
  458. this.$copyText(this.phoneOne).then(
  459. (e) => {
  460. this.$message.success("号码复制成功,请联系管理员进行解密!")
  461. },
  462. (e) => {
  463. this.$toast("复制失败")
  464. }
  465. )
  466. }
  467. })
  468. .catch(() => {
  469. this.$message.info("查询失败")
  470. })
  471. },
  472. // 备用号码解密
  473. clickCut2(id) {
  474. const params = {
  475. id: id,
  476. type: 1,
  477. }
  478. encryptphone(params)
  479. .then((response) => {
  480. if (response.state.toLowerCase() === "success") {
  481. this.phoneOne2 = response.data
  482. this.$copyText(this.phoneOne2).then(
  483. (e) => {
  484. this.$message.success("号码复制成功,请联系管理员进行解密!")
  485. },
  486. (e) => {
  487. this.$toast("复制失败")
  488. }
  489. )
  490. }
  491. })
  492. .catch(() => {
  493. this.$message.info("查询失败")
  494. })
  495. },
  496. // 外呼
  497. clickCallOut(phoneNumber) {
  498. this.callOut(phoneNumber)
  499. },
  500. // 外呼
  501. callOut(phoneNumber) {
  502. if (phoneNumber) {
  503. getCallOutprefix(phoneNumber).then((response) => {
  504. if (response.state.toLowerCase() === "success") {
  505. const res = response.data
  506. this.scoketDatas = {
  507. Type: "MakeCall",
  508. AgentID: this.usercode,
  509. AgentExten: this.extension,
  510. Header: res.fix, // 号码前缀 用于截断前缀得到真实号码
  511. DestinationNumber: res.phone, //
  512. }
  513. store.dispatch("ChangeCallNum", phoneNumber)
  514. Send(this.scoketDatas)
  515. store.dispatch("UpdateCalloutScreen", false) // 关闭外呼面板
  516. store.dispatch("UpdateOutboundScreen", false) // 关闭外呼弹屏
  517. }
  518. })
  519. } else {
  520. this.$message({
  521. message: "请先输入电话号码!",
  522. type: "warning",
  523. })
  524. }
  525. },
  526. },
  527. }
  528. </script>
  529. <style rel="stylesheet/scss" lang="scss" scoped>
  530. .phoneIcon {
  531. cursor: pointer;
  532. }
  533. </style>