소스 검색

开发频道留言历史功能

vothin 2 년 전
부모
커밋
7d08576fb4

+ 9 - 2
languages/en.js

@@ -474,7 +474,12 @@ module.exports = {
     channelAdd: 'Add channel',
     channelName: 'Channel name',
     inputChannelName: 'Please enter the channel name',
-    subscribeManage: 'Subscription Management'
+    subscribeManage: 'Management',
+    channelImHistory: 'History',
+    senderMemberName: 'Sender name',
+    senderTime: 'Send time',
+    audioPath: 'File address',
+    play: 'Play the message'
   },
   remark: {
     remarkAdd: 'New note',
@@ -814,7 +819,8 @@ module.exports = {
     twoColorDoorLightValid: 'Two-color door lights are supported or not',
     support: 'Support two-color door lights',
     customerNameHidden: 'Enable user name hiding',
-    hidden: 'Turn on user name hide'
+    hidden: 'Turn on user name hide',
+    channelImHistoryStoreDays: 'The number of days that channel messages are retained'
   },
   role: {
     roleName: 'Role name',
@@ -841,6 +847,7 @@ module.exports = {
     userLocationManage: 'User Location',
     sosDeviceSettingManage: 'Alarm device',
     channelManage: 'Intercom channel',
+    channelImHistory: 'Channel message history',
     remarkManage: 'Note management',
     taskManage: 'Task management',
     interactionHistory: 'Interaction History',

+ 9 - 2
languages/zh-CN.js

@@ -475,7 +475,12 @@ module.exports = {
     channelAdd: '新增频道',
     channelName: '频道名称',
     inputChannelName: '请输入频道名称',
-    subscribeManage: '订阅管理'
+    subscribeManage: '订阅管理',
+    channelImHistory: '频道历史',
+    senderMemberName: '发送者姓名',
+    senderTime: '发送时间',
+    audioPath: '文件地址',
+    play: '播放留言'
   },
   remark: {
     remarkAdd: '新建便签',
@@ -815,7 +820,8 @@ module.exports = {
     twoColorDoorLightValid: '是否支持双色门灯',
     support: '支持双色门灯',
     customerNameHidden: '是否开启用户名隐藏',
-    hidden: '开启用户名隐藏'
+    hidden: '开启用户名隐藏',
+    channelImHistoryStoreDays: '频道留言保留天数'
   },
   role: {
     roleName: '角色名称',
@@ -842,6 +848,7 @@ module.exports = {
     userLocationManage: '用户位置',
     sosDeviceSettingManage: '报警设备',
     channelManage: '对讲频道',
+    channelImHistory: '频道留言历史',
     remarkManage: '便签管理',
     taskManage: '任务管理',
     interactionHistory: '交互历史',

+ 16 - 0
src/api/ncs_channel_im_history.js

@@ -0,0 +1,16 @@
+import request from '@/utils/request'
+
+/**
+ * 对讲频道相关接口
+ * @param params
+ * @returns {*|Promise|Promise<unknown>}
+ */
+export function getList(params) {
+  return request({
+    url: '/ncs/channel_im_history/channel_im_history_list',
+    method: 'POST',
+    loading: true,
+    data: params,
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
+  })
+}

+ 8 - 2
src/router/index.js

@@ -211,8 +211,7 @@ export const partRoutes = [
         meta: { title: i18n.t('customerManage.footprint'), icon: 'area', noCache: true },
         hidden: true
       }
-    ],
-    hidden: uiVersion === 1
+    ]
   },
   {
     path: '/ncs-user-watch',
@@ -251,6 +250,13 @@ export const partRoutes = [
         component: () => import('@/views/ncs-channel/index'),
         name: 'ncsChannel',
         meta: { title: i18n.t('tab.channelManage'), icon: 'el-icon-mobile-phone', noCache: true }
+      },
+      {
+        path: '/ncs-channel/history/:id?',
+        component: () => import('@/views/ncs-channel/channelImHistory'),
+        name: 'channelImHistory',
+        meta: { title: i18n.t('tab.channelImHistory'), icon: 'area', noCache: true },
+        hidden: true
       }
     ],
     hidden: uiVersion !== 2

+ 356 - 0
src/views/ncs-channel/channelImHistory.vue

@@ -0,0 +1,356 @@
+<template>
+  <div class="app-container">
+    <ag-grid-layout
+        :table-height="tableHeight"
+        theme="ag-theme-alpine"
+        :column-defs="columnDefs"
+        :row-data="tableData"
+        :locale-text="localeText"
+        :grid-options="gridOptions"
+        :default-col-def="defaultColDef"
+        :animate-rows="true"
+        :row-selection="rowSelection"
+        row-height="50"
+        @filterChanged="filterModifed"
+        @sortChanged="gridSortChange"
+    >
+      <!--工具栏-->
+      <div slot="toolbar" class="inner-toolbar">
+        <div class="toolbar-search">
+          <en-table-search :placeholder="this.$t('action.keywords')" @search="handlerSearch" />
+        </div>
+        <div  class="toolbar-search"></div>
+        <div class="toolbar-btns">
+          <el-form label-width="120px">
+            <el-form-item>
+              <el-date-picker
+                  v-model="searchDateRange"
+                  type="daterange"
+                  align="right"
+                  unlink-panels
+                  value-format="yyyy/MM/dd"
+                  :range-separator="this.$t('action.to')"
+                  :start-placeholder="this.$t('action.startDate')"
+                  :end-placeholder="this.$t('action.endDate')"
+                  :picker-options="pickerOptions"
+                  :default-time="['00:00:00', '23:59:59']"
+                  @change="dateRangeChange"
+              />
+            </el-form-item>
+
+          </el-form>
+        </div>
+      </div>
+      <el-pagination
+          v-if="pageData"
+          slot="pagination"
+          :current-page="pageData.page_no"
+          :page-sizes="[10, 20, 50, 100]"
+          :page-size="pageData.page_size"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="pageData.data_total"
+          @size-change="handlePageSizeChange"
+          @current-change="handlePageCurrentChange"
+      />
+    </ag-grid-layout>
+
+<!--    <el-dialog title="留言播放" :visible.sync="dialogVisible" :before-close="stop">-->
+<!--      <template>-->
+<!--        <audio-->
+<!--          :src="src"-->
+<!--          autoplay="autoplay"-->
+<!--          controls="controls"-->
+<!--          ref="audio"-->
+<!--          >-->
+<!--        </audio>-->
+<!--      </template>-->
+<!--    </el-dialog>-->
+  </div>
+</template>
+
+<script>
+import ButtonCellRender from "@/components/AgGridCellRender/ButtonCellRender";
+import RadioFilter from "@/components/AgGridCustomFilter/RadioFilter";
+import ListFilter from "@/components/AgGridCustomFilter/ListFilter";
+import {AG_GRID_LOCALE_CN} from "@/utils/AgGridVueLocaleCn";
+import * as API_ChannelImHistory from "@/api/ncs_channel_im_history";
+import {unixToDate} from "@/utils/Foundation";
+
+const DeviceUrl = domain.DeviceUrl
+export default {
+  name: "channelImHistory",
+  components: { ButtonCellRender, RadioFilter, ListFilter},
+  data: function() {
+    return {
+      pickerOptions: {
+        shortcuts: [{
+          text: this.$t('action.lastWeek'),
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+            picker.$emit('pick', [start, end])
+          }
+        },{
+          text: this.$t('action.lastMonth'),
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
+            picker.$emit('pick', [start, end])
+          }
+        }, {
+          text: this.$t('action.lastThreeMonths'),
+          onClick(picker) {
+            const end = new Date()
+            const start = new Date()
+            start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
+            picker.$emit('pick', [start, end])
+          }
+        }]
+      },
+      /** 表格数据 */
+      tableData: [],
+      pageData: [],
+      loading: false,
+      multipleSelection: [],
+      /** 列表参数 */
+      params: {
+        page_size: 20,
+        page_no: 1,
+        fixedCondition: 'channel_id = ' + this.$route.params.id,
+        sort: 'id',
+        dir: 'desc'
+      },
+      searchDateRange: [],
+      columnDefs: null, // 新表格
+      defaultColDef: null,
+      gridOptions: null,
+      gridApi: null,
+      columnApi: null,
+      localeText: AG_GRID_LOCALE_CN,
+      rowSelection: null,
+      showViewer: false,
+      timer: '',
+      audio: new Audio(),
+      src: '',
+      // dialogVisible: false
+    }
+  },
+  computed: {
+    tableHeight() {
+      return this.mainAreaHeight - 130
+    }
+  },
+  beforeMount() {
+    this.gridOptions = {
+    }
+    this.columnDefs = [
+      {
+        headerName: '#',
+        headerCheckboxSelection: true,
+        headerCheckboxSelectionFilteredOnly: true,
+        checkboxSelection: true,
+        sortable: false, filter: false,
+        width: 50,
+        resizable: false,
+        valueGetter: this.hashValueGetter
+      },
+      { headerName: 'ID', field: 'id', sortable: true, filter: 'agNumberColumnFilter', width: 200 },
+      { headerName: this.$t('channel.channelName'), field: 'channel_name', sortable: false, filter: false , width: 200},
+      { headerName: this.$t('channel.senderMemberName'), field: 'sender_member_name', sortable: false, filter: false , width: 200 },
+      { headerName: this.$t('channel.senderTime'), field: 'send_time', sortable: true, valueFormatter: this.formatterDate, filter: false , width: 200 },
+      { headerName: this.$t('channel.audioPath'), field: 'audio_path', sortable: false, filter: false , width: 300 },
+      {
+        headerName: this.$t('channel.play'), field: 'id',
+        cellRendererFramework: 'ButtonCellRender',
+        cellRendererParams: param => {
+          return {
+            onClick: this.playIm,
+            label: this.$t('channel.play'),
+            buttonType: 'primary',
+            buttonSize: 'mini'
+          }
+        },
+        filter: false,
+        pinned: 'right',
+        lockPinned: true,
+        width: 100,
+        resizable: false,
+        sortable: false
+      }
+    ]
+    this.defaultColDef = {
+      sortable: true,
+      resizable: true,
+      filter: true,
+      filterParams: {
+        debounceMs: 200,
+        newRowsAction: 'keep',
+      }
+    }
+    this.rowSelection = 'multiple'
+  },
+  mounted() {
+    // window.onresize = this.windowResize()
+    this.gridApi = this.gridOptions.api
+    this.getList()
+  },
+  methods: {
+    /** 分页大小发生改变 */
+    handlePageSizeChange(size) {
+      this.params.page_size = size
+      this.getList()
+    },
+    /** 分页页数发生改变 */
+    handlePageCurrentChange(page) {
+      this.params.page_no = page
+      this.getList()
+    },
+    /** 加载通知列表 */
+    getList() {
+      this.loading = true
+      const param = this.MixinClone(this.params)
+      this.gridApi.showLoadingOverlay()
+      API_ChannelImHistory.getList(param).then(response => {
+        this.loading = false
+        this.tableData = response.data
+        this.pageData = {
+          page_no: response.page_no,
+          page_size: response.page_size,
+          data_total: response.data_total
+        }
+        this.$nextTick(() => {
+          const node = this.gridApi.getDisplayedRowAtIndex(0)
+          if (node !== null && node !== undefined) {
+            node.setSelected(true)
+          }
+        })
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    /** 处理搜索 */
+    handlerSearch(keywords) {
+      this.params.filerStr = keywords
+      this.getList()
+    },
+    /** 处理排序 */
+    tableSort(column) {
+      if (column.order !== null) {
+        this.params.sort = column.prop
+        this.params.dir = column.order === 'ascending' ? 'asc' : 'desc'
+      } else {
+        this.params.sort = null
+        this.params.dir = null
+      }
+      this.getList()
+    },
+    filterModifed(param) {
+      const model = param.api.getFilterModel()
+      // 连接状态不经过服务器过滤
+      delete model.online_state
+      this.params.filter = JSON.stringify(model)
+      this.getList()
+    },
+    gridSortChange(param) {
+      const columnState = param.columnApi.getColumnState()
+      // 排序状态
+      const sortState = columnState.filter(function(s) {
+        return s.sort != null
+      }).map(function(s) {
+        return {
+          colId: s.colId,
+          sort: s.sort,
+          sortIndex: s.sortIndex
+        }
+      }).sort(function(a, b) {
+        return a.sortIndex - b.sortIndex
+      })
+      if (sortState.length > 0) {
+        if (sortState.length === 1) {
+          this.params.sort = sortState[0].colId
+          this.params.dir = sortState[0].sort
+        } else {
+          let sortstring = ''
+          sortState.forEach(function(item) {
+            sortstring += item.colId + ' ' + item.sort + ','
+          })
+          this.params.sort = sortstring.substring(0, sortstring.length - 1)
+          this.params.dir = ' '
+        }
+      } else {
+        delete this.params.sort
+        delete this.params.dir
+      }
+      this.getList()
+    },
+    formatterDate(params) {
+      return unixToDate(params.value)
+    },
+    dateRangeChange(value) {
+      if (value && value.length > 0) {
+        this.params.start_date = value[0]
+        this.params.end_date = value[1]
+      } else {
+        delete this.params.start_date
+        delete this.params.end_date
+      }
+      this.params.page_no = 1
+      this.getList()
+    },
+    playIm(params) {
+      console.log(params.audio_path)
+      console.log(DeviceUrl + '/' + params.audio_path)
+      this.audio.src = DeviceUrl + '/' + params.audio_path
+      this.audio.play();
+
+      // this.src = DeviceUrl + '/' + params.audio_path
+      // this.play();
+    },
+    // play() {
+    //   this.dialogVisible = true
+    //   this.$refs.audio.play()
+    // },
+    // stop() {
+    //   this.dialogVisible = false
+    //   this.$refs.audio.pause()
+    //   this.$refs.audio.currentTime = 0
+    // }
+  }
+}
+</script>
+
+<style type="text/scss" scoped>
+.tablewen{
+  width:100%;
+  border-collapse:collapse;
+  border: 1px solid #a5b6c8;
+  margin-bottom: 30px;
+  line-height: 40px;
+}
+.tablewen td{
+  font-size: 14px;
+  -webkit-margin-before: 0.83em;
+  -webkit-margin-after: 0.83em;
+  -webkit-margin-start: 0px;
+  -webkit-margin-end: 0px;
+  font-weight: bold;
+}
+.tablewen td span{
+  font-size: 0.8em;
+  -webkit-margin-before: 0.83em;
+  -webkit-margin-after: 0.83em;
+  -webkit-margin-start: 0px;
+  -webkit-margin-end: 0px;
+  font-weight: bold;
+  color: #8c939d;
+  margin-left: 5px;
+}
+.tablewen .td1{
+  width:15%;
+}
+.tablewen .td2{
+  width:20%;
+}
+</style>

+ 104 - 45
src/views/ncs-channel/index.vue

@@ -89,10 +89,11 @@ import { unix2Date } from '@/utils/Foundation'
 import * as API_Clerk from '@/api/ncs_clerk'
 import ListFilter from '@/components/AgGridCustomFilter/ListFilter'
 import RadioFilter from '@/components/AgGridCustomFilter/RadioFilter'
+import ButtonCellRenderList from "@/components/AgGridCellRender/ButtonCellRenderList";
 
 export default {
   name: 'Index',
-  components: { ButtonCellRender, ListFilter, RadioFilter },
+  components: { ButtonCellRenderList, ButtonCellRender, ListFilter, RadioFilter },
   data() {
     return {
       tableData: [],
@@ -171,58 +172,113 @@ export default {
         width: 200,
         valueFormatter: this.unixDateFormatter
       },
-      {
-        headerName: this.$t('action.edit'), field: 'id',
-        cellRendererFramework: 'ButtonCellRender',
-        cellRendererParams: {
-          onClick: this.handEdit,
-          label: this.$t('action.edit'),
-          buttonType: 'primary',
-          buttonSize: 'mini'
-        },
-        filter: false,
-        pinned: 'right',
-        lockPinned: true,
-        width: 100,
-        resizable: false,
-        sortable: false
-      },
-
-      {
-        headerName: this.$t('channel.subscribeManage'), field: 'id',
-        cellRendererFramework: 'ButtonCellRender',
-        cellRendererParams: {
-          onClick: this.manageSubscribe,
-          label: this.$t('channel.subscribeManage'),
-          buttonType: 'success',
-          buttonSize: 'mini'
-        },
-        filter: false,
-        pinned: 'right',
-        lockPinned: true,
-        width: 100,
-        resizable: false,
-        sortable: false
-      },
-
-      {
-        headerName: this.$t('action.delete'), field: 'id',
-        cellRendererFramework: 'ButtonCellRender',
+      { headerName: this.$t('action.handle'), field: 'id',
+        cellRendererFramework: 'ButtonCellRenderList',
         cellRendererParams: param => {
           return {
-            onClick: this.deleteSingle,
-            label: this.$t('action.delete'),
-            buttonType: 'danger',
-            buttonSize: 'mini'
-          }
+            list: [
+              {
+                onClick: this.handleEdit,
+                label: this.$t('action.edit'),
+                buttonType: 'primary',
+                buttonSize: 'mini'
+              },
+              {
+                onClick: this.manageSubscribe,
+                label: this.$t('channel.subscribeManage'),
+                buttonType: 'warning',
+                buttonSize: 'mini',
+              },
+              {
+                onClick: this.channelImHistory,
+                label: this.$t('channel.channelImHistory'),
+                buttonType: 'success',
+                buttonSize: 'mini',
+              },
+              {
+                onClick: this.deleteSingle,
+                label: this.$t('action.delete'),
+                buttonType: 'danger',
+                buttonSize: 'mini',
+              }
+            ]}
         },
+        filter: false,
         pinned: 'right',
         lockPinned: true,
-        width: 100,
+        minWidth: this.$i18n.locale === 'zh' ? 310 : 340,
         resizable: false,
-        filter: false,
         sortable: false
       }
+      // {
+      //   headerName: this.$t('action.edit'), field: 'id',
+      //   cellRendererFramework: 'ButtonCellRender',
+      //   cellRendererParams: {
+      //     onClick: this.handEdit,
+      //     label: this.$t('action.edit'),
+      //     buttonType: 'primary',
+      //     buttonSize: 'mini'
+      //   },
+      //   filter: false,
+      //   pinned: 'right',
+      //   lockPinned: true,
+      //   width: 100,
+      //   resizable: false,
+      //   sortable: false
+      // },
+      //
+      // {
+      //   headerName: this.$t('channel.subscribeManage'), field: 'id',
+      //   cellRendererFramework: 'ButtonCellRender',
+      //   cellRendererParams: {
+      //     onClick: this.manageSubscribe,
+      //     label: this.$t('channel.subscribeManage'),
+      //     buttonType: 'success',
+      //     buttonSize: 'mini'
+      //   },
+      //   filter: false,
+      //   pinned: 'right',
+      //   lockPinned: true,
+      //   width: 100,
+      //   resizable: false,
+      //   sortable: false
+      // },
+      //
+      // {
+      //   headerName: "留言历史", field: 'id',
+      //   cellRendererFramework: 'ButtonCellRender',
+      //   cellRendererParams: {
+      //     onClick: this.channelImHistory,
+      //     label: "留言历史",
+      //     buttonType: 'success',
+      //     buttonSize: 'mini'
+      //   },
+      //   filter: false,
+      //   pinned: 'right',
+      //   lockPinned: true,
+      //   width: 100,
+      //   resizable: false,
+      //   sortable: false
+      // },
+      //
+      // {
+      //   headerName: this.$t('action.delete'), field: 'id',
+      //   cellRendererFramework: 'ButtonCellRender',
+      //   cellRendererParams: param => {
+      //     return {
+      //       onClick: this.deleteSingle,
+      //       label: this.$t('action.delete'),
+      //       buttonType: 'danger',
+      //       buttonSize: 'mini'
+      //     }
+      //   },
+      //   pinned: 'right',
+      //   lockPinned: true,
+      //   width: 100,
+      //   resizable: false,
+      //   filter: false,
+      //   sortable: false
+      // }
     ]
     this.defaultColDef = {
       sortable: true,
@@ -457,6 +513,9 @@ export default {
       this.subscribeTitle = row.channel_name + this.$t('channel.subscribeManage')
       this.formSubscribe = true
     },
+    channelImHistory(row) {
+      this.$router.push({ name: 'channelImHistory', params: { id: row.id, callback: this.getList() }})
+    },
     getEmployees() {
       const _this = this
       _this.nurses = []

+ 8 - 0
src/views/ncs-orginazition/components/partInfoEdit.vue

@@ -315,6 +315,13 @@
           </el-row>
 
 
+          <el-row>
+            <el-form-item :label="this.$t('partInfo.channelImHistoryStoreDays')" prop="channel_im_history_store_days">
+              <el-input-number v-model="formmodel.channel_im_history_store_days" :min="1" :max="1000" :label="this.$t('partInfo.channelImHistoryStoreDays')" />
+            </el-form-item>
+          </el-row>
+
+
 
           <el-row>
             <el-col :span="8">
@@ -631,6 +638,7 @@ export default {
                 customize_role_call_fourth: 0,
                 customize_role_call_fifth: 0,
                 customer_name_hidden: 0,
+                channel_im_history_store_days: 30,
                 auto_accept: 0,
                 door_nurse_title: '呼叫护士',
                 door_nurse_valid: 1,