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