入库单明细增加操作日志
							parent
							
								
									72a1b7773e
								
							
						
					
					
						commit
						90d593a388
					
				| 
						 | 
				
			
			@ -12,20 +12,20 @@
 | 
			
		|||
  <a-form class="smart-query-form">
 | 
			
		||||
    <a-row class="smart-query-form-row">
 | 
			
		||||
      <a-form-item label="关键字" class="smart-query-form-item">
 | 
			
		||||
        <a-input style="width: 300px" v-model:value="queryForm.keywords" placeholder="变更内容" />
 | 
			
		||||
        <a-input style="width: 300px" v-model:value="queryForm.keywords" placeholder="变更内容"/>
 | 
			
		||||
      </a-form-item>
 | 
			
		||||
 | 
			
		||||
      <a-form-item class="smart-query-form-item smart-margin-left10">
 | 
			
		||||
        <a-button-group>
 | 
			
		||||
          <a-button type="primary" @click="onSearch">
 | 
			
		||||
            <template #icon>
 | 
			
		||||
              <SearchOutlined />
 | 
			
		||||
              <SearchOutlined/>
 | 
			
		||||
            </template>
 | 
			
		||||
            查询
 | 
			
		||||
          </a-button>
 | 
			
		||||
          <a-button @click="onReload">
 | 
			
		||||
            <template #icon>
 | 
			
		||||
              <ReloadOutlined />
 | 
			
		||||
              <ReloadOutlined/>
 | 
			
		||||
            </template>
 | 
			
		||||
            重置
 | 
			
		||||
          </a-button>
 | 
			
		||||
| 
						 | 
				
			
			@ -39,20 +39,20 @@
 | 
			
		|||
    <!-- <DataTracerTable :tableData="tableData" @showDetail="showDetail" /> -->
 | 
			
		||||
 | 
			
		||||
    <!---以 timeline 时间轴形式 显示-->
 | 
			
		||||
    <DataTracerTimeline :tableData="tableData" @showDetail="showDetail" />
 | 
			
		||||
    <DataTracerTimeline :tableData="tableData" @showDetail="showDetail"/>
 | 
			
		||||
 | 
			
		||||
    <a-pagination
 | 
			
		||||
      showSizeChanger
 | 
			
		||||
      showQuickJumper
 | 
			
		||||
      show-less-items
 | 
			
		||||
      :pageSizeOptions="PAGE_SIZE_OPTIONS"
 | 
			
		||||
      :defaultPageSize="queryForm.pageSize"
 | 
			
		||||
      v-model:current="queryForm.pageNum"
 | 
			
		||||
      v-model:pageSize="queryForm.pageSize"
 | 
			
		||||
      :total="total"
 | 
			
		||||
      @change="ajaxQuery"
 | 
			
		||||
      @showSizeChange="ajaxQuery"
 | 
			
		||||
      :show-total="(total) => `共${total}条`"
 | 
			
		||||
        showSizeChanger
 | 
			
		||||
        showQuickJumper
 | 
			
		||||
        show-less-items
 | 
			
		||||
        :pageSizeOptions="PAGE_SIZE_OPTIONS"
 | 
			
		||||
        :defaultPageSize="queryForm.pageSize"
 | 
			
		||||
        v-model:current="queryForm.pageNum"
 | 
			
		||||
        v-model:pageSize="queryForm.pageSize"
 | 
			
		||||
        :total="total"
 | 
			
		||||
        @change="ajaxQuery"
 | 
			
		||||
        @showSizeChange="ajaxQuery"
 | 
			
		||||
        :show-total="(total) => `共${total}条`"
 | 
			
		||||
    />
 | 
			
		||||
    <a-modal v-model:open="visibleDiff" width="90%" title="数据比对" :footer="null">
 | 
			
		||||
      <div v-html="prettyHtml"></div>
 | 
			
		||||
| 
						 | 
				
			
			@ -60,76 +60,79 @@
 | 
			
		|||
  </a-card>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
  import * as Diff from 'diff';
 | 
			
		||||
  import * as Diff2Html from 'diff2html';
 | 
			
		||||
  import 'diff2html/bundles/css/diff2html.min.css';
 | 
			
		||||
  import uaparser from 'ua-parser-js';
 | 
			
		||||
  import { nextTick, reactive, ref, watch } from 'vue';
 | 
			
		||||
  import { dataTracerApi } from '/@/api/support/data-tracer-api';
 | 
			
		||||
  import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '/@/constants/common-const';
 | 
			
		||||
  import { smartSentry } from '/@/lib/smart-sentry';
 | 
			
		||||
  import DataTracerTimeline from './data-tracer-timeline.vue';
 | 
			
		||||
import * as Diff from 'diff';
 | 
			
		||||
import * as Diff2Html from 'diff2html';
 | 
			
		||||
import 'diff2html/bundles/css/diff2html.min.css';
 | 
			
		||||
import uaparser from 'ua-parser-js';
 | 
			
		||||
import {nextTick, reactive, ref, watch} from 'vue';
 | 
			
		||||
import {dataTracerApi} from '/@/api/support/data-tracer-api';
 | 
			
		||||
import {PAGE_SIZE, PAGE_SIZE_OPTIONS} from '/@/constants/common-const';
 | 
			
		||||
import {smartSentry} from '/@/lib/smart-sentry';
 | 
			
		||||
import DataTracerTimeline from './data-tracer-timeline.vue';
 | 
			
		||||
 | 
			
		||||
  let props = defineProps({
 | 
			
		||||
    // 数据id
 | 
			
		||||
    dataId: {
 | 
			
		||||
      type: Number,
 | 
			
		||||
    },
 | 
			
		||||
    // 数据 类型
 | 
			
		||||
    type: {
 | 
			
		||||
      type: Number,
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
let props = defineProps({
 | 
			
		||||
  // 数据id
 | 
			
		||||
  dataId: {
 | 
			
		||||
    type: Number,
 | 
			
		||||
  },
 | 
			
		||||
  // 数据 类型
 | 
			
		||||
  type: {
 | 
			
		||||
    type: Number,
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
  // --------------- 查询表单、查询方法 ---------------
 | 
			
		||||
// --------------- 查询表单、查询方法 ---------------
 | 
			
		||||
 | 
			
		||||
  const queryFormState = {
 | 
			
		||||
    pageNum: 1,
 | 
			
		||||
    pageSize: PAGE_SIZE,
 | 
			
		||||
    searchCount: true,
 | 
			
		||||
    keywords: undefined,
 | 
			
		||||
  };
 | 
			
		||||
  const queryForm = reactive({ ...queryFormState });
 | 
			
		||||
  const tableLoading = ref(false);
 | 
			
		||||
  const tableData = ref([]);
 | 
			
		||||
  const total = ref(0);
 | 
			
		||||
const queryFormState = {
 | 
			
		||||
  pageNum: 1,
 | 
			
		||||
  pageSize: PAGE_SIZE,
 | 
			
		||||
  searchCount: true,
 | 
			
		||||
  keywords: undefined,
 | 
			
		||||
};
 | 
			
		||||
const queryForm = reactive({...queryFormState});
 | 
			
		||||
const tableLoading = ref(false);
 | 
			
		||||
const tableData = ref([]);
 | 
			
		||||
const total = ref(0);
 | 
			
		||||
 | 
			
		||||
  function onReload() {
 | 
			
		||||
    Object.assign(queryForm, queryFormState);
 | 
			
		||||
    onSearch();
 | 
			
		||||
  }
 | 
			
		||||
function onReload() {
 | 
			
		||||
  Object.assign(queryForm, queryFormState);
 | 
			
		||||
  onSearch();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  function onSearch() {
 | 
			
		||||
    queryForm.pageNum = 1;
 | 
			
		||||
    ajaxQuery();
 | 
			
		||||
  }
 | 
			
		||||
function onSearch() {
 | 
			
		||||
  queryForm.pageNum = 1;
 | 
			
		||||
  ajaxQuery();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  async function ajaxQuery() {
 | 
			
		||||
    try {
 | 
			
		||||
      tableLoading.value = true;
 | 
			
		||||
      let responseModel = await dataTracerApi.queryList(Object.assign({}, queryForm, { dataId: props.dataId, type: props.type }));
 | 
			
		||||
      for (const e of responseModel.data.list) {
 | 
			
		||||
        if (!e.userAgent) {
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
        // e.content = e.content.replaceAll('<br/>',';');
 | 
			
		||||
        let ua = uaparser(e.userAgent);
 | 
			
		||||
        e.browser = ua.browser.name;
 | 
			
		||||
        e.os = ua.os.name;
 | 
			
		||||
        e.device = ua.device.vendor ? ua.device.vendor + ua.device.model : '';
 | 
			
		||||
async function ajaxQuery() {
 | 
			
		||||
  try {
 | 
			
		||||
    tableLoading.value = true;
 | 
			
		||||
    let responseModel = await dataTracerApi.queryList(Object.assign({}, queryForm, {
 | 
			
		||||
      dataId: props.dataId,
 | 
			
		||||
      type: props.type
 | 
			
		||||
    }));
 | 
			
		||||
    for (const e of responseModel.data.list) {
 | 
			
		||||
      if (!e.userAgent) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      const list = responseModel.data.list;
 | 
			
		||||
      total.value = responseModel.data.total;
 | 
			
		||||
      tableData.value = list;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      smartSentry.captureError(e);
 | 
			
		||||
    } finally {
 | 
			
		||||
      tableLoading.value = false;
 | 
			
		||||
      // e.content = e.content.replaceAll('<br/>',';');
 | 
			
		||||
      let ua = uaparser(e.userAgent);
 | 
			
		||||
      e.browser = ua.browser.name;
 | 
			
		||||
      e.os = ua.os.name;
 | 
			
		||||
      e.device = ua.device.vendor ? ua.device.vendor + ua.device.model : '';
 | 
			
		||||
    }
 | 
			
		||||
    const list = responseModel.data.list;
 | 
			
		||||
    total.value = responseModel.data.total;
 | 
			
		||||
    tableData.value = list;
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    smartSentry.captureError(e);
 | 
			
		||||
  } finally {
 | 
			
		||||
    tableLoading.value = false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  // ========= 定义 watch 监听 ===============
 | 
			
		||||
  watch(
 | 
			
		||||
// ========= 定义 watch 监听 ===============
 | 
			
		||||
watch(
 | 
			
		||||
    () => props.dataId,
 | 
			
		||||
    (e) => {
 | 
			
		||||
      if (e) {
 | 
			
		||||
| 
						 | 
				
			
			@ -137,44 +140,49 @@
 | 
			
		|||
        onSearch();
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    { immediate: true }
 | 
			
		||||
  );
 | 
			
		||||
    {immediate: true}
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
  // --------------- diff 特效 ---------------
 | 
			
		||||
  // diff
 | 
			
		||||
  const visibleDiff = ref(false);
 | 
			
		||||
  let prettyHtml = ref('');
 | 
			
		||||
  function showDetail(record) {
 | 
			
		||||
    visibleDiff.value = true;
 | 
			
		||||
    let diffOld = record.diffOld.replaceAll('<br/>', '\r\n');
 | 
			
		||||
    let diffNew = record.diffNew.replaceAll('<br/>', '\r\n');
 | 
			
		||||
    const args = ['', diffOld, diffNew, '变更前', '变更后'];
 | 
			
		||||
// --------------- diff 特效 ---------------
 | 
			
		||||
// diff
 | 
			
		||||
const visibleDiff = ref(false);
 | 
			
		||||
let prettyHtml = ref('');
 | 
			
		||||
 | 
			
		||||
    let diffPatch = Diff.createPatch(...args);
 | 
			
		||||
    let html = Diff2Html.html(diffPatch, {
 | 
			
		||||
      drawFileList: false,
 | 
			
		||||
      matching: 'words',
 | 
			
		||||
      diffMaxChanges: 1000,
 | 
			
		||||
      outputFormat: 'side-by-side',
 | 
			
		||||
    });
 | 
			
		||||
function showDetail(record) {
 | 
			
		||||
  visibleDiff.value = true;
 | 
			
		||||
  let diffOld = record.diffOld.replaceAll('<br/>', '\r\n');
 | 
			
		||||
  let diffNew = record.diffNew.replaceAll('<br/>', '\r\n');
 | 
			
		||||
  const args = ['', diffOld, diffNew, '变更前', '变更后'];
 | 
			
		||||
 | 
			
		||||
    prettyHtml.value = html;
 | 
			
		||||
    nextTick(() => {
 | 
			
		||||
      let diffDiv = document.querySelectorAll('.d2h-file-side-diff');
 | 
			
		||||
      if (diffDiv.length > 0) {
 | 
			
		||||
        let left = diffDiv[0],
 | 
			
		||||
  let diffPatch = Diff.createPatch(...args);
 | 
			
		||||
  let html = Diff2Html.html(diffPatch, {
 | 
			
		||||
    drawFileList: false,
 | 
			
		||||
    matching: 'words',
 | 
			
		||||
    diffMaxChanges: 1000,
 | 
			
		||||
    outputFormat: 'side-by-side',
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  prettyHtml.value = html;
 | 
			
		||||
  nextTick(() => {
 | 
			
		||||
    let diffDiv = document.querySelectorAll('.d2h-file-side-diff');
 | 
			
		||||
    if (diffDiv.length > 0) {
 | 
			
		||||
      let left = diffDiv[0],
 | 
			
		||||
          right = diffDiv[1];
 | 
			
		||||
        left.addEventListener('scroll', function (e) {
 | 
			
		||||
          if (left.scrollLeft !== right.scrollLeft) {
 | 
			
		||||
            right.scrollLeft = left.scrollLeft;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        right.addEventListener('scroll', function (e) {
 | 
			
		||||
          if (left.scrollLeft !== right.scrollLeft) {
 | 
			
		||||
            left.scrollLeft = right.scrollLeft;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
      left.addEventListener('scroll', function (e) {
 | 
			
		||||
        if (left.scrollLeft !== right.scrollLeft) {
 | 
			
		||||
          right.scrollLeft = left.scrollLeft;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      right.addEventListener('scroll', function (e) {
 | 
			
		||||
        if (left.scrollLeft !== right.scrollLeft) {
 | 
			
		||||
          left.scrollLeft = right.scrollLeft;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
defineExpose({
 | 
			
		||||
  ajaxQuery
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,24 +8,32 @@
 | 
			
		|||
 * @Copyright  1024创新实验室 ( https://1024lab.net ),Since 2012
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { SmartEnum } from '/@/types/smart-enum';
 | 
			
		||||
import {SmartEnum} from '/@/types/smart-enum';
 | 
			
		||||
 | 
			
		||||
// 业务类型
 | 
			
		||||
export const DATA_TRACER_TYPE_ENUM: SmartEnum<number> = {
 | 
			
		||||
  GOODS: {
 | 
			
		||||
    value: 1,
 | 
			
		||||
    desc: '商品',
 | 
			
		||||
  },
 | 
			
		||||
  OA_NOTICE: {
 | 
			
		||||
    value: 2,
 | 
			
		||||
    desc: 'OA-通知公告',
 | 
			
		||||
  },
 | 
			
		||||
  OA_ENTERPRISE: {
 | 
			
		||||
    value: 3,
 | 
			
		||||
    desc: 'OA-企业信息',
 | 
			
		||||
  },
 | 
			
		||||
    GOODS: {
 | 
			
		||||
        value: 1,
 | 
			
		||||
        desc: '商品',
 | 
			
		||||
    },
 | 
			
		||||
    OA_NOTICE: {
 | 
			
		||||
        value: 2,
 | 
			
		||||
        desc: 'OA-通知公告',
 | 
			
		||||
    },
 | 
			
		||||
    OA_ENTERPRISE: {
 | 
			
		||||
        value: 3,
 | 
			
		||||
        desc: 'OA-企业信息',
 | 
			
		||||
    },
 | 
			
		||||
    ASN: {
 | 
			
		||||
        value: 4,
 | 
			
		||||
        desc: '入库',
 | 
			
		||||
    },
 | 
			
		||||
    ASN_DETAIL: {
 | 
			
		||||
        value: 5,
 | 
			
		||||
        desc: '入库明细',
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  DATA_TRACER_TYPE_ENUM,
 | 
			
		||||
    DATA_TRACER_TYPE_ENUM,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,13 +84,13 @@
 | 
			
		|||
  <a-card class="smart-margin-top10" size="small">
 | 
			
		||||
    <a-tabs @change="handleTabChange">
 | 
			
		||||
      <a-tab-pane key="asnDetail" tab="入库明细">
 | 
			
		||||
        <ReceiveDetailList ref="receiveDetailListRef" :asnId="form.asnId" />
 | 
			
		||||
        <ReceiveDetailList ref="receiveDetailListRef" :asnId="form.asnId"/>
 | 
			
		||||
      </a-tab-pane>
 | 
			
		||||
      <a-tab-pane key="asnTask" tab="收货详情">
 | 
			
		||||
        <AsnTaskList ref="asnTaskListRef" :asnId="form.asnId"/>
 | 
			
		||||
      </a-tab-pane>
 | 
			
		||||
      <a-tab-pane key="dataTracer" tab="操作记录">
 | 
			
		||||
        <DataTracer :dataId="form.asnId" :type="DATA_TRACER_TYPE_ENUM.OA_ENTERPRISE.value"/>
 | 
			
		||||
        <DataTracer ref="dataTracerRef" :dataId="form.asnId" :type="DATA_TRACER_TYPE_ENUM.ASN.value"/>
 | 
			
		||||
      </a-tab-pane>
 | 
			
		||||
    </a-tabs>
 | 
			
		||||
  </a-card>
 | 
			
		||||
| 
						 | 
				
			
			@ -238,11 +238,15 @@ function onBack() {
 | 
			
		|||
//选项卡
 | 
			
		||||
const receiveDetailListRef = ref()
 | 
			
		||||
const asnTaskListRef = ref()
 | 
			
		||||
const dataTracerRef = ref()
 | 
			
		||||
 | 
			
		||||
function handleTabChange(activeKey: string) {
 | 
			
		||||
  if (activeKey === 'asnDetail' && receiveDetailListRef.value) {
 | 
			
		||||
    receiveDetailListRef.value.queryData();
 | 
			
		||||
  }else if(activeKey === 'asnTask' && asnTaskListRef.value){
 | 
			
		||||
  } else if (activeKey === 'asnTask' && asnTaskListRef.value) {
 | 
			
		||||
    asnTaskListRef.value.queryData();
 | 
			
		||||
  } else if (activeKey === 'dataTracer' && dataTracerRef.value) {
 | 
			
		||||
    dataTracerRef.value.ajaxQuery();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,9 +157,6 @@ async function queryData() {
 | 
			
		|||
    let queryResult = await taskApi.queryPage(queryForm);
 | 
			
		||||
    tableData.value = queryResult.data.list;
 | 
			
		||||
    total.value = queryResult.data.total;
 | 
			
		||||
 | 
			
		||||
    console.log(props.asnId);
 | 
			
		||||
    console.log(selectedRowKeyList.value);
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    smartSentry.captureError(e);
 | 
			
		||||
  } finally {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue