Jelajahi Sumber

3.0.59 增加资产异常出入记录页面

liuyanpeng 2 tahun lalu
induk
melakukan
0cfba3fd96

+ 1 - 1
package.json

@@ -1,7 +1,7 @@
 {
   "name": "client-eam-v3",
   "description": "Leanwo Prodog Client",
-  "version": "3.0.57",
+  "version": "3.0.59",
   "author": "yangzhijie1488 <yangzhijie1488@163.com>",
   "scripts": {
     "dev": "cross-env webpack serve --config ./webpack.dev.js",

+ 276 - 0
src/components/rfidRecord/AssetRfidRecord.vue

@@ -0,0 +1,276 @@
+<template>
+  <Navbar title="资产异常出入记录" :is-go-back="false" />
+  <div class="globalMain">
+    <ul class="siteList">
+      <li class="site">
+        <span class="labels">
+          <span class="noRequired"> * </span>
+          <label>资产名称</label>
+        </span>
+        <a-input
+          v-model:value="searchParams.assetInstanceName"
+          placeholder="请输入资产名称"
+          style="width: 70%"
+          @change="searchRecord"
+        />
+      </li>
+      <li class="site">
+        <span class="labels">
+          <span class="noRequired"> * </span>
+          <label>资产编号</label>
+        </span>
+        <a-input
+          v-model:value="searchParams.assetInstanceNo"
+          placeholder="请输入资产编号"
+          style="width: 70%"
+          @change="searchRecord"
+        />
+      </li>
+      <li class="site">
+        <span class="labels">
+          <span class="noRequired"> * </span>
+          <label>资产EPC</label>
+        </span>
+        <a-input
+          v-model:value="searchParams.epc"
+          placeholder="请输入资产EPC"
+          style="width: 70%"
+          @change="searchRecord"
+        />
+      </li>
+      <li class="site">
+        <span class="labels">
+          <span class="noRequired"> * </span>
+          <label>资产位置</label>
+        </span>
+        <a-input
+          v-model:value="searchParams.position"
+          placeholder="请输入资产位置"
+          style="width: 70%"
+          @change="searchRecord"
+        />
+      </li>
+      <li class="site">
+        <span class="labels">
+          <span class="noRequired"> * </span>
+          <label>异常类型</label>
+        </span>
+        <a-input
+          v-model:value="searchParams.assetInstanceRecordType"
+          placeholder="请输入异常类型"
+          style="width: 70%"
+          @change="searchRecord"
+        />
+      </li>
+      <li class="site">
+        <span class="labels">
+          <span class="noRequired"> * </span>
+          <label>开始日期</label>
+        </span>
+        <a-config-provider :locale="zhCN">
+          <a-date-picker
+            v-model:value="startValue"
+            format="YYYY-MM-DD HH:mm:ss"
+            :show-time="{
+              format: 'HH:mm:ss',
+              defaultValue: moment('00:00:00', 'HH:mm:ss'),
+            }"
+            style="width: 70%"
+            placeholder="请选择开始时间"
+            @change="startTimeChange"
+          />
+        </a-config-provider>
+      </li>
+      <li class="site">
+        <span class="labels">
+          <span class="noRequired"> * </span>
+          <label>结束日期</label>
+        </span>
+        <a-config-provider :locale="zhCN">
+          <a-date-picker
+            v-model:value="endValue"
+            format="YYYY-MM-DD HH:mm:ss"
+            :show-time="{
+              format: 'HH:mm:ss',
+              defaultValue: moment('00:00:00', 'HH:mm:ss'),
+            }"
+            style="width: 70%"
+            placeholder="请选择结束时间"
+            @change="endTimeChange"
+          />
+        </a-config-provider>
+      </li>
+      <li class="site" style="display: flex">
+        <div style="width: 300px">
+          <a-button
+            type="primary"
+            style="margin-left: 20px"
+            @click="searchRecord"
+          >
+            查询
+          </a-button>
+          <a-button type="dashed" style="margin-left: 8px" @click="clearParams">
+            清空
+          </a-button>
+        </div>
+      </li>
+    </ul>
+  </div>
+  <div class="tableArea">
+    <CommonTable
+      ref="table"
+      style="margin-top: 10px"
+      :total="total"
+      :columns="columns"
+      :is-loading="isLoading"
+      :data-source="dataSource"
+      @get-page="getPageParams"
+    />
+  </div>
+</template>
+  
+  
+<script setup>
+import dayjs from 'dayjs';
+import 'dayjs/locale/zh-cn';
+import moment from 'moment';
+import CommonTable from './CommonTable';
+import Common from '../../common/Common.js';
+import { ref, reactive, onMounted } from 'vue';
+import zhCN from 'ant-design-vue/es/locale/zh_CN';
+import { recordColumns, rfidQuery, debounce } from './configDatas.js';
+
+dayjs.locale('zh-cn');
+const total = ref(0);
+const table = ref(null);
+const endValue = ref(); // 日期
+const startValue = ref(); // 日期
+const dataSource = ref([]); //表格数据
+const isLoading = ref(false); //表格loading
+const columns = ref(recordColumns); //表格列
+
+const searchParams = reactive({
+  start: 1,
+  epc: null,
+  length: 20,
+  endDate: null,
+  position: null,
+  startDate: null,
+  assetInstanceNo: null,
+  assetInstanceName: null,
+  assetInstanceRecordType: null,
+});
+
+// 从子组件获取的分页参数
+const getPageParams = (start, length) => {
+  searchParams.start = start;
+  searchParams.length = length;
+  queryInfo();
+};
+
+// 查询回到第一页(防抖)
+const searchRecord = debounce(() => {
+  table.value.backFirstPage();
+}, 500);
+
+// 查询日期
+const startTimeChange = (_, dateString) => {
+  searchParams.startDate = dateString;
+  searchRecord();
+  console.log(dateString);
+};
+const endTimeChange = (_, dateString) => {
+  searchParams.endDate = dateString;
+  searchRecord();
+};
+
+// 查询表格数据
+const queryInfo = () => {
+  isLoading.value = true;
+  const params = { ...searchParams };
+  rfidQuery(params).then(
+    success => {
+      total.value = success.totalSize;
+      dataSource.value = success.dataList;
+      isLoading.value = false;
+    },
+    error => {
+      Common.processException(error);
+      isLoading.value = false;
+    },
+  );
+};
+onMounted(() => {
+  searchRecord();
+});
+
+// 清空查询条件
+const clearParams = () => {
+  endValue.value = null;
+  startValue.value = null;
+  searchParams.epc = null;
+  searchParams.endDate = null;
+  searchParams.position = null;
+  searchParams.startDate = null;
+  searchParams.assetInstanceNo = null;
+  searchParams.assetInstanceName = null;
+  searchParams.assetInstanceRecordType = null;
+  searchRecord();
+};
+</script>
+  
+<style scoped>
+:deep(.ant-table-body) {
+  height: 400px;
+}
+
+.globalMain {
+  max-width: 99%;
+  margin-left: auto;
+  margin-right: auto;
+  list-style: none;
+  box-sizing: border-box;
+  margin-top: 20px;
+}
+
+.labels {
+  display: inline-block;
+  width: 70px;
+}
+.required {
+  width: 10px;
+  color: red;
+}
+.noRequired {
+  width: 10px;
+  color: #f7f7f7;
+}
+.siteList {
+  margin: -10px 0 -8px -24px !important;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+}
+.siteList .site {
+  width: 300px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  position: relative;
+}
+.siteList > li {
+  margin-bottom: 8px;
+  margin-left: 0px;
+}
+
+@media (min-width: 500px) {
+  .siteList {
+    margin-left: 0;
+    margin-right: -25px;
+    justify-content: flex-start;
+  }
+  .siteList > li {
+    margin-right: 8px;
+  }
+}
+</style>

+ 215 - 0
src/components/rfidRecord/CommonTable.vue

@@ -0,0 +1,215 @@
+<template>
+  <!-- 表格 + 分页 -->
+  <div class="tablePaganations">
+    <a-config-provider :locale="locale">
+      <a-table
+        class="ant-table-striped"
+        bordered
+        size="small"
+        height="1000px"
+        :loading="isLoading"
+        :data-source="dataSource"
+        :columns="columns"
+        :row-key="(record) => record.id"
+        :scroll="scrollValue"
+        :pagination="havePage ? pagination : false"
+        :row-class-name="
+          (_record, index) => (index % 2 === 1 ? 'table-striped' : null)
+        "
+        :row-selection="
+          isSelect
+            ? {
+              selectedRowKeys: state.selectedRowKeys,
+              onSelect: selectEvent,
+              onSelectAll: selectAllEvent,
+            }
+            : null
+        "
+        @change="tableChange"
+        @resize-column="handleResizeColumn"
+      >
+        <template
+          v-for="(item, index) in renderArr"
+          #[item]="scope"
+          :key="index"
+        >
+          <slot :name="item" :scope="scope" v-bind="scope || {}" />
+        </template>
+      </a-table>
+    </a-config-provider>
+  </div>
+</template>
+  
+<script setup>
+import {
+  useSlots,
+  ref,
+  reactive,
+  defineProps,
+  defineEmits,
+  defineExpose,
+  watch,
+} from 'vue';
+import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN';
+const locale = ref(zhCN);
+const props = defineProps({
+  dataSource: {
+    type: Object,
+    required: true,
+  },
+  columns: {
+    type: Object,
+    required: true,
+  },
+  isSelect: {
+    type: Boolean,
+  },
+  isLoading: {
+    type: Boolean,
+  },
+  total: {
+    type: Number,
+    default: 0,
+  },
+  havePage: {
+    type: Boolean,
+    default: true,
+  },
+  scrollValue: {
+    type: Object,
+    default: () => ({ y: 900 }),
+  },
+  selectedKeys: {
+    type: Array,
+    default: () => [],
+  },
+});
+
+const emit = defineEmits(['getPage', 'getTableSort', 'getSelectColumn']);
+
+// 分页配置
+const pagination = reactive({
+  showQuickJumper: true,
+  current: 1,
+  pageSize: 20, // 默认每页显示数量
+  showSizeChanger: true, // 显示可改变每页数量
+  pageSizeOptions: ['10', '20', '50', '100', '200', '500'], // 每页数量选项值
+  showTotal: (total, range) =>
+    range[0] + '-' + range[1] + '条' + ' 共' + total + '条', // 显示总数
+  onShowSizeChange: (current, pageSize) => showSizeChange(current, pageSize),
+  onChange: (current, pageSize) => changePage(current, pageSize), //点击页码事件
+  total: props.total,
+});
+const lastSorter = reactive({ field: '', order: '' });
+//  选择数据
+const state = reactive({
+  selectedRows: [],
+  selectedRowKeys: [],
+});
+
+// 改变每页数量时更新显示
+const showSizeChange = (current, pageSize) => {
+  setTimeout(() => {
+    pagination.current = 1;
+    emit('getPage', pagination.current, pageSize);
+  });
+  pagination.pageSize = pageSize;
+};
+
+//点击页码事件
+const changePage = (current, size) => {
+  pagination.current = current;
+  emit('getPage', pagination.current, size);
+};
+
+// 回到第一页
+const backFirstPage = () => {
+  pagination.current = 1;
+  emit('getPage', pagination.current, pagination.pageSize);
+};
+
+// 选择每一项操作
+const selectEvent = (record, selected, selectedRows) => {
+  state.selectedRows = selectedRows.map(pro => pro);
+  state.selectedRowKeys = selectedRows.map(pro => pro.id);
+  emit('getSelectColumn', state);
+};
+
+// 点击以后全选当前分页数据
+const selectAllEvent = (selected, selectedRows, changeRows) => {
+  if (selected) {
+    state.selectedRows = selectedRows;
+    changeRows.forEach(item => {
+      state.selectedRowKeys.push(item.id);
+    });
+  } else {
+    changeRows.forEach(item => {
+      let index = state.selectedRowKeys.indexOf(item.id);
+      if (index >= 0) {
+        state.selectedRows.splice(index, 1);
+        state.selectedRowKeys.splice(index, 1);
+      }
+    });
+  }
+  emit('getSelectColumn', state);
+};
+// 清空选择
+const clear = () => {
+  state.selectedRowKeys = [];
+  state.selectedRows = [];
+  emit('getSelectColumn', state);
+};
+// 获取排序信息
+const tableChange = (pagination, filters, sorter) => {
+  // pagination, filters 变化时也会触发所以对sorter进行判断限制执行
+  if (Object.keys(sorter).length > 0) {
+    if (sorter.field != lastSorter.field && sorter.order != lastSorter.order) {
+      lastSorter.field = sorter.field;
+      lastSorter.order = sorter.order;
+      emit('getTableSort', sorter);
+    }
+    if (sorter.field != lastSorter.field && sorter.order == lastSorter.order) {
+      lastSorter.field = sorter.field;
+      lastSorter.order = sorter.order;
+      emit('getTableSort', sorter);
+    }
+    if (sorter.field == lastSorter.field && sorter.order != lastSorter.order) {
+      lastSorter.field = sorter.field;
+      lastSorter.order = sorter.order;
+      emit('getTableSort', sorter);
+    }
+  }
+};
+// 伸缩列
+const handleResizeColumn = (w, col) => {
+  col.width = w;
+};
+defineExpose({ backFirstPage, clear });
+
+// 监听total变化
+watch(
+  props,
+  newData => {
+    pagination.total = newData.total;
+    if (newData.selectedKeys && newData.selectedKeys.length > 0) {
+      state.selectedRowKeys = newData.selectedKeys;
+      emit('getSelectColumn', state);
+    }
+  },
+  { immediate: true, deep: true },
+);
+// 插槽的实例
+const slots = useSlots();
+const renderArr = Object.keys(slots);
+</script>
+<style scoped>
+.tablePaganations {
+  width: 100%;
+  margin-top: 20px;
+}
+.ant-table-striped :deep(.table-striped) td {
+  background-color: #fafafa;
+}
+</style>
+  
+  

+ 125 - 0
src/components/rfidRecord/configDatas.js

@@ -0,0 +1,125 @@
+import Common from '../../common/Common.js';
+// 查询表格列
+export const recordColumns = [
+  {
+    title: '序号',
+    dataIndex: 'index',
+    key: 'index',
+    width: 75,
+    customRender: ({ text, record, index }) => `${index + 1}`,
+  },
+  {
+    title: '所属单位',
+    key: 'affiliatedUnit',
+    dataIndex: 'affiliatedUnit',
+    width: 150,
+  },
+  {
+    title: '所属部门',
+    key: 'department',
+    dataIndex: 'department',
+    width: 150,
+  },
+  {
+    title: '使用单位',
+    key: 'usingUnit',
+    dataIndex: 'usingUnit',
+    width: 150,
+  },
+  {
+    title: '使用部门',
+    key: 'userDepartment',
+    dataIndex: 'userDepartment',
+    width: 150,
+  },
+  {
+    title: '资产编号',
+    key: 'assetNo',
+    dataIndex: 'assetNo',
+    width: 150,
+  },
+  {
+    title: '资产名称',
+    key: 'assetInstanceName',
+    dataIndex: 'assetInstanceName',
+    width: 150,
+  },
+  {
+    title: '卡片编号',
+    key: 'assetInstanceNo',
+    dataIndex: 'assetInstanceNo',
+    width: 150,
+  },
+  {
+    title: '条码',
+    key: 'barcode',
+    dataIndex: 'barcode',
+    width: 230,
+  },
+  {
+    title: 'EPC',
+    key: 'epc',
+    dataIndex: 'epc',
+    width: 200,
+  },
+  {
+    title: '扫描时间',
+    key: 'scanDate',
+    dataIndex: 'scanDate',
+    width: 150,
+  },
+  {
+    title: '位置',
+    key: 'position',
+    dataIndex: 'position',
+    width: 150,
+  },
+  {
+    title: '异常类型',
+    key: 'assetInstanceRecordType',
+    dataIndex: 'assetInstanceRecordType',
+    width: 150,
+  },
+  // {
+  //   title: '操作',
+  //   key: 'operation',
+  //   dataIndex: 'operation',
+  //   width: 150,
+  //   fixed: 'right',
+  // },
+].map(item => ({ ...item, align: 'center', resizable: true, maxWidth: 300, minWidth: 75 }));
+
+
+export const rfidQuery = params => {
+  var requestUrl = 'AssetInstanceRfidRecordResource/queryAssetInstanceRfidRecord';
+  return new Promise((resolve, reject) => {
+    $.ajax({
+      url: Common.getApiURL(requestUrl),
+      type: 'post',
+      contentType: 'application/json',
+      dataType:'json',
+      data: JSON.stringify({...params}),
+
+      beforeSend: function (request) {
+        Common.addTokenToRequest(request);
+      },
+      success: function (data) {
+        resolve(data);
+      },
+      error: function (XMLHttpRequest, textStatus, errorThrown) {
+        reject(XMLHttpRequest);
+      },
+    });
+  });
+};
+
+// 防抖函数
+export const debounce = (fn, wait = 1000) => {
+  let timer;
+  return function (...args) {
+    clearTimeout(timer);
+    timer = setTimeout(() => {
+      fn.call(this, args);
+    }, wait);
+  };
+};

+ 3 - 0
src/index.js

@@ -41,6 +41,8 @@ import InventoryDataProcessing from './components/customer/InventoryDataProcessi
 import AssetLabelPrint from './components/customer/AssetLabelPrint.vue';
 import InventoryAssetInstanceSearch from './customer/InventoryAssetInstanceSearch.vue';
 import RunDataArchive from './components/customer/RunDataArchive.vue';
+import AssetRfidRecord from './components/rfidRecord/AssetRfidRecord.vue';
+
 export {
   langZhCn,
   langEnUs,
@@ -82,4 +84,5 @@ export {
   AssetLabelPrint,
   InventoryAssetInstanceSearch,
   RunDataArchive,
+  AssetRfidRecord,
 };

+ 5 - 0
src/router/index.js

@@ -34,6 +34,8 @@ const PerformInventoryTasks = () => import(/* webpackChunkName: "component-33" *
 const InventoryDataProcessing = () => import(/* webpackChunkName: "component-34" */ '../components/customer/InventoryDataProcessing.vue');
 const AssetLabelPrint = () => import(/* webpackChunkName: "component-35" */ '../components/customer/AssetLabelPrint.vue');
 const RunDataArchive = () => import(/* webpackChunkName: "component-35" */ '../components/customer/RunDataArchive.vue');
+const AssetRfidRecord = () => import('../components/rfidRecord/AssetRfidRecord.vue');
+
 const routes = [
 
   { path: '/eam/hello-world', component: HelloWorld },
@@ -294,6 +296,9 @@ const routes = [
   {
     path: '/eam/runDataArchive', component: RunDataArchive,
   },
+  {
+    path: '/eam/assetRfidRecord', component: AssetRfidRecord,
+  },
 ];