RemoteDataView.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. <script>
  2. // import * as customerApi from '@/api/operateCenter/customerAnalysis'
  3. // import * as groupApi from '@/api/operateCenter/groupAnalysis'
  4. // import * as conversationApi from '@/api/operateCenter/conversationAnalysis'
  5. import { getList as getGroupList } from '@/api/customer/group'
  6. export default {
  7. name: '',
  8. components: {
  9. ChartLine: () => import('@/components/ChartLine'),
  10. ChartBar: () => import('@/components/ChartBar'),
  11. },
  12. props: {
  13. // 图表类型
  14. type: {
  15. type: String, // lineChart, barChart, table
  16. default: '',
  17. },
  18. // 图表图例; 单个图例可传字符串,多个图例传数组
  19. legend: {
  20. type: [Array, String],
  21. default: null,
  22. },
  23. // 接口请求
  24. request: {
  25. type: Function,
  26. default: () => {},
  27. },
  28. // 是否显示时间查询
  29. isTimeQuery: {
  30. type: Boolean,
  31. default: false,
  32. },
  33. // 是否显示选择群主
  34. isGroupOwnerQuery: {
  35. type: Boolean,
  36. default: false,
  37. },
  38. // 是否显示选择群聊
  39. isGroupQuery: {
  40. type: Boolean,
  41. default: false,
  42. },
  43. // 是否显示选择部门或员工
  44. isDepartOrStaff: {
  45. type: Boolean,
  46. default: false,
  47. },
  48. // 导出接口请求
  49. requestExport: {
  50. type: Function,
  51. default: null,
  52. },
  53. // 自定义图表配置项,使用loadsh.merge(origin, option)和原有的配置进行覆盖合并
  54. // loadsh.merge: https://www.html.cn/doc/lodash/#_mergeobject-sources
  55. option: {
  56. type: Object,
  57. default: null,
  58. },
  59. // 导出接口请求
  60. dealDataFun: {
  61. type: Function,
  62. default: null,
  63. },
  64. },
  65. data() {
  66. return {
  67. loading: false,
  68. timeRange: 7,
  69. total: 0,
  70. // 表格数据
  71. data: [],
  72. xData: [],
  73. // 日期范围
  74. dateRange: [],
  75. // 查询参数
  76. query: {
  77. pageNum: undefined,
  78. pageSize: undefined,
  79. deptIds: [],
  80. userIds: [],
  81. chatIds: [],
  82. ownerIds: [],
  83. beginTime: undefined,
  84. endTime: undefined,
  85. },
  86. // 群聊
  87. groupChats: [],
  88. tableProps: [],
  89. userArray: [], // 选择人员
  90. dialogVisible: false,
  91. dialogType: '',
  92. }
  93. },
  94. computed: {},
  95. watch: {},
  96. created() {
  97. this.setTime(7)
  98. },
  99. mounted() {},
  100. methods: {
  101. getList(page) {
  102. if (this.type == 'table') {
  103. this.query.pageSize || (this.query.pageSize = 10)
  104. }
  105. if (this.dateRange) {
  106. this.query.beginTime = this.dateRange[0]
  107. this.query.endTime = this.dateRange[1]
  108. } else {
  109. this.query.beginTime = ''
  110. this.query.endTime = ''
  111. }
  112. if (this.dialogType === '_users') {
  113. if (Array.isArray(this.userArray)) {
  114. this.query.deptIds = this.userArray
  115. .filter((e) => e.isParty)
  116. .map((e) => e.id)
  117. .join(',')
  118. this.query.userIds = this.userArray
  119. .filter((e) => !e.isParty)
  120. .map((e) => e.userId)
  121. .join(',')
  122. } else {
  123. this.query.deptIds = this.query.userIds = ''
  124. }
  125. } else if (this.dialogType === '_groupOwners') {
  126. if (Array.isArray(this.userArray)) {
  127. this.query.ownerIds = this.userArray
  128. .filter((e) => !e.isParty)
  129. .map((e) => e.userId)
  130. .join(',')
  131. } else {
  132. this.query.ownerIds = ''
  133. }
  134. }
  135. this.loading = true
  136. page && (this.query.pageNum = page)
  137. this.request(this.query)
  138. .then(({ rows, total, data }) => {
  139. this.series = []
  140. data = data || rows
  141. if (!data || !data.length) {
  142. return
  143. }
  144. if (this.type == 'table') {
  145. // 表格
  146. this.data = data
  147. this.total = Number(total)
  148. } else {
  149. this.dealDataFun && this.dealDataFun(data, this.data, this.xData)
  150. }
  151. })
  152. .catch((e) => {
  153. console.error(e)
  154. })
  155. .finally(() => {
  156. this.loading = false
  157. })
  158. },
  159. getGroupList(params) {
  160. getGroupList(params)
  161. .then(({ rows }) => {
  162. this.groupChats = rows
  163. })
  164. .catch(() => {})
  165. },
  166. getTime(datePar) {
  167. const d = datePar ? new Date(datePar) : new Date()
  168. d.setMinutes(d.getMinutes() - d.getTimezoneOffset())
  169. return d.toJSON().substr(0, 10)
  170. },
  171. setTime(days) {
  172. this.timeRange = days
  173. if (days) {
  174. let date = new Date()
  175. date.setDate(date.getDate() - days)
  176. this.dateRange = [this.getTime(date), this.getTime()]
  177. this.getList()
  178. } else {
  179. this.dateRange = null
  180. }
  181. },
  182. showDialog(type) {
  183. this.dialogType = type
  184. this.dialogVisible = true
  185. },
  186. getSelectUser(data) {
  187. this.userArray = data
  188. this.query[this.dialogType] = data.map((e) => e.userId).join(',')
  189. if (['customerGroupMemberTotalChart', 'customerGroupMemberTotalTable'].includes(this.type)) {
  190. this.query.chatIds = ''
  191. this.getGroupList({
  192. userIds: this.query[this.dialogType],
  193. })
  194. }
  195. this.getList()
  196. },
  197. exprotTable() {
  198. this.$confirm('是否确认导出吗?', '提示', {
  199. confirmButtonText: '确定',
  200. cancelButtonText: '取消',
  201. type: 'warning',
  202. })
  203. .then(() => {
  204. this.loading = true
  205. let query = Object.assign({}, this.query, { pageNum: undefined, pageSize: undefined })
  206. return this.requestExport(query)
  207. })
  208. .then((res) => {
  209. this.download(res.data)
  210. })
  211. .catch((error) => {
  212. console.error(error)
  213. })
  214. .finally(() => {
  215. this.loading = false
  216. })
  217. },
  218. },
  219. }
  220. </script>
  221. <template>
  222. <div>
  223. <div class="operation">
  224. <template v-if="isTimeQuery">
  225. <el-button-group>
  226. <el-button type="primary" :plain="timeRange != 7" @click="setTime(7)">近一周</el-button>
  227. <el-button type="primary" :plain="timeRange != 30" @click="setTime(30)"
  228. >近一月
  229. </el-button>
  230. <el-button type="primary" :plain="!!timeRange" @click="setTime()">自定义 </el-button>
  231. </el-button-group>
  232. <el-date-picker
  233. v-if="!timeRange"
  234. v-model="dateRange"
  235. class="ml20"
  236. style="width: 260px"
  237. value-format="yyyy-MM-dd"
  238. type="daterange"
  239. :clearable="false"
  240. :picker-options="pickerOptions"
  241. range-separator="-"
  242. start-placeholder="开始日期"
  243. end-placeholder="结束日期"
  244. @change="getList(1)"
  245. ></el-date-picker>
  246. </template>
  247. <el-input
  248. v-if="isGroupOwnerQuery"
  249. style="width: 180px; margin-left: 20px"
  250. :value="userArray.map((e) => e.name) + ''"
  251. readonly
  252. @focus="showDialog('_groupOwners')"
  253. placeholder="请选择群主"
  254. >
  255. </el-input>
  256. <el-select
  257. style="margin-left: 20px"
  258. v-if="isGroupQuery"
  259. v-model="query.chatIds"
  260. placeholder="请选择群聊"
  261. clearable
  262. @change="getList()"
  263. >
  264. <el-option
  265. v-for="item in groupChats"
  266. :key="item.chatId"
  267. :label="item.groupName"
  268. :value="item.chatId"
  269. >
  270. </el-option>
  271. </el-select>
  272. <el-input
  273. v-if="isDepartOrStaff"
  274. style="width: 180px; margin-left: 20px"
  275. :value="userArray.map((e) => e.name) + ''"
  276. readonly
  277. @focus="showDialog('_users')"
  278. placeholder="请选择部门或员工"
  279. />
  280. <el-button v-if="requestExport" class="fr" type="primary" @click="exprotTable"
  281. >导出 Excel</el-button
  282. >
  283. </div>
  284. <div v-loading="loading">
  285. <ChartLine
  286. v-if="type == 'lineChart'"
  287. :xData="xData"
  288. :legend="legend"
  289. :series="data"
  290. ></ChartLine>
  291. <template v-else-if="type == 'table'">
  292. <el-table :data="data" style="width: 100%">
  293. <el-table-column
  294. v-for="(item, index) in tableProps[type]"
  295. :key="index"
  296. :prop="item.prop"
  297. :label="item.label"
  298. align="center"
  299. >
  300. </el-table-column>
  301. </el-table>
  302. <pagination
  303. :total="total"
  304. :page.sync="query.pageNum"
  305. :limit.sync="query.pageSize"
  306. @pagination="getList()"
  307. />
  308. </template>
  309. <ChartBar v-else-if="'barChart'.includes(type)" :xData="xData" :series="data"></ChartBar>
  310. <ChartLine
  311. v-else-if="'rowEchart'.includes('vChart')"
  312. :xData="xData"
  313. :legend="legend"
  314. :series="data"
  315. :option="option"
  316. ></ChartLine>
  317. </div>
  318. <SelectWeUser
  319. :visible.sync="dialogVisible"
  320. title="组织架构"
  321. :defaultValues="userArray"
  322. @success="getSelectUser"
  323. :isOnlyLeaf="dialogType === '_groupOwners'"
  324. ></SelectWeUser>
  325. </div>
  326. </template>
  327. <style lang="scss" scoped></style>