fix: 修复PIMTable不支持懒加载问题。修复【来票登记】金额格式化显示NaN问题。
style: 重构来票登记页面。
feat: 完善文件上传组件功能。【来票台账】底部添加合计。【来票登记】添加上传附件
已修改23个文件
已添加3个文件
3569 ■■■■■ 文件已修改
src/api/procurementManagement/invoiceEntry.js 82 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/procurementManagement/procurementInvoiceLedger.js 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Editor/index.vue 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FileUpload/index.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/PIMTable/PIMTable.vue 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Upload/FileUpload.vue 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/useModal.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/usePaginationApi.jsx 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/customerFile/index.vue 630 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/product/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/basicData/supplierManage/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/ledger/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/onboarding/index.vue 189 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/invoiceEntry/components/ExpandTable.vue 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/invoiceEntry/components/Modal.vue 407 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/invoiceEntry/index.vue 820 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/invoiceEntry/indexOld.vue 725 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/paymentEntry/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/paymentHistory/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/paymentLedger/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementInvoiceLedger/index.vue 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/procurementLedger/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/procurementManagement/thePaymentLedger/index.vue 109 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/projectProfit/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/reportAnalysis/taxComparison/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/receiptPaymentHistory/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/procurementManagement/invoiceEntry.js
@@ -1,69 +1,69 @@
// é‡‡è´­-来票登记接口
import request from '@/utils/request'
import request from "@/utils/request";
// æŸ¥è¯¢é‡‡è´­åˆåŒå·
export function getProduct(query) {
    return request({
        url: '/purchase/ledger/getProduct',
        method: 'get',
        params: query
    })
  return request({
    url: "/purchase/ledger/getProduct",
    method: "get",
    params: query,
  });
}
// æŸ¥è¯¢id采购合同号
export function getPurchaseNoById(query) {
    return request({
        url: '/purchase/ledger/getPurchaseNoById',
        method: 'get',
        params: query
    })
  return request({
    url: "/purchase/ledger/getPurchaseNoById",
    method: "get",
    params: query,
  });
}
// æ ¹æ®é‡‡è´­åˆåŒå·æŸ¥è¯¢è¯¦ç»†ä¿¡æ¯
export function getInfo(query) {
    return request({
        url: '/purchase/ledger/getInfo',
        method: 'get',
        params: query
    })
  return request({
    url: "/purchase/ledger/getInfo",
    method: "get",
    params: query,
  });
}
// ä¸»åˆ—表查询
export function gePurchaseList(query) {
    return request({
        url: '/purchase/ledger/list',
        method: 'get',
        params: query
    })
  return request({
    url: "/purchase/ledger/list",
    method: "get",
    params: query,
  });
}
// ä¸»åˆ—表查询
export function getRegistrationById(query) {
    return request({
        url: '/purchase/registration/getRegistrationById',
        method: 'get',
        params: query
    })
  return request({
    url: "/purchase/registration/getRegistrationById",
    method: "get",
    params: query,
  });
}
// æ–°å¢žç¼–辑来票登记
export function addOrUpdateRegistration(query) {
    return request({
        url: '/purchase/registration/addOrUpdateRegistration',
        method: 'post',
        data: query
    })
  return request({
    url: "/purchase/registration/addOrUpdateRegistration",
    method: "post",
    data: query,
  });
}
// åˆ é™¤æ¥ç¥¨ç™»è®°
export function delRegistration(query) {
    return request({
        url: '/purchase/registration/delRegistration',
        method: 'delete',
        data: query
    })
  return request({
    url: "/purchase/registration/delRegistration",
    method: "delete",
    data: query,
  });
}
// ä¸»åˆ—表查询
export function gePurchaseListPage(query) {
    return request({
        url: '/purchase/ledger/listPage',
        method: 'get',
        params: query
    })
  return request({
    url: "/purchase/ledger/listPage",
    method: "get",
    params: query,
  });
}
src/api/procurementManagement/procurementInvoiceLedger.js
@@ -10,13 +10,13 @@
  });
}
// æŸ¥è¯¢è¯¦æƒ…
export function getInvoiceById(query) {
  return request({
    url: "/purchase/registration/getRegistrationById",
    method: "get",
    params: query,
  });
}
// export function getInvoiceById(query) {
//   return request({
//     url: "/purchase/registration/getRegistrationById",
//     method: "get",
//     params: query,
//   });
// }
// æ–°å¢žã€ç¼–辑
export function addOrUpdateInvoice(query) {
  return request({
src/components/Editor/index.vue
@@ -27,18 +27,18 @@
</template>
<script setup>
import axios from 'axios'
import { QuillEditor } from "@vueup/vue-quill"
import "@vueup/vue-quill/dist/vue-quill.snow.css"
import { getToken } from "@/utils/auth"
import axios from "axios";
import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { getToken } from "@/utils/auth";
const { proxy } = getCurrentInstance()
const { proxy } = getCurrentInstance();
const quillEditorRef = ref()
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload") // ä¸Šä¼ çš„图片服务器地址
const quillEditorRef = ref();
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // ä¸Šä¼ çš„图片服务器地址
const headers = ref({
  Authorization: "Bearer " + getToken()
})
  Authorization: "Bearer " + getToken(),
});
const props = defineProps({
  /* ç¼–辑器的内容 */
@@ -69,8 +69,8 @@
  type: {
    type: String,
    default: "url",
  }
})
  },
});
const options = ref({
  theme: "snow",
@@ -79,74 +79,78 @@
  modules: {
    // å·¥å…·æ é…ç½®
    toolbar: [
      ["bold", "italic", "underline", "strike"],      // åŠ ç²— æ–œä½“ ä¸‹åˆ’线 åˆ é™¤çº¿
      ["blockquote", "code-block"],                   // å¼•用  ä»£ç å—
      [{ list: "ordered" }, { list: "bullet" }],      // æœ‰åºã€æ— åºåˆ—表
      [{ indent: "-1" }, { indent: "+1" }],           // ç¼©è¿›
      [{ size: ["small", false, "large", "huge"] }],  // å­—体大小
      [{ header: [1, 2, 3, 4, 5, 6, false] }],        // æ ‡é¢˜
      [{ color: [] }, { background: [] }],            // å­—体颜色、字体背景颜色
      [{ align: [] }],                                // å¯¹é½æ–¹å¼
      ["clean"],                                      // æ¸…除文本格式
      ["link", "image", "video"]                      // é“¾æŽ¥ã€å›¾ç‰‡ã€è§†é¢‘
      ["bold", "italic", "underline", "strike"], // åŠ ç²— æ–œä½“ ä¸‹åˆ’线 åˆ é™¤çº¿
      ["blockquote", "code-block"], // å¼•用  ä»£ç å—
      [{ list: "ordered" }, { list: "bullet" }], // æœ‰åºã€æ— åºåˆ—表
      [{ indent: "-1" }, { indent: "+1" }], // ç¼©è¿›
      [{ size: ["small", false, "large", "huge"] }], // å­—体大小
      [{ header: [1, 2, 3, 4, 5, 6, false] }], // æ ‡é¢˜
      [{ color: [] }, { background: [] }], // å­—体颜色、字体背景颜色
      [{ align: [] }], // å¯¹é½æ–¹å¼
      ["clean"], // æ¸…除文本格式
      ["link", "image", "video"], // é“¾æŽ¥ã€å›¾ç‰‡ã€è§†é¢‘
    ],
  },
  placeholder: "请输入内容",
  readOnly: props.readOnly
})
  readOnly: props.readOnly,
});
const styles = computed(() => {
  let style = {}
  let style = {};
  if (props.minHeight) {
    style.minHeight = `${props.minHeight}px`
    style.minHeight = `${props.minHeight}px`;
  }
  if (props.height) {
    style.height = `${props.height}px`
    style.height = `${props.height}px`;
  }
  return style
})
  return style;
});
const content = ref("")
watch(() => props.modelValue, (v) => {
  if (v !== content.value) {
    content.value = v == undefined ? "<p></p>" : v
  }
}, { immediate: true })
const content = ref("");
watch(
  () => props.modelValue,
  (v) => {
    if (v !== content.value) {
      content.value = v == undefined ? "<p></p>" : v;
    }
  },
  { immediate: true }
);
// å¦‚果设置了上传地址则自定义图片上传事件
onMounted(() => {
  if (props.type == 'url') {
    let quill = quillEditorRef.value.getQuill()
    let toolbar = quill.getModule("toolbar")
  if (props.type == "url") {
    let quill = quillEditorRef.value.getQuill();
    let toolbar = quill.getModule("toolbar");
    toolbar.addHandler("image", (value) => {
      if (value) {
        proxy.$refs.uploadRef.click()
        proxy.$refs.uploadRef.click();
      } else {
        quill.format("image", false)
        quill.format("image", false);
      }
    })
    quill.root.addEventListener('paste', handlePasteCapture, true)
    });
    quill.root.addEventListener("paste", handlePasteCapture, true);
  }
})
});
// ä¸Šä¼ å‰æ ¡æ£€æ ¼å¼å’Œå¤§å°
function handleBeforeUpload(file) {
  const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"]
  const isJPG = type.includes(file.type)
  const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"];
  const isJPG = type.includes(file.type);
  //检验文件格式
  if (!isJPG) {
    proxy.$modal.msgError(`图片格式错误!`)
    return false
    proxy.$modal.msgError(`图片格式错误!`);
    return false;
  }
  // æ ¡æ£€æ–‡ä»¶å¤§å°
  if (props.fileSize) {
    const isLt = file.size / 1024 / 1024 < props.fileSize
    const isLt = file.size / 1024 / 1024 < props.fileSize;
    if (!isLt) {
      proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`)
      return false
      proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
      return false;
    }
  }
  return true
  return true;
}
// ä¸Šä¼ æˆåŠŸå¤„ç†
@@ -154,44 +158,55 @@
  // å¦‚果上传成功
  if (res.code == 200) {
    // èŽ·å–å¯Œæ–‡æœ¬å®žä¾‹
    let quill = toRaw(quillEditorRef.value).getQuill()
    let quill = toRaw(quillEditorRef.value).getQuill();
    // èŽ·å–å…‰æ ‡ä½ç½®
    let length = quill.selection.savedRange.index
    let length = quill.selection.savedRange.index;
    // æ’入图片,res.url为服务器返回的图片链接地址
    quill.insertEmbed(length, "image", import.meta.env.VITE_APP_BASE_API + res.fileName)
    quill.insertEmbed(
      length,
      "image",
      import.meta.env.VITE_APP_BASE_API + res.fileName
    );
    // è°ƒæ•´å…‰æ ‡åˆ°æœ€åŽ
    quill.setSelection(length + 1)
    quill.setSelection(length + 1);
  } else {
    proxy.$modal.msgError("图片插入失败")
    proxy.$modal.msgError("图片插入失败");
  }
}
// ä¸Šä¼ å¤±è´¥å¤„理
function handleUploadError() {
  proxy.$modal.msgError("图片插入失败")
  proxy.$modal.msgError("图片插入失败");
}
// å¤åˆ¶ç²˜è´´å›¾ç‰‡å¤„理
function handlePasteCapture(e) {
  const clipboard = e.clipboardData || window.clipboardData
  const clipboard = e.clipboardData || window.clipboardData;
  if (clipboard && clipboard.items) {
    for (let i = 0; i < clipboard.items.length; i++) {
      const item = clipboard.items[i]
      if (item.type.indexOf('image') !== -1) {
        e.preventDefault()
        const file = item.getAsFile()
        insertImage(file)
      const item = clipboard.items[i];
      if (item.type.indexOf("image") !== -1) {
        e.preventDefault();
        const file = item.getAsFile();
        insertImage(file);
      }
    }
  }
}
function insertImage(file) {
  const formData = new FormData()
  formData.append("file", file)
  axios.post(uploadUrl.value, formData, { headers: { "Content-Type": "multipart/form-data", Authorization: headers.value.Authorization } }).then(res => {
    handleUploadSuccess(res.data)
  })
  const formData = new FormData();
  formData.append("file", file);
  axios
    .post(uploadUrl.value, formData, {
      headers: {
        "Content-Type": "multipart/form-data",
        Authorization: headers.value.Authorization,
      },
    })
    .then((res) => {
      handleUploadSuccess(res.data);
    });
}
</script>
@@ -199,7 +214,8 @@
.editor-img-uploader {
  display: none;
}
.editor, .ql-toolbar {
.editor,
.ql-toolbar {
  white-space: pre-wrap !important;
  line-height: normal !important;
}
src/components/FileUpload/index.vue
@@ -22,18 +22,40 @@
    <!-- ä¸Šä¼ æç¤º -->
    <div class="el-upload__tip" v-if="showTip && !disabled">
      è¯·ä¸Šä¼ 
      <template v-if="fileSize"> å¤§å°ä¸è¶…过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
      <template v-if="fileType"> æ ¼å¼ä¸º <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
      <template v-if="fileSize">
        å¤§å°ä¸è¶…过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
      </template>
      <template v-if="fileType">
        æ ¼å¼ä¸º <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
      </template>
      çš„æ–‡ä»¶
    </div>
    <!-- æ–‡ä»¶åˆ—表 -->
    <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
      <li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
        <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
    <transition-group
      class="upload-file-list el-upload-list el-upload-list--text"
      name="el-fade-in-linear"
      tag="ul"
    >
      <li
        :key="file.uid"
        class="el-upload-list__item ele-upload-list__item-content"
        v-for="(file, index) in fileList"
      >
        <el-link
          :href="`${baseUrl}${file.url}`"
          :underline="false"
          target="_blank"
        >
          <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
        </el-link>
        <div class="ele-upload-list__item-content-action">
          <el-link :underline="false" @click="handleDelete(index)" type="danger" v-if="!disabled">&nbsp;删除</el-link>
          <el-link
            :underline="false"
            @click="handleDelete(index)"
            type="danger"
            v-if="!disabled"
            >&nbsp;删除</el-link
          >
        </div>
      </li>
    </transition-group>
@@ -41,152 +63,160 @@
</template>
<script setup>
import { getToken } from "@/utils/auth"
import Sortable from 'sortablejs'
import { getToken } from "@/utils/auth";
import Sortable from "sortablejs";
const props = defineProps({
  modelValue: [String, Object, Array],
  // ä¸Šä¼ æŽ¥å£åœ°å€
  action: {
    type: String,
    default: "/common/upload"
    default: "/common/upload",
  },
  // ä¸Šä¼ æºå¸¦çš„参数
  data: {
    type: Object
    type: Object,
  },
  // æ•°é‡é™åˆ¶
  limit: {
    type: Number,
    default: 5
    default: 5,
  },
  // å¤§å°é™åˆ¶(MB)
  fileSize: {
    type: Number,
    default: 5
    default: 5,
  },
  // æ–‡ä»¶ç±»åž‹, ä¾‹å¦‚['png', 'jpg', 'jpeg']
  fileType: {
    type: Array,
    default: () => ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf"]
    default: () => ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf"],
  },
  // æ˜¯å¦æ˜¾ç¤ºæç¤º
  isShowTip: {
    type: Boolean,
    default: true
    default: true,
  },
  // ç¦ç”¨ç»„件(仅查看文件)
  disabled: {
    type: Boolean,
    default: false
    default: false,
  },
  // æ‹–动排序
  drag: {
    type: Boolean,
    default: true
  }
})
    default: true,
  },
});
const { proxy } = getCurrentInstance()
const emit = defineEmits()
const number = ref(0)
const uploadList = ref([])
const baseUrl = import.meta.env.VITE_APP_BASE_API
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + props.action) // ä¸Šä¼ æ–‡ä»¶æœåŠ¡å™¨åœ°å€
const headers = ref({ Authorization: "Bearer " + getToken() })
const fileList = ref([])
const { proxy } = getCurrentInstance();
const emit = defineEmits();
const number = ref(0);
const uploadList = ref([]);
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + props.action); // ä¸Šä¼ æ–‡ä»¶æœåŠ¡å™¨åœ°å€
const headers = ref({ Authorization: "Bearer " + getToken() });
const fileList = ref([]);
const showTip = computed(
  () => props.isShowTip && (props.fileType || props.fileSize)
)
);
watch(() => props.modelValue, val => {
  if (val) {
    let temp = 1
    // é¦–先将值转为数组
    const list = Array.isArray(val) ? val : props.modelValue.split(',')
    // ç„¶åŽå°†æ•°ç»„转为对象数组
    fileList.value = list.map(item => {
      if (typeof item === "string") {
        item = { name: item, url: item }
      }
      item.uid = item.uid || new Date().getTime() + temp++
      return item
    })
  } else {
    fileList.value = []
    return []
  }
},{ deep: true, immediate: true })
watch(
  () => props.modelValue,
  (val) => {
    if (val) {
      let temp = 1;
      // é¦–先将值转为数组
      const list = Array.isArray(val) ? val : props.modelValue.split(",");
      // ç„¶åŽå°†æ•°ç»„转为对象数组
      fileList.value = list.map((item) => {
        if (typeof item === "string") {
          item = { name: item, url: item };
        }
        item.uid = item.uid || new Date().getTime() + temp++;
        return item;
      });
    } else {
      fileList.value = [];
      return [];
    }
  },
  { deep: true, immediate: true }
);
// ä¸Šä¼ å‰æ ¡æ£€æ ¼å¼å’Œå¤§å°
function handleBeforeUpload(file) {
  // æ ¡æ£€æ–‡ä»¶ç±»åž‹
  if (props.fileType.length) {
    const fileName = file.name.split('.')
    const fileExt = fileName[fileName.length - 1]
    const isTypeOk = props.fileType.indexOf(fileExt) >= 0
    const fileName = file.name.split(".");
    const fileExt = fileName[fileName.length - 1];
    const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
    if (!isTypeOk) {
      proxy.$modal.msgError(`文件格式不正确,请上传${props.fileType.join("/")}格式文件!`)
      return false
      proxy.$modal.msgError(
        `文件格式不正确,请上传${props.fileType.join("/")}格式文件!`
      );
      return false;
    }
  }
  // æ ¡æ£€æ–‡ä»¶åæ˜¯å¦åŒ…含特殊字符
  if (file.name.includes(',')) {
    proxy.$modal.msgError('文件名不正确,不能包含英文逗号!')
    return false
  if (file.name.includes(",")) {
    proxy.$modal.msgError("文件名不正确,不能包含英文逗号!");
    return false;
  }
  // æ ¡æ£€æ–‡ä»¶å¤§å°
  if (props.fileSize) {
    const isLt = file.size / 1024 / 1024 < props.fileSize
    const isLt = file.size / 1024 / 1024 < props.fileSize;
    if (!isLt) {
      proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`)
      return false
      proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
      return false;
    }
  }
  proxy.$modal.loading("正在上传文件,请稍候...")
  number.value++
  return true
  proxy.$modal.loading("正在上传文件,请稍候...");
  number.value++;
  return true;
}
// æ–‡ä»¶ä¸ªæ•°è¶…出
function handleExceed() {
  proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} ä¸ª!`)
  proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} ä¸ª!`);
}
// ä¸Šä¼ å¤±è´¥
function handleUploadError(err) {
  proxy.$modal.msgError("上传文件失败")
  proxy.$modal.closeLoading()
  proxy.$modal.msgError("上传文件失败");
  proxy.$modal.closeLoading();
}
// ä¸Šä¼ æˆåŠŸå›žè°ƒ
function handleUploadSuccess(res, file) {
  if (res.code === 200) {
    uploadList.value.push({ name: res.fileName, url: res.fileName })
    uploadedSuccessfully()
    uploadList.value.push({ name: res.fileName, url: res.fileName });
    uploadedSuccessfully();
  } else {
    number.value--
    proxy.$modal.closeLoading()
    proxy.$modal.msgError(res.msg)
    proxy.$refs.fileUpload.handleRemove(file)
    uploadedSuccessfully()
    number.value--;
    proxy.$modal.closeLoading();
    proxy.$modal.msgError(res.msg);
    proxy.$refs.fileUpload.handleRemove(file);
    uploadedSuccessfully();
  }
}
// åˆ é™¤æ–‡ä»¶
function handleDelete(index) {
  fileList.value.splice(index, 1)
  emit("update:modelValue", listToString(fileList.value))
  fileList.value.splice(index, 1);
  emit("update:modelValue", listToString(fileList.value));
}
// ä¸Šä¼ ç»“束处理
function uploadedSuccessfully() {
  if (number.value > 0 && uploadList.value.length === number.value) {
    fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value)
    uploadList.value = []
    number.value = 0
    emit("update:modelValue", listToString(fileList.value))
    proxy.$modal.closeLoading()
    fileList.value = fileList.value
      .filter((f) => f.url !== undefined)
      .concat(uploadList.value);
    uploadList.value = [];
    number.value = 0;
    emit("update:modelValue", listToString(fileList.value));
    proxy.$modal.closeLoading();
  }
}
@@ -194,40 +224,40 @@
function getFileName(name) {
  // å¦‚果是url那么取最后的名字 å¦‚果不是直接返回
  if (name.lastIndexOf("/") > -1) {
    return name.slice(name.lastIndexOf("/") + 1)
    return name.slice(name.lastIndexOf("/") + 1);
  } else {
    return name
    return name;
  }
}
// å¯¹è±¡è½¬æˆæŒ‡å®šå­—符串分隔
function listToString(list, separator) {
  let strs = ""
  separator = separator || ","
  let strs = "";
  separator = separator || ",";
  for (let i in list) {
    if (list[i].url) {
      strs += list[i].url + separator
      strs += list[i].url + separator;
    }
  }
  return strs != '' ? strs.substr(0, strs.length - 1) : ''
  return strs != "" ? strs.substr(0, strs.length - 1) : "";
}
// åˆå§‹åŒ–拖拽排序
onMounted(() => {
  if (props.drag) {
    nextTick(() => {
      const element = document.querySelector('.upload-file-list')
      const element = document.querySelector(".upload-file-list");
      Sortable.create(element, {
        ghostClass: 'file-upload-darg',
        ghostClass: "file-upload-darg",
        onEnd: (evt) => {
          const movedItem = fileList.value.splice(evt.oldIndex, 1)[0]
          fileList.value.splice(evt.newIndex, 0, movedItem)
          emit('update:modelValue', listToString(fileList.value))
        }
      })
    })
          const movedItem = fileList.value.splice(evt.oldIndex, 1)[0];
          fileList.value.splice(evt.newIndex, 0, movedItem);
          emit("update:modelValue", listToString(fileList.value));
        },
      });
    });
  }
})
});
</script>
<style scoped lang="scss">
.file-upload-darg {
src/components/PIMTable/PIMTable.vue
@@ -5,18 +5,20 @@
    :border="border"
    :data="tableData"
    :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
    height="calc(100vh - 18.5em)"
    :height="height"
    :highlight-current-row="highlightCurrentRow"
    :row-class-name="rowClassName"
    :row-style="rowStyle"
    :row-key="rowKey"
    style="width: 100%"
    tooltip-effect="dark"
    @row-click="rowClick"
    @current-change="currentChange"
    :expand-row-keys="expandRowKeys"
    :show-summary="isShowSummary"
    :summary-method="summaryMethod"
    @row-click="rowClick"
    @current-change="currentChange"
    @selection-change="handleSelectionChange"
    @expand-change="expandChange"
    class="lims-table"
  >
    <el-table-column
@@ -224,7 +226,7 @@
const uploadHeader = proxy.uploadHeader;
const javaApi = proxy.javaApi;
const emit = defineEmits(["pagination"]);
const emit = defineEmits(["pagination", "expand-change", "selection-change"]);
// Filters
const typeFn = (val, row) => {
@@ -241,9 +243,13 @@
    type: Boolean,
    default: false,
  },
  handleSelectionChange: {
    type: Function,
    default: () => {},
  height: {
    type: [Number, String],
    default: "calc(100vh - 18.5em)",
  },
  expandRowKeys: {
    type: Array,
    default: () => [],
  },
  summaryMethod: {
    type: Function,
@@ -405,6 +411,14 @@
const paginationSearch = ({ page, limit }) => {
  emit("pagination", { page: page, limit: limit });
};
const expandChange = (row, expandedRows) => {
  emit("expand-change", row, expandedRows);
};
const handleSelectionChange = (newSelection) => {
  emit("selection-change", newSelection);
};
</script>
<style scoped lang="scss">
src/components/Upload/FileUpload.vue
@@ -18,8 +18,20 @@
    type: Boolean,
    default: false,
  },
  showTip: {
    type: Boolean,
    default: true,
  },
  autoUpload: {
    type: Boolean,
    default: false,
  },
  limit: {
    type: Number,
    default: 1,
  },
});
const emits = defineEmits(["success", "error"]);
const emits = defineEmits(["success", "remove"]);
const uploadRef = ref();
const fileList = ref([]);
@@ -29,10 +41,12 @@
};
const handleFileSuccess = (response, file, fileList) => {
  upload.open = false;
  upload.isUploading = false;
  uploadRef.value.handleRemove(file);
  // uploadRef.value.handleRemove(file);
  emits("success", response, file, fileList);
};
const handleRemove = (file) => {
  emits("remove", file);
};
defineExpose({
@@ -51,10 +65,11 @@
    :accept="accept"
    :headers="headers"
    :disabled="disabled"
    :auto-upload="false"
    :limit="1"
    :auto-upload="autoUpload"
    :limit="limit"
    :drag="true"
    :on-success="handleFileSuccess"
    :on-remove="handleRemove"
  >
    <div class="el-upload__text">
      <el-icon class="el-icon--upload"><upload-filled /></el-icon>
@@ -64,7 +79,7 @@
      </div>
    </div>
    <template #tip>
      <div class="el-upload__tip text-center">
      <div v-if="showTip" class="el-upload__tip text-center">
        åªèƒ½ä¸Šä¼ xlsx/xls文件,且不超过10M
        <el-button
          type="primary"
src/hooks/useModal.js
@@ -8,11 +8,10 @@
  const openModal = (e) => {
    id.value = e;
    modalOptions.value = {
      title: e ? "编辑设备台账" : "新增设备台账",
      title: e ? `修改${options.title}` : `新增${options.title}`,
      content: "确定执行此操作吗?",
      confirmText: "确定",
      cancelText: "取消",
      ...options,
    };
    visible.value = true;
  };
src/hooks/usePaginationApi.jsx
@@ -1,6 +1,7 @@
import { ref, reactive, watchEffect, unref } from "vue";
import useFormData from "@/hooks/useFormData";
import { deepClone, isEqual } from "@/utils/index.js"
import { ElMessage } from 'element-plus'
/**
 * åˆ†é¡µapi
@@ -85,7 +86,7 @@
      ...getFinalParams(),
      current: pagination.currentPage,
      size: pagination.pageSize
    }).then(({ code, data, ...rest }) => {
    }).then(({ code, data, msg, ...rest }) => {
      if (code == 200) {
        // pagination.currentPage = meta.current_page;
        // pagination.pageSize = meta.per_page;
@@ -96,7 +97,7 @@
        loading.value = false;
      } else {
        loading.value = false;
        ElMessage({ message: data.msg, type: "error" });
        ElMessage({ message: msg, type: "error" });
      }
    });
  }
src/views/basicData/customerFile/index.vue
@@ -1,97 +1,170 @@
<template>
<div class="app-container">
  <div class="search_form">
    <div>
      <span class="search_title">客户名称:</span>
      <el-input
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title">客户名称:</span>
        <el-input
          v-model="searchForm.customerName"
          style="width: 240px"
          placeholder="请输入"
          @change="handleQuery"
          clearable
          :prefix-icon="Search"
      />
      <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
        />
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
          >搜索</el-button
        >
      </div>
      <div>
        <el-button type="primary" @click="openForm('add')">新增客户</el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button type="info" plain icon="Upload" @click="handleImport"
          >导入</el-button
        >
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div>
      <el-button type="primary" @click="openForm('add')">新增客户</el-button>
      <el-button @click="handleOut">导出</el-button>
      <el-button type="info" plain icon="Upload" @click="handleImport">导入</el-button>
      <el-button type="danger" plain @click="handleDelete">删除</el-button>
    <div class="table_list">
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :isSelection="true"
        @selection-change="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="total"
      ></PIMTable>
    </div>
  </div>
  <div class="table_list">
    <PIMTable :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true" :handleSelectionChange="handleSelectionChange"
              :tableLoading="tableLoading" @pagination="pagination" :total="total"></PIMTable>
  </div>
  <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '新增客户信息' : '编辑客户信息'" width="70%" @close="closeDia">
    <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="客户名称:" prop="customerName">
            <el-input v-model="form.customerName" placeholder="请输入" clearable/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="纳税人识别号:" prop="taxpayerIdentificationNumber">
            <el-input v-model="form.taxpayerIdentificationNumber" placeholder="请输入" clearable/>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="公司地址:" prop="companyAddress">
            <el-input v-model="form.companyAddress" placeholder="请输入" clearable/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="公司电话:" prop="companyPhone">
            <el-input v-model="form.companyPhone" placeholder="请输入" clearable/>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="联系人:" prop="contactPerson">
            <el-input v-model="form.contactPerson" placeholder="请输入" clearable/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="联系电话:" prop="contactPhone">
            <el-input v-model="form.contactPhone" placeholder="请输入" clearable/>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="银行基本户:" prop="basicBankAccount">
            <el-input v-model="form.basicBankAccount" placeholder="请输入" clearable/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="银行账号:" prop="bankAccount">
            <el-input v-model="form.bankAccount" placeholder="请输入" clearable/>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="开户行号:" prop="bankCode">
            <el-input v-model="form.bankCode" placeholder="请输入" clearable/>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="维护人:" prop="maintainer">
            <el-select v-model="form.maintainer" placeholder="请选择" clearable disabled>
              <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="维护时间:" prop="maintenanceTime" >
            <el-date-picker
    <el-dialog
      v-model="dialogFormVisible"
      :title="operationType === 'add' ? '新增客户信息' : '编辑客户信息'"
      width="70%"
      @close="closeDia"
    >
      <el-form
        :model="form"
        label-width="140px"
        label-position="top"
        :rules="rules"
        ref="formRef"
      >
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="客户名称:" prop="customerName">
              <el-input
                v-model="form.customerName"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item
              label="纳税人识别号:"
              prop="taxpayerIdentificationNumber"
            >
              <el-input
                v-model="form.taxpayerIdentificationNumber"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="公司地址:" prop="companyAddress">
              <el-input
                v-model="form.companyAddress"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="公司电话:" prop="companyPhone">
              <el-input
                v-model="form.companyPhone"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="联系人:" prop="contactPerson">
              <el-input
                v-model="form.contactPerson"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="联系电话:" prop="contactPhone">
              <el-input
                v-model="form.contactPhone"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="银行基本户:" prop="basicBankAccount">
              <el-input
                v-model="form.basicBankAccount"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="银行账号:" prop="bankAccount">
              <el-input
                v-model="form.bankAccount"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="开户行号:" prop="bankCode">
              <el-input
                v-model="form.bankCode"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="维护人:" prop="maintainer">
              <el-select
                v-model="form.maintainer"
                placeholder="请选择"
                clearable
                disabled
              >
                <el-option
                  v-for="item in userList"
                  :key="item.nickName"
                  :label="item.nickName"
                  :value="item.nickName"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="维护时间:" prop="maintenanceTime">
              <el-date-picker
                style="width: 100%"
                v-model="form.maintenanceTime"
                value-format="YYYY-MM-DD"
@@ -100,155 +173,186 @@
                placeholder="请选择"
                clearable
                disabled
            />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitForm">确认</el-button>
        <el-button @click="closeDia">取消</el-button>
      </div>
    </template>
  </el-dialog>
  <!-- ç”¨æˆ·å¯¼å…¥å¯¹è¯æ¡† -->
  <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
    <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
      <el-icon class="el-icon--upload"><upload-filled /></el-icon>
      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
      <template #tip>
        <div class="el-upload__tip text-center">
          <span>仅允许导入xls、xlsx格式文件。</span>
          <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-upload>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitFileForm">ç¡® å®š</el-button>
        <el-button @click="upload.open = false">取 æ¶ˆ</el-button>
      </div>
    </template>
  </el-dialog>
</div>
    </el-dialog>
    <!-- ç”¨æˆ·å¯¼å…¥å¯¹è¯æ¡† -->
    <el-dialog
      :title="upload.title"
      v-model="upload.open"
      width="400px"
      append-to-body
    >
      <el-upload
        ref="uploadRef"
        :limit="1"
        accept=".xlsx, .xls"
        :headers="upload.headers"
        :action="upload.url + '?updateSupport=' + upload.updateSupport"
        :disabled="upload.isUploading"
        :on-progress="handleFileUploadProgress"
        :on-success="handleFileSuccess"
        :auto-upload="false"
        drag
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
        <template #tip>
          <div class="el-upload__tip text-center">
            <span>仅允许导入xls、xlsx格式文件。</span>
            <el-link
              type="primary"
              :underline="false"
              style="font-size: 12px; vertical-align: baseline"
              @click="importTemplate"
              >下载模板</el-link
            >
          </div>
        </template>
      </el-upload>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitFileForm">ç¡® å®š</el-button>
          <el-button @click="upload.open = false">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import {Search} from "@element-plus/icons-vue";
import {addCustomer, delCustomer, getCustomer, listCustomer, updateCustomer} from "@/api/basicData/customerFile.js";
import {ElMessageBox } from "element-plus";
import {userListNoPage} from "@/api/system/user.js";
import useUserStore from "@/store/modules/user"
import {getToken} from "@/utils/auth.js";
const { proxy } = getCurrentInstance()
const userStore = useUserStore()
import { ref } from "vue";
import { Search } from "@element-plus/icons-vue";
import {
  addCustomer,
  delCustomer,
  getCustomer,
  listCustomer,
  updateCustomer,
} from "@/api/basicData/customerFile.js";
import { ElMessageBox } from "element-plus";
import { userListNoPage } from "@/api/system/user.js";
import useUserStore from "@/store/modules/user";
import { getToken } from "@/utils/auth.js";
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
const tableColumn = ref([
  {
    label: '客户名称',
    prop: 'customerName',
    label: "客户名称",
    prop: "customerName",
    width: 220,
  },
  {
    label: '纳税人识别码',
    prop: 'taxpayerIdentificationNumber',
    label: "纳税人识别码",
    prop: "taxpayerIdentificationNumber",
    width: 220,
  },
  {
    label: '地址及联系方式',
    prop: 'addressPhone',
    label: "地址及联系方式",
    prop: "addressPhone",
    width: 220,
  },
  {
    label: '联系人',
    prop: 'contactPerson'
    label: "联系人",
    prop: "contactPerson",
  },
  {
    label: '联系电话',
    prop: 'contactPhone',
    label: "联系电话",
    prop: "contactPhone",
  },
  {
    label: '银行基本户',
    prop: 'basicBankAccount',
    label: "银行基本户",
    prop: "basicBankAccount",
  },
  {
    label: '银行账号',
    prop: 'bankAccount',
    label: "银行账号",
    prop: "bankAccount",
  },
  {
    label: '开户行号',
    prop: 'bankCode',
    label: "开户行号",
    prop: "bankCode",
  },
  {
    label: '维护人',
    prop: 'maintainer',
    label: "维护人",
    prop: "maintainer",
  },
  {
    label: '维护时间',
    prop: 'maintenanceTime',
    label: "维护时间",
    prop: "maintenanceTime",
  },
  {
    dataType: "action",
    label: "操作",
    align: 'center',
    align: "center",
    operation: [
      {
        name: "编辑",
        type: "text",
        clickFun: (row) => {
          openForm('edit', row);
          openForm("edit", row);
        },
      },
    ],
  },
])
const tableData = ref([])
const selectedRows = ref([])
const userList = ref([])
const tableLoading = ref(false)
]);
const tableData = ref([]);
const selectedRows = ref([]);
const userList = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 10,
})
const total = ref(0)
});
const total = ref(0);
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref('')
const dialogFormVisible = ref(false)
const operationType = ref("");
const dialogFormVisible = ref(false);
const data = reactive({
  searchForm: {
    customerName: '',
    customerName: "",
  },
  form: {
    customerName: '',
    taxpayerIdentificationNumber: '',
    companyAddress: '',
    companyPhone: '',
    contactPerson: '',
    contactPhone: '',
    maintainer: '',
    maintenanceTime: '',
    basicBankAccount:'',
    bankAccount:'',
    bankCode:''
    customerName: "",
    taxpayerIdentificationNumber: "",
    companyAddress: "",
    companyPhone: "",
    contactPerson: "",
    contactPhone: "",
    maintainer: "",
    maintenanceTime: "",
    basicBankAccount: "",
    bankAccount: "",
    bankCode: "",
  },
  rules: {
    customerName: [{ required: true, message: "请输入", trigger: "blur" }],
    taxpayerIdentificationNumber: [{ required: true, message: "请输入", trigger: "blur" }],
    taxpayerIdentificationNumber: [
      { required: true, message: "请输入", trigger: "blur" },
    ],
    companyAddress: [{ required: true, message: "请输入", trigger: "blur" }],
    companyPhone: [{ required: true, message: "请输入", trigger: "blur" }],
    contactPerson: [{ required: true, message: "请输入", trigger: "blur" }],
    contactPhone: [{ required: true, message: "请输入", trigger: "blur" }],
    maintainer: [{ required: false, message: "请选择", trigger: "change" }],
    maintenanceTime: [{ required: false, message: "请选择", trigger: "change" }],
    maintenanceTime: [
      { required: false, message: "请选择", trigger: "change" },
    ],
    basicBankAccount: [{ required: true, message: "请输入", trigger: "blur" }],
    bankAccount: [{ required: true, message: "请输入", trigger: "blur" }],
    bankCode: [{ required: true, message: "请输入", trigger: "blur" }],
  }
})
  },
});
const upload = reactive({
  // æ˜¯å¦æ˜¾ç¤ºå¼¹å‡ºå±‚(客户导入)
  open: false,
@@ -259,147 +363,145 @@
  // è®¾ç½®ä¸Šä¼ çš„请求头部
  headers: { Authorization: "Bearer " + getToken() },
  // ä¸Šä¼ çš„地址
  url: import.meta.env.VITE_APP_BASE_API + "/basic/customer/importData"
})
const { searchForm, form, rules } = toRefs(data)
  url: import.meta.env.VITE_APP_BASE_API + "/basic/customer/importData",
});
const { searchForm, form, rules } = toRefs(data);
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1
  getList()
}
  page.current = 1;
  getList();
};
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList()
}
  getList();
};
const getList = () => {
  tableLoading.value = true
  listCustomer({...searchForm.value, ...page}).then(res => {
    tableLoading.value = false
    tableData.value = res.records
    total.value = res.total
  })
}
  tableLoading.value = true;
  listCustomer({ ...searchForm.value, ...page }).then((res) => {
    tableLoading.value = false;
    tableData.value = res.records;
    total.value = res.total;
  });
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection
}
  selectedRows.value = selection;
};
/** æäº¤ä¸Šä¼ æ–‡ä»¶ */
function submitFileForm() {
  proxy.$refs["uploadRef"].submit()
  proxy.$refs["uploadRef"].submit();
}
/** å¯¼å…¥æŒ‰é’®æ“ä½œ */
function handleImport() {
  upload.title = "客户导入"
  upload.open = true
  upload.title = "客户导入";
  upload.open = true;
}
// æ‰“开弹框
const openForm = (type, row) => {
  operationType.value = type
  form.value = {}
  form.value.maintainer = userStore.nickName
  operationType.value = type;
  form.value = {};
  form.value.maintainer = userStore.nickName;
  form.value.maintenanceTime = getCurrentDate();
  userListNoPage().then(res => {
    userList.value = res.data
  })
  if (type === 'edit') {
    getCustomer(row.id).then(res => {
      form.value = {...res.data}
    })
  userListNoPage().then((res) => {
    userList.value = res.data;
  });
  if (type === "edit") {
    getCustomer(row.id).then((res) => {
      form.value = { ...res.data };
    });
  }
  dialogFormVisible.value = true
}
  dialogFormVisible.value = true;
};
// æäº¤è¡¨å•
const submitForm = () => {
  proxy.$refs["formRef"].validate(valid => {
  proxy.$refs["formRef"].validate((valid) => {
    if (valid) {
      if (operationType.value === "edit") {
        submitEdit()
        submitEdit();
      } else {
        submitAdd()
        submitAdd();
      }
    }
  })
}
  });
};
// æäº¤æ–°å¢ž
const submitAdd = () => {
  addCustomer(form.value).then(res => {
    proxy.$modal.msgSuccess("提交成功")
    closeDia()
    getList()
  })
}
  addCustomer(form.value).then((res) => {
    proxy.$modal.msgSuccess("提交成功");
    closeDia();
    getList();
  });
};
// æäº¤ä¿®æ”¹
const submitEdit = () => {
  updateCustomer(form.value).then(res => {
    proxy.$modal.msgSuccess("提交成功")
    closeDia()
    getList()
  })
}
  updateCustomer(form.value).then((res) => {
    proxy.$modal.msgSuccess("提交成功");
    closeDia();
    getList();
  });
};
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef")
  dialogFormVisible.value = false
}
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm(
      '选中的内容将被导出,是否确认导出?',
      '导出', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
      }
  ).then(() => {
    proxy.download("/basic/customer/export", {}, '客户档案.xlsx')
  }).catch(() => {
    proxy.$modal.msg("已取消")
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
}
    .then(() => {
      proxy.download("/basic/customer/export", {}, "客户档案.xlsx");
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
// åˆ é™¤
const handleDelete = () => {
  let ids = []
  let ids = [];
  if (selectedRows.value.length > 0) {
    ids = selectedRows.value.map(item => item.id);
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning('请选择数据')
    return
    proxy.$modal.msgWarning("请选择数据");
    return;
  }
  ElMessageBox.confirm(
      '选中的内容将被删除,是否确认删除?',
      '删除提示', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
      }
  ).then(() => {
    tableLoading.value = true
    delCustomer(ids).then(res => {
      proxy.$modal.msgSuccess("删除成功")
      getList()
    }).finally(() => {
      tableLoading.value = false
    })
  }).catch(() => {
    proxy.$modal.msg("已取消")
  ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
}
    .then(() => {
      tableLoading.value = true;
      delCustomer(ids)
        .then((res) => {
          proxy.$modal.msgSuccess("删除成功");
          getList();
        })
        .finally(() => {
          tableLoading.value = false;
        });
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
// èŽ·å–å½“å‰æ—¥æœŸå¹¶æ ¼å¼åŒ–ä¸º YYYY-MM-DD
function getCurrentDate() {
  const today = new Date();
  const year = today.getFullYear();
  const month = String(today.getMonth() + 1).padStart(2, '0'); // æœˆä»½ä»Ž0开始
  const day = String(today.getDate()).padStart(2, '0');
  const month = String(today.getMonth() + 1).padStart(2, "0"); // æœˆä»½ä»Ž0开始
  const day = String(today.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
}
getList()
getList();
</script>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>
src/views/basicData/product/index.vue
@@ -83,11 +83,12 @@
        </el-button>
      </div>
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :isSelection="true"
        :handleSelectionChange="handleSelectionChange"
        @selection-change="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="total"
src/views/basicData/supplierManage/index.vue
@@ -28,11 +28,12 @@
    </div>
    <div class="table_list">
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :isSelection="true"
        :handleSelectionChange="handleSelectionChange"
        @selection-change="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="total"
src/views/equipmentManagement/ledger/index.vue
@@ -25,6 +25,7 @@
        </div>
      </div>
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableData="dataList"
        :page="{
src/views/personnelManagement/onboarding/index.vue
@@ -4,177 +4,184 @@
      <div>
        <span class="search_title">姓名:</span>
        <el-input
            v-model="searchForm.customerName"
            style="width: 240px"
            placeholder="请输入名称搜索"
            @change="handleQuery"
            clearable
            :prefix-icon="Search"
          v-model="searchForm.customerName"
          style="width: 240px"
          placeholder="请输入名称搜索"
          @change="handleQuery"
          clearable
          :prefix-icon="Search"
        />
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
          >搜索</el-button
        >
      </div>
      <div>
        <el-button type="primary" @click="openForm">新增入职</el-button>
      </div>
    </div>
    <div class="table_list">
      <PIMTable :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true"
                :handleSelectionChange="handleSelectionChange" :tableLoading="tableLoading" @pagination="pagination"
                :total="total"></PIMTable>
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :isSelection="true"
        @selection-change="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="total"
      ></PIMTable>
    </div>
  </div>
</template>
<script setup>
import {Search} from "@element-plus/icons-vue";
import {ref} from "vue";
import { Search } from "@element-plus/icons-vue";
import { ref } from "vue";
const data = reactive({
  searchForm: {
    customerName: '',
    customerName: "",
  },
  form: {
    salesLedgerId: '',
    customerName: '',
    salesman: '',
    projectName: '',
    productData: []
    salesLedgerId: "",
    customerName: "",
    salesman: "",
    projectName: "",
    productData: [],
  },
  rules: {
    salesLedgerId: [{ required: true, message: "请选择", trigger: "change" }]
  }
})
const { searchForm, form, rules } = toRefs(data)
    salesLedgerId: [{ required: true, message: "请选择", trigger: "change" }],
  },
});
const { searchForm, form, rules } = toRefs(data);
const tableColumn = ref([
  {
    label: '状态',
    prop: 'paymentDate',
    dataType: 'tag',
    label: "状态",
    prop: "paymentDate",
    dataType: "tag",
    formatData: (params) => {
      if (params == 0) {
        return '在职';
        return "在职";
      } else if (params == 1) {
        return '离职';
        return "离职";
      } else {
        return null
        return null;
      }
    },
    formatType: (params) => {
      if (params == 0) {
        return 'primary';
        return "primary";
      } else if (params == 1) {
        return 'danger';
        return "danger";
      } else {
        return null
        return null;
      }
    }
    },
  },
  {
    label: '员工编号',
    prop: 'supplierName',
    label: "员工编号",
    prop: "supplierName",
  },
  {
    label: '姓名',
    prop: 'currentPaymentAmount',
    label: "姓名",
    prop: "currentPaymentAmount",
  },
  {
    label: '性别',
    prop: 'paymentMethod'
    label: "性别",
    prop: "paymentMethod",
  },
  {
    label: '籍贯',
    prop: 'registrant'
    label: "籍贯",
    prop: "registrant",
  },
  {
    label: '岗位',
    prop: 'registrationtDate'
    label: "岗位",
    prop: "registrationtDate",
  },
  {
    label: '家庭住址',
    prop: 'registrationtDate'
    label: "家庭住址",
    prop: "registrationtDate",
  },
  {
    label: '第一学历',
    prop: 'registrationtDate'
    label: "第一学历",
    prop: "registrationtDate",
  },
  {
    label: '专业',
    prop: 'registrationtDate'
    label: "专业",
    prop: "registrationtDate",
  },
  {
    label: '身份证号',
    prop: 'registrationtDate'
    label: "身份证号",
    prop: "registrationtDate",
  },
  {
    label: '年龄',
    prop: 'registrationtDate'
    label: "年龄",
    prop: "registrationtDate",
  },
  {
    label: '联系电话',
    prop: 'registrationtDate'
    label: "联系电话",
    prop: "registrationtDate",
  },
  {
    label: '紧急联系人',
    prop: 'registrationtDate'
    label: "紧急联系人",
    prop: "registrationtDate",
  },
  {
    label: '联系电话',
    prop: 'registrationtDate'
    label: "联系电话",
    prop: "registrationtDate",
  },
  {
    label: '合同年限',
    prop: 'registrationtDate'
    label: "合同年限",
    prop: "registrationtDate",
  },
  {
    label: '合同开始日期',
    prop: 'registrationtDate'
    label: "合同开始日期",
    prop: "registrationtDate",
  },
  {
    label: '合同结束日期',
    prop: 'registrationtDate'
    label: "合同结束日期",
    prop: "registrationtDate",
  },
])
const tableData = ref([])
const selectedRows = ref([])
const tableLoading = ref(false)
]);
const tableData = ref([]);
const selectedRows = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
})
const total = ref(0)
});
const total = ref(0);
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1
  getList()
}
  page.current = 1;
  getList();
};
const pagination = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList()
}
  getList();
};
const getList = () => {
  tableLoading.value = true
  ledgerListPage({...searchForm.value, ...page}).then(res => {
    tableLoading.value = false
  tableLoading.value = true;
  ledgerListPage({ ...searchForm.value, ...page }).then((res) => {
    tableLoading.value = false;
    tableData.value = res.records;
    total.value = res.total
  })
}
    total.value = res.total;
  });
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  console.log('selection', selection)
  selectedRows.value = selection.filter(item => item.salesContractNo !== undefined);
}
  console.log("selection", selection);
  selectedRows.value = selection.filter(
    (item) => item.salesContractNo !== undefined
  );
};
// æ‰“开弹框
const openForm = () => {
}
const openForm = () => {};
</script>
<style scoped>
</style>
<style scoped></style>
src/views/procurementManagement/invoiceEntry/components/ExpandTable.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,111 @@
<template>
  <PIMTable
    rowKey="id"
    :column="columns"
    :tableData="dataList"
    :tableLoading="loading"
  >
  </PIMTable>
</template>
<script setup>
import { usePaginationApi } from "@/hooks/usePaginationApi";
import { productList } from "@/api/procurementManagement/procurementLedger.js";
defineOptions({
  name: "来票登记折叠表",
});
const {
  loading,
  filters,
  columns,
  dataList,
  pagination,
  getTableData,
  resetFilters,
} = usePaginationApi(
  productList,
  {
    salesLedgerId: undefined,
    type: 2,
  },
  [
    {
      label: "产品大类",
      prop: "productCategory",
    },
    {
      label: "规格型号",
      prop: "specificationModel",
    },
    {
      label: "单位",
      prop: "unit",
    },
    {
      label: "数量",
      prop: "quantity",
    },
    {
      label: "税率(%)",
      prop: "taxRate",
    },
    {
      label: "含税单价(元)",
      prop: "taxInclusiveUnitPrice",
      formatData: (val) => {
        return parseFloat(val).toFixed(2) ?? 0;
      },
    },
    {
      label: "含税总价(元)",
      prop: "taxInclusiveTotalPrice",
      formatData: (val) => {
        return parseFloat(val).toFixed(2) ?? 0;
      },
    },
    {
      label: "不含税总价(元)",
      prop: "taxExclusiveTotalPrice",
      formatData: (val) => {
        return parseFloat(val).toFixed(2) ?? 0;
      },
    },
    {
      label: "本次来票金额(元)",
      prop: "ticketsAmount",
      formatData: (val) => {
        return parseFloat(val).toFixed(2) ?? 0;
      },
    },
    {
      label: "未来票数",
      prop: "futureTickets",
    },
    {
      label: "未来票金额(元)",
      prop: "futureTicketsAmount",
      formatData: (val) => {
        return parseFloat(val).toFixed(2) ?? 0;
      },
    },
  ],
  {},
  {},
  (data) => {
    dataList.value = data;
  }
);
const getList = (id) => {
  filters.salesLedgerId = id;
  getTableData();
};
defineExpose({
  getList,
});
</script>
<style lang="scss" scoped></style>
src/views/procurementManagement/invoiceEntry/components/Modal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,407 @@
<template>
  <el-dialog :title="modalOptions.title" v-model="visible" width="70%">
    <el-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="120px"
      label-position="top"
    >
      <el-row :gutter="30">
        <el-col :span="12">
          <el-form-item label="采购合同号:" prop="purchaseLedgerNo">
            <el-input v-model="form.purchaseLedgerNo" disabled />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="销售合同号:" prop="salesContractNo">
            <el-input
              v-model="form.salesContractNo"
              placeholder="自动填充"
              clearable
              disabled
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="供应商名称:" prop="supplierName">
            <el-input
              v-model="form.supplierName"
              placeholder="自动填充"
              clearable
              disabled
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="项目名称:" prop="projectName">
            <el-input
              v-model="form.projectName"
              placeholder="自动填充"
              clearable
              disabled
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="发票号:" prop="invoiceNumber">
            <el-input
              v-model="form.invoiceNumber"
              placeholder="请输入"
              clearable
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="发票金额(元):" prop="invoiceAmount">
            <el-input
              type="number"
              :step="0.01"
              :min="0"
              v-model="form.invoiceAmount"
              placeholder="自动填充"
              clearable
              :disabled="true"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="录入人:" prop="issUer">
            <el-input
              v-model="form.issUer"
              placeholder="请输入"
              clearable
              disabled
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="开票日期:" prop="entryDate">
            <el-date-picker
              style="width: 100%"
              v-model="form.entryDate"
              type="date"
              clearable
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="上传附件">
            <FileUpload
              :showTip="false"
              accept="*"
              :autoUpload="true"
              :action="action"
              :headers="{
                Authorization: 'Bearer ' + getToken(),
              }"
              :limit="10"
              @success="uploadSuccess"
              @remove="removeFile"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item label="产品信息:" prop="entryDate"> </el-form-item>
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableData="form.productData"
        height="auto"
      >
        <template #ticketsNumRef="{ row }">
          <el-input-number
            v-model="row.ticketsNum"
            placeholder="请选择"
            :min="0"
            :step="0.1"
            clearable
            style="width: 100%"
            @change="invoiceNumBlur(row)"
          />
        </template>
        <template #ticketsAmountRef="{ row }">
          <el-input-number
            v-model="row.ticketsAmount"
            placeholder="请选择"
            :min="0"
            :step="0.1"
            clearable
            style="width: 100%"
            @change="invoiceAmountBlur(row)"
          />
        </template>
      </PIMTable>
    </el-form>
    <template #footer>
      <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
      <el-button type="primary" :loading="modalLoading" @click="submitForm">
        {{ modalOptions.confirmText }}
      </el-button>
    </template>
  </el-dialog>
</template>
<script setup>
import { ref, getCurrentInstance } from "vue";
import { useModal } from "@/hooks/useModal";
import useFormData from "@/hooks/useFormData";
import FileUpload from "@/components/Upload/FileUpload.vue";
import {
  getPurchaseNoById,
  getInfo,
  addOrUpdateRegistration,
} from "@/api/procurementManagement/invoiceEntry.js";
import { getPurchaseById } from "@/api/procurementManagement/procurementLedger.js";
import { getToken } from "@/utils/auth";
import useUserStore from "@/store/modules/user";
defineOptions({
  name: "来票登记模态框",
});
const userStore = useUserStore();
const action = import.meta.env.VITE_APP_BASE_API + "/file/upload";
const formRef = ref();
const { proxy } = getCurrentInstance();
const { form } = useFormData({
  purchaseLedgerNo: undefined, // é‡‡è´­åˆåŒå·
  salesContractNo: undefined, // é”€å”®åˆåŒå·
  supplierName: undefined, // ä¾›åº”商名称
  projectName: undefined, // é¡¹ç›®åç§°
  invoiceNumber: undefined, // å‘票号
  invoiceAmount: undefined, // å‘票金额(元)
  issUerId: userStore.id, // å½•入人
  issUer: userStore.nickName, // å½•入人
  entryDate: undefined, // å¼€ç¥¨æ—¥æœŸ
  salesContractNoId: undefined, // å¼€ç¥¨æ—¥æœŸ
  productData: [], // è¡¨æ ¼
  tempFileIds: [], // æ–‡ä»¶
});
const rules = ref({
  invoiceNumber: [
    { required: true, message: "请输入发票号", trigger: "blur" },
    { type: "string" },
  ],
  invoiceAmount: [
    { required: true, message: "请输入发票金额", trigger: "blur" },
  ],
});
const {
  id,
  visible,
  loading: modalLoading,
  openModal,
  modalOptions,
  handleConfirm,
  closeModal,
} = useModal({
  title: "来票登记",
});
const columns = [
  {
    label: "产品大类",
    prop: "productCategory",
  },
  {
    label: "规格型号",
    prop: "specificationModel",
  },
  {
    label: "单位",
    prop: "unit",
    width: 80,
  },
  {
    label: "数量",
    prop: "quantity",
    width: 80,
  },
  {
    label: "税率(%)",
    prop: "taxRate",
    width: 80,
  },
  {
    label: "录入日期",
    prop: "registerDate",
    width: 120,
  },
  {
    label: "含税单价(元)",
    prop: "taxInclusiveUnitPrice",
    width: 150,
    formatData: (val) => {
      return parseFloat(val).toFixed(2) ?? 0;
    },
  },
  {
    label: "含税总价(元)",
    prop: "taxInclusiveTotalPrice",
    width: 150,
    formatData: (val) => {
      return parseFloat(val).toFixed(2) ?? 0;
    },
  },
  {
    label: "不含税总价(元)",
    prop: "taxExclusiveTotalPrice",
    width: 150,
    formatData: (val) => {
      return parseFloat(val).toFixed(2) ?? 0;
    },
  },
  {
    label: "本次来票数",
    prop: "ticketsNum",
    dataType: "slot",
    slot: "ticketsNumRef",
    width: 180,
    align: "center",
  },
  {
    label: "本次来票金额(元)",
    prop: "ticketsAmount",
    dataType: "slot",
    slot: "ticketsAmountRef",
    width: 180,
    align: "center",
  },
  {
    label: "未来票数",
    prop: "futureTickets",
  },
  {
    label: "未来票金额(元)",
    prop: "futureTicketsAmount",
  },
];
const getTableData = async (type, id) => {
  if (type == "add") {
    const { data } = await getPurchaseNoById({ id });
    form.purchaseLedgerNo = data.purchaseContractNumber;
    form.invoiceAmount = data.invoiceAmount;
    form.invoiceNumber = data.invoiceNumber;
    form.entryDate = data.entryDate;
    form.salesContractNoId = data.salesContractNoId;
    const { data: infoData } = await getInfo({ id });
    form.salesContractNo = infoData.salesContractNo;
    form.projectName = infoData.projectName;
    form.supplierName = infoData.supplierName;
    form.productData = infoData.productData;
  } else if (type == "edit") {
    const data = await getPurchaseById({ id, type: 2 });
    form.purchaseLedgerNo = data.purchaseContractNumber;
    form.invoiceAmount = data.invoiceAmount;
    form.invoiceNumber = data.invoiceNumber;
    form.salesContractNo = data.salesContractNo;
    form.projectName = data.projectName;
    form.supplierName = data.supplierName;
    form.entryDate = data.entryDate;
    form.productData = data.productData;
  }
};
//本次来票数失焦操作
const invoiceNumBlur = (row) => {
  if (!row.ticketsNum || row.ticketsNum === "") {
    row.ticketsNum = 0;
  }
  if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) {
    proxy.$modal.msgWarning("本次开票数不得大于未开票数");
    row.ticketsNum = 0;
    return;
  }
  // è®¡ç®—本次来票金额
  row.ticketsAmount = row.ticketsNum * row.taxInclusiveUnitPrice;
  // è®¡ç®—未来票数
  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
  // è®¡ç®—未来票金额
  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
  calculateinvoiceAmount();
};
// æœ¬æ¬¡æ¥ç¥¨é‡‘额失焦操作
const invoiceAmountBlur = (row) => {
  if (!row.ticketsAmount) {
    row.ticketsAmount = 0;
  }
  // è®¡ç®—是否超过来票总金额
  if (row.ticketsAmount > row.tempFutureTicketsAmount) {
    proxy.$modal.msgWarning("本次来票金额不得大于未来票金额");
    row.ticketsAmount = 0;
  }
  // è®¡ç®—本次来票数
  row.ticketsNum = Number(
    (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2)
  );
  // è®¡ç®—未来票数
  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
  // è®¡ç®—未来票金额
  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
  calculateinvoiceAmount();
};
const calculateinvoiceAmount = () => {
  let invoiceAmountTotal = 0;
  form.productData.forEach((item) => {
    if (item.ticketsAmount) {
      invoiceAmountTotal += item.ticketsAmount;
    }
  });
  form.invoiceAmount = invoiceAmountTotal.toFixed(2);
};
const open = (type, eid) => {
  openModal();
  getTableData(type, eid);
  id.value = eid;
};
const uploadSuccess = (response) => {
  form.tempFileIds.push(response.data.tempId);
  console.log(form);
};
const removeFile = (file) => {
  const { tempId } = file.response.data;
  form.tempFileIds = form.tempFileIds.filter((item) => item !== tempId);
};
const submitForm = () => {
  formRef.value.validate(async (valid, fields) => {
    if (valid) {
      modalLoading.value = true;
      const { code } = await addOrUpdateRegistration({
        purchaseLedgerId: id.value,
        purchaseContractNumber: form.purchaseLedgerNo,
        invoiceNumber: form.invoiceNumber,
        invoiceAmount: form.invoiceAmount,
        salesContractNo: form.salesContractNo,
        projectName: form.projectName,
        productData: form.productData,
        issUerId: form.issUerId, // å½•入人
        issUer: form.issUer, // å½•入人
        salesContractNoId: form.salesContractNoId,
        supplierName: form.supplierName,
        tempFileIds: form.tempFileIds,
      });
      modalLoading.value = false;
      if (code == 200) {
        closeModal();
      }
    }
  });
};
defineExpose({
  open,
});
</script>
<style lang="scss" scoped></style>
src/views/procurementManagement/invoiceEntry/index.vue
@@ -1,699 +1,185 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title">采购合同号:</span>
        <el-input
          v-model="searchForm.purchaseContractNumber"
          style="width: 240px"
          placeholder="请输入"
          @change="handleQuery"
          clearable
          prefix-icon="Search"
        />
        <el-button
          type="primary"
          @click="handleQuery"
          style="margin-left: 10px"
        >
          æœç´¢
        </el-button>
      </div>
      <div>
        <el-button type="primary" @click="handleAdd">新增登记</el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
      <el-form :model="filters" :inline="true">
        <el-form-item label="采购合同号:">
          <el-input
            v-model="filters.purchaseContractNumber"
            placeholder="请输入"
            clearable
            prefix-icon="Search"
            @change="getTableData"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="getTableData"> æœç´¢ </el-button>
          <el-button @click="resetFilters"> é‡ç½® </el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="table_list">
      <el-table
        :data="tableData"
        border
        v-loading="tableLoading"
        @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys"
        :row-key="(row) => row.id"
        show-summary
        :summary-method="summarizeMainTable"
        @expand-change="expandChange"
        height="calc(100vh - 18.5em)"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column type="expand">
          <template #default="props">
            <el-table
              :data="props.row.children"
              border
              show-summary
              :summary-method="summarizeChildrenTable"
            >
              <el-table-column
                align="center"
                label="序号"
                type="index"
                width="60"
              />
              <el-table-column label="产品大类" prop="productCategory" />
              <el-table-column label="规格型号" prop="specificationModel" />
              <el-table-column label="单位" prop="unit" />
              <el-table-column label="数量" prop="quantity" />
              <el-table-column label="税率(%)" prop="taxRate" />
              <el-table-column
                label="含税单价(元)"
                prop="taxInclusiveUnitPrice"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="含税总价(元)"
                prop="taxInclusiveTotalPrice"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="不含税总价(元)"
                prop="taxExclusiveTotalPrice"
                :formatter="formattedNumber"
              />
              <el-table-column label="本次来票数" prop="ticketsNum" />
              <el-table-column
                label="本次来票金额(元)"
                prop="ticketsAmount"
                :formatter="formattedNumber"
              />
              <el-table-column label="未来票数" prop="futureTickets" />
              <el-table-column
                label="未来票金额(元)"
                prop="futureTicketsAmount"
                :formatter="formattedNumber"
              />
            </el-table>
          </template>
        </el-table-column>
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column
          label="采购合同号"
          prop="purchaseContractNumber"
          show-overflow-tooltip
        />
        <el-table-column
          label="销售合同号"
          prop="salesContractNo"
          show-overflow-tooltip
        />
        <el-table-column
          label="供应商名称"
          prop="supplierName"
          show-overflow-tooltip
        />
        <el-table-column
          label="项目名称"
          prop="projectName"
          show-overflow-tooltip
        />
        <el-table-column
          label="合同金额(元)"
          prop="contractAmount"
          show-overflow-tooltip
          :formatter="formattedNumber"
        />
        <el-table-column
          label="已开票金额(元)"
          prop="receiptPaymentAmount"
          show-overflow-tooltip
          :formatter="formattedNumber"
        />
        <el-table-column
          label="待开票金额(元)"
          prop="unReceiptPaymentAmount"
          show-overflow-tooltip
          :formatter="formattedNumber"
        />
        <!-- <el-table-column fixed="right" label="操作" min-width="60" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="openForm('edit', scope.row);">编辑</el-button>
          </template>
        </el-table-column> -->
      </el-table>
      <pagination
        v-show="total > 0"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="page.current"
        :limit="page.size"
        @pagination="paginationChange"
      />
    </div>
    <el-dialog
      v-model="dialogFormVisible"
      :title="operationType === 'add' ? '新增来票登记' : '编辑来票登记'"
      width="80%"
      @close="closeDia"
    >
      <el-form
        :model="form"
        label-width="140px"
        label-position="top"
        :rules="rules"
        ref="formRef"
      >
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="采购合同号:" prop="purchaseLedgerNo">
              <el-input v-model="form.purchaseLedgerNo" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="销售合同号:" prop="salesContractNo">
              <el-input
                v-model="form.salesContractNo"
                placeholder="自动填充"
                clearable
                disabled
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="供应商名称:" prop="supplierName">
              <el-input
                v-model="form.supplierName"
                placeholder="自动填充"
                clearable
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="项目名称:" prop="projectName">
              <el-input
                v-model="form.projectName"
                placeholder="自动填充"
                clearable
                disabled
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="发票号:" prop="invoiceNumber">
              <el-input
                v-model="form.invoiceNumber"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="发票金额(元):" prop="invoiceAmount">
              <el-input
                type="number"
                :step="0.01"
                v-model="form.invoiceAmount"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="录入人:" prop="issUer">
              <el-input
                v-model="form.issUer"
                placeholder="请输入"
                clearable
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="开票日期:" prop="issueDate">
              <el-date-picker
                style="width: 100%"
                v-model="form.issueDate"
                type="date"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="录入日期:" prop="createTime">
              <el-date-picker
                style="width: 100%"
                v-model="form.createTime"
                type="date"
                placeholder="请选择"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row> -->
        <el-row>
          <el-form-item label="产品信息:" prop="entryDate"> </el-form-item>
        </el-row>
        <el-table
          :data="productData"
          border
          @selection-change="productSelected"
          show-summary
          style="width: 100%"
          :summary-method="summarizeChildrenTable"
        >
          <el-table-column
            align="center"
            label="序号"
            type="index"
            width="60"
          />
          <el-table-column label="产品大类" prop="productCategory" />
          <el-table-column label="规格型号" prop="specificationModel" />
          <el-table-column label="单位" prop="unit" width="70" />
          <el-table-column label="数量" prop="quantity" width="70" />
          <el-table-column label="税率(%)" prop="taxRate" width="80" />
          <el-table-column label="录入日期" prop="createTime" width="120" />
          <el-table-column
            label="含税单价(元)"
            width="150"
            prop="taxInclusiveUnitPrice"
            :formatter="formattedNumber"
          />
          <el-table-column
            label="含税总价(元)"
            width="150"
            prop="taxInclusiveTotalPrice"
            :formatter="formattedNumber"
          />
          <el-table-column
            label="不含税总价(元)"
            width="150"
            prop="taxExclusiveTotalPrice"
            :formatter="formattedNumber"
          />
          <el-table-column label="本次来票数" prop="ticketsNum" width="170">
            <template #default="scope">
              <el-input-number
                v-model="scope.row.ticketsNum"
                placeholder="请选择"
                :min="0"
                :step="0.1"
                clearable
                style="width: 100%"
                @change="invoiceNumBlur(scope.row)"
              />
            </template>
          </el-table-column>
          <el-table-column
            label="本次来票金额(元)"
            prop="ticketsAmount"
            :min="0"
            :step="0.1"
            :formatter="formattedNumber"
            @change="invoiceAmountBlur"
            width="170"
          >
            <template #default="scope">
              <el-input-number
                v-model="scope.row.ticketsAmount"
                placeholder="请选择"
                :min="0"
                :step="0.1"
                clearable
                style="width: 100%"
                @change="invoiceAmountBlur(scope.row)"
              />
            </template>
          </el-table-column>
          <el-table-column
            label="未来票数"
            prop="futureTickets"
            :="
              (row) =>
                row.futureTickets == null || row.futureTickets === ''
                  ? row.quantity
                  : row.futureTickets
            "
          >
          </el-table-column>
          <el-table-column
            label="未来票金额(元)"
            prop="futureTicketsAmount"
            :formatter="
              (row) =>
                row.futureTicketsAmount !== undefined &&
                row.futureTicketsAmount !== null &&
                row.futureTicketsAmount !== ''
                  ? row.futureTicketsAmount
                  : row.taxExclusiveTotalPrice
            "
          >
          </el-table-column>
        </el-table>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
      <div class="actions">
        <div></div>
        <div>
          <el-button type="primary" @click="handleAdd('add')">
            æ–°å¢žç™»è®°
          </el-button>
          <el-button @click="handleOut">导出</el-button>
          <el-button type="danger" plain @click="handleDelete">删除</el-button>
        </div>
      </template>
    </el-dialog>
      </div>
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableData="dataList"
        :tableLoading="loading"
        :isSelection="true"
        :page="{
          current: pagination.currentPage,
          size: pagination.pageSize,
          total: pagination.total,
        }"
        :expand-row-keys="expandRowKeys"
        @expand-change="expandChange"
        @selection-change="handleSelectionChange"
      >
        <template #expand="{ row }">
          <ExpandTable ref="expandTableRef" />
        </template>
        <template #operation="{ row }">
          <el-button
            text
            type="primary"
            size="small"
            @click="handleEdit('edit', row.id)"
          >
            ç¼–辑
          </el-button>
        </template>
      </PIMTable>
    </div>
    <Modal ref="modalRef"></Modal>
  </div>
</template>
<script setup>
import pagination from "@/components/PIMTable/Pagination.vue";
import { ref } from "vue";
import { ElMessageBox } from "element-plus";
import { userListNoPage } from "@/api/system/user.js";
import { productList } from "@/api/procurementManagement/procurementLedger.js";
import useUserStore from "@/store/modules/user";
const userStore = useUserStore();
import { usePaginationApi } from "@/hooks/usePaginationApi";
import { gePurchaseListPage } from "@/api/procurementManagement/invoiceEntry.js";
import { nextTick, onMounted, getCurrentInstance } from "vue";
import ExpandTable from "./components/ExpandTable.vue";
import Modal from "./components/Modal.vue";
defineOptions({
  name: "来票登记",
});
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const productData = ref([]);
const expandRowKeys = ref([]);
const expandTableRef = ref();
const modalRef = ref();
const selectedRows = ref([]);
const productSelectedRows = ref([]);
const userList = ref([]);
const purchaseLedgerList = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
});
const total = ref(0);
const fileList = ref([]);
import {
  addOrUpdateRegistration,
  delRegistration,
const {
  loading,
  filters,
  columns,
  dataList,
  pagination,
  getTableData,
  resetFilters,
} = usePaginationApi(
  gePurchaseListPage,
  getInfo,
  getProduct,
  getPurchaseNoById,
  getRegistrationById,
} from "@/api/procurementManagement/invoiceEntry.js";
  {
    purchaseContractNumber: undefined,
  },
  [
    {
      type: "expand",
      dataType: "slot",
      slot: "expand",
    },
    {
      label: "销售合同号",
      prop: "salesContractNo",
    },
    {
      label: "供应商名称",
      prop: "supplierName",
    },
    {
      label: "项目名称",
      prop: "projectName",
    },
    {
      label: "合同金额(元)",
      prop: "contractAmount",
      formatData: (val) => {
        return parseFloat(val).toFixed(2) ?? 0;
      },
    },
    {
      label: "已开票金额(元)",
      prop: "receiptPaymentAmount",
      formatData: (val) => {
        return parseFloat(val).toFixed(2) ?? 0;
      },
    },
    {
      label: "待开票金额(元)",
      prop: "unReceiptPaymentAmount",
      formatData: (val) => {
        return parseFloat(val).toFixed(2) ?? 0;
      },
    },
    // {
    //   fixed: "right",
    //   label: "操作",
    //   dataType: "slot",
    //   slot: "operation",
    //   align: "center",
    //   width: "200px",
    // },
  ]
);
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref("");
const dialogFormVisible = ref(false);
const data = reactive({
  searchForm: {
    purchaseContractNumber: "",
  },
  form: {
    issueDate: "", // å¼€ç¥¨æ—¥æœŸ
    purchaseLedgerId: "",
    purchaseLedgerNo: "",
    issUerId: "", // å¼€ç¥¨äººid
    issUer: "", // å¼€ç¥¨äººå§“名
    invoiceNumber: "", // å‘票号
    invoiceAmount: "", // å‘票金额
    createTime: "", // å½•入日期
  },
  rules: {
    invoiceNumber: [
      { required: true, message: "请输入发票号", trigger: "blur" },
      { type: "string" },
    ],
    invoiceAmount: [
      { required: true, message: "请输入发票金额", trigger: "blur" },
    ],
  },
});
const { searchForm, form, rules } = toRefs(data);
// äº§å“è¡¨å•弹框数据
const productFormVisible = ref(false);
const productOperationType = ref("");
const currentId = ref("");
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1;
  getList();
};
const paginationChange = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
const getList = () => {
  tableLoading.value = true;
  gePurchaseListPage({ ...searchForm.value, ...page })
    .then((res) => {
      tableLoading.value = false;
      tableData.value = res.records;
      tableData.value.map((item) => {
        item.children = [];
      });
      total.value = res.total;
      expandedRowKeys.value = [];
    })
    .catch(() => {
      tableLoading.value = false;
    });
};
const formattedNumber = (row, column, cellValue) => {
  return parseFloat(cellValue).toFixed(2);
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection.filter(
    (item) => item.purchaseContractNumber !== undefined
  );
};
const productSelected = (selectedRows) => {
  productSelectedRows.value = selectedRows;
};
const expandedRowKeys = ref([]);
// å±•开行
const expandChange = (row, expandedRows) => {
  if (expandedRows.length > 0) {
    expandedRowKeys.value = [];
    try {
      productList({ salesLedgerId: row.id, type: 2 }).then((res) => {
        const index = tableData.value.findIndex((item) => item.id === row.id);
        if (index > -1) {
          tableData.value[index].children = res;
        }
        expandedRowKeys.value.push(row.id);
      });
    } catch (error) {
      console.log(error);
    }
  } else {
    expandedRowKeys.value = [];
  }
};
// ä¸»è¡¨åˆè®¡æ–¹æ³•
const summarizeMainTable = (param) => {
  return proxy.summarizeTable(
    param,
    ["contractAmount", "receiptPaymentAmount", "unReceiptPaymentAmount"],
    {
      ticketsNum: { noDecimal: true }, // ä¸ä¿ç•™å°æ•°
      futureTickets: { noDecimal: true }, // ä¸ä¿ç•™å°æ•°
    }
  );
};
// å­è¡¨åˆè®¡æ–¹æ³•
const summarizeChildrenTable = (param) => {
  return proxy.summarizeTable(
    param,
    [
      "taxInclusiveUnitPrice",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
      "ticketsNum",
      "ticketsAmount",
      "futureTickets",
      "futureTicketsAmount",
    ],
    {
      ticketsNum: { noDecimal: true }, // ä¸ä¿ç•™å°æ•°
      futureTickets: { noDecimal: true }, // ä¸ä¿ç•™å°æ•°
    }
  );
};
const handleAdd = () => {
const handleAdd = (type) => {
  if (selectedRows.value.length !== 1) {
    proxy.$modal.msgWarning("请先选中一条数据");
    return;
  }
  openForm("add", selectedRows.value[0]);
  modalRef.value.open(type, selectedRows.value[0].id);
};
// æ‰“开弹框
const openForm = (type, row) => {
  invoiceNumBlur(row);
  operationType.value = type;
  form.value = {};
  productData.value = [];
  fileList.value = [];
  form.value.issUerId = userStore.id;
  form.value.issUer = userStore.name;
  form.value.issueDate = getNowFormatDate();
  userListNoPage().then((res) => {
    userList.value = res.data;
  });
  // æ–°å¢žæ—¶ä¼ å…¥å½“前行id并查询采购合同号
  if (type === "add" && row && row.id) {
    form.value.purchaseLedgerId = row.id;
    getPurchaseNoById({ id: row.id }).then((res) => {
      let result = res.data;
      (purchaseLedgerList.value = result),
        (form.value.purchaseLedgerNo = result.purchaseContractNumber);
      form.value.invoiceAmount = result.invoiceAmount;
      form.value.invoiceNumber = result.invoiceNumber;
      setInfo(result.id);
    });
  } else {
    getProduct().then((res) => {
      purchaseLedgerList.value = res;
    });
  }
  if (type === "edit") {
    currentId.value = row.id;
    getRegistrationById({ id: row.id }).then((res) => {
      form.value = { ...res };
      productData.value = form.value.productData;
      if (form.value.salesLedgerFiles) {
        fileList.value = form.value.salesLedgerFiles;
      } else {
        fileList.value = [];
      }
    });
  }
  dialogFormVisible.value = true;
};
// é€‰æ‹©é‡‡è´­åˆåŒå·èµ‹å€¼
const setInfo = (value) => {
  getInfo({ id: value }).then((res) => {
    let result = res.data;
    form.value.salesContractNo = result.salesContractNo;
    form.value.projectName = result.projectName;
    productData.value = result.productData;
    form.value.supplierName = result.supplierName;
  });
};
// æäº¤è¡¨å•
const submitForm = () => {
  proxy.$refs["formRef"].validate((valid) => {
    if (valid) {
      form.value.productData = proxy.HaveJson(productData.value);
      addOrUpdateRegistration(form.value).then((res) => {
        proxy.$modal.msgSuccess("提交成功");
        closeDia();
        getList();
      });
    }
  });
};
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      proxy.download("/purchase/registration/export", {}, "来票登记.xlsx");
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
// åˆ é™¤
const handleDelete = () => {
  let ids = [];
  if (selectedRows.value.length > 0) {
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning("请选择数据");
    return;
  }
  ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      delRegistration(ids).then((res) => {
        proxy.$modal.msgSuccess("删除成功");
        getList();
      });
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
//本次来票数失焦操作
const invoiceNumBlur = (row) => {
  if (!row.ticketsNum || row.ticketsNum === "") {
    row.ticketsNum = 0;
  }
  if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) {
    proxy.$modal.msgWarning("本次开票数不得大于未开票数");
    row.ticketsNum = 0;
    return;
  }
  // è®¡ç®—本次来票金额
  row.ticketsAmount = row.ticketsNum * row.taxInclusiveUnitPrice;
  // è®¡ç®—未来票数
  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
  // è®¡ç®—未来票金额
  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
  calculateinvoiceAmount();
};
// æœ¬æ¬¡æ¥ç¥¨é‡‘额失焦操作
const invoiceAmountBlur = (row) => {
  if (!row.ticketsAmount) {
    row.ticketsAmount = 0;
  }
  // è®¡ç®—是否超过来票总金额
  if (row.ticketsAmount > row.tempFutureTicketsAmount) {
    proxy.$modal.msgWarning("本次来票金额不得大于未来票金额");
    row.ticketsAmount = 0;
  }
  // è®¡ç®—本次来票数
  row.ticketsNum = (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2);
  // è®¡ç®—未来票数
  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
  // è®¡ç®—未来票金额
  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
  calculateinvoiceAmount();
const handleEdit = (type, id) => {
  modalRef.value.open(type, id);
};
// èŽ·å–å½“å‰æ—¥æœŸå‡½æ•°
function getNowFormatDate() {
  let date = new Date(),
    year = date.getFullYear(), //获取完整的年份(4位)
    month = date.getMonth() + 1, //获取当前月份(0-11,0代表1月)
    strDate = date.getDate(); // èŽ·å–å½“å‰æ—¥(1-31)
  if (month < 10) month = `0${month}`; // å¦‚果月份是个位数,在前面补0
  if (strDate < 10) strDate = `0${strDate}`; // å¦‚果日是个位数,在前面补0
  return `${year}-${month}-${strDate}`;
}
const handleOut = () => {};
const handleDelete = () => {};
function calculateinvoiceAmount() {
  console.log("productData", productData.value);
  var invoiceAmountTotal = 0;
  productData.value.forEach((item) => {
    if (item.ticketsAmount) {
      invoiceAmountTotal += item.ticketsAmount;
    }
  });
  form.value.invoiceAmount = invoiceAmountTotal.toFixed(2);
}
const expandChange = async (row, expandedRows) => {
  await nextTick();
  expandTableRef.value.getList(row.id);
};
getList();
onMounted(() => {
  getTableData();
});
</script>
<style scoped lang="scss"></style>
<style lang="scss" scoped>
.table_list {
  margin-top: unset;
}
.actions {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
}
</style>
src/views/procurementManagement/invoiceEntry/indexOld.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,725 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <div>
        <span class="search_title">采购合同号:</span>
        <el-input
          v-model="searchForm.purchaseContractNumber"
          style="width: 240px"
          placeholder="请输入"
          @change="handleQuery"
          clearable
          prefix-icon="Search"
        />
        <el-button
          type="primary"
          @click="handleQuery"
          style="margin-left: 10px"
        >
          æœç´¢
        </el-button>
      </div>
      <div>
        <el-button type="primary" @click="handleAdd">新增登记</el-button>
        <el-button @click="handleOut">导出</el-button>
        <el-button type="danger" plain @click="handleDelete">删除</el-button>
      </div>
    </div>
    <div class="table_list">
      <el-table
        :data="tableData"
        border
        v-loading="tableLoading"
        @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys"
        :row-key="(row) => row.id"
        show-summary
        :summary-method="summarizeMainTable"
        @expand-change="expandChange"
        height="calc(100vh - 18.5em)"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column type="expand">
          <template #default="props">
            <el-table
              :data="props.row.children"
              border
              show-summary
              :summary-method="summarizeChildrenTable"
            >
              <el-table-column
                align="center"
                label="序号"
                type="index"
                width="60"
              />
              <el-table-column label="产品大类" prop="productCategory" />
              <el-table-column label="规格型号" prop="specificationModel" />
              <el-table-column label="单位" prop="unit" />
              <el-table-column label="数量" prop="quantity" />
              <el-table-column label="税率(%)" prop="taxRate" />
              <el-table-column
                label="含税单价(元)"
                prop="taxInclusiveUnitPrice"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="含税总价(元)"
                prop="taxInclusiveTotalPrice"
                :formatter="formattedNumber"
              />
              <el-table-column
                label="不含税总价(元)"
                prop="taxExclusiveTotalPrice"
                :formatter="formattedNumber"
              />
              <el-table-column label="本次来票数" prop="ticketsNum" />
              <el-table-column
                label="本次来票金额(元)"
                prop="ticketsAmount"
                :formatter="formattedNumber"
              />
              <el-table-column label="未来票数" prop="futureTickets" />
              <el-table-column
                label="未来票金额(元)"
                prop="futureTicketsAmount"
                :formatter="formattedNumber"
              />
            </el-table>
          </template>
        </el-table-column>
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column
          label="采购合同号"
          prop="purchaseContractNumber"
          show-overflow-tooltip
        />
        <el-table-column
          label="销售合同号"
          prop="salesContractNo"
          show-overflow-tooltip
        />
        <el-table-column
          label="供应商名称"
          prop="supplierName"
          show-overflow-tooltip
        />
        <el-table-column
          label="项目名称"
          prop="projectName"
          show-overflow-tooltip
        />
        <el-table-column
          label="合同金额(元)"
          prop="contractAmount"
          show-overflow-tooltip
          :formatter="formattedNumber"
        />
        <el-table-column
          label="已开票金额(元)"
          prop="receiptPaymentAmount"
          show-overflow-tooltip
          :formatter="formattedNumber"
        />
        <el-table-column
          label="待开票金额(元)"
          prop="unReceiptPaymentAmount"
          show-overflow-tooltip
          :formatter="formattedNumber"
        />
        <el-table-column
          fixed="right"
          label="操作"
          min-width="60"
          align="center"
        >
          <template #default="scope">
            <el-button
              text
              type="primary"
              size="small"
              @click="openForm('edit', scope.row)"
            >
              ç¼–辑
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="total > 0"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="page.current"
        :limit="page.size"
        @pagination="paginationChange"
      />
    </div>
    <el-dialog
      v-model="dialogFormVisible"
      :title="operationType === 'add' ? '新增来票登记' : '编辑来票登记'"
      width="80%"
      @close="closeDia"
    >
      <el-form
        :model="form"
        label-width="140px"
        label-position="top"
        :rules="rules"
        ref="formRef"
      >
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="采购合同号:" prop="purchaseLedgerNo">
              <el-input v-model="form.purchaseLedgerNo" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="销售合同号:" prop="salesContractNo">
              <el-input
                v-model="form.salesContractNo"
                placeholder="自动填充"
                clearable
                disabled
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="供应商名称:" prop="supplierName">
              <el-input
                v-model="form.supplierName"
                placeholder="自动填充"
                clearable
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="项目名称:" prop="projectName">
              <el-input
                v-model="form.projectName"
                placeholder="自动填充"
                clearable
                disabled
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="发票号:" prop="invoiceNumber">
              <el-input
                v-model="form.invoiceNumber"
                placeholder="请输入"
                clearable
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="发票金额(元):" prop="invoiceAmount">
              <el-input
                type="number"
                :step="0.01"
                v-model="form.invoiceAmount"
                placeholder="自动填充"
                clearable
                :disabled="true"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="录入人:" prop="issUer">
              <el-input
                v-model="form.issUer"
                placeholder="请输入"
                clearable
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="开票日期:" prop="issueDate">
              <el-date-picker
                style="width: 100%"
                v-model="form.issueDate"
                type="date"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="上传附件">
              <FileUpload :showTip="false" accept="*" :autoUpload="true" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="录入日期:" prop="createTime">
              <el-date-picker
                style="width: 100%"
                v-model="form.createTime"
                type="date"
                placeholder="请选择"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row> -->
        <el-row>
          <el-form-item label="产品信息:" prop="entryDate"> </el-form-item>
        </el-row>
        <el-table
          :data="productData"
          border
          @selection-change="productSelected"
          show-summary
          style="width: 100%"
          :summary-method="summarizeChildrenTable"
        >
          <el-table-column
            align="center"
            label="序号"
            type="index"
            width="60"
          />
          <el-table-column label="产品大类" prop="productCategory" />
          <el-table-column label="规格型号" prop="specificationModel" />
          <el-table-column label="单位" prop="unit" width="70" />
          <el-table-column label="数量" prop="quantity" width="70" />
          <el-table-column label="税率(%)" prop="taxRate" width="80" />
          <el-table-column label="录入日期" prop="createTime" width="120" />
          <el-table-column
            label="含税单价(元)"
            width="150"
            prop="taxInclusiveUnitPrice"
            :formatter="formattedNumber"
          />
          <el-table-column
            label="含税总价(元)"
            width="150"
            prop="taxInclusiveTotalPrice"
            :formatter="formattedNumber"
          />
          <el-table-column
            label="不含税总价(元)"
            width="150"
            prop="taxExclusiveTotalPrice"
            :formatter="formattedNumber"
          />
          <el-table-column label="本次来票数" prop="ticketsNum" width="170">
            <template #default="scope">
              <el-input-number
                v-model="scope.row.ticketsNum"
                placeholder="请选择"
                :min="0"
                :step="0.1"
                clearable
                style="width: 100%"
                @change="invoiceNumBlur(scope.row)"
              />
            </template>
          </el-table-column>
          <el-table-column
            label="本次来票金额(元)"
            prop="ticketsAmount"
            :min="0"
            :step="0.1"
            :formatter="formattedNumber"
            width="170"
          >
            <template #default="scope">
              <el-input-number
                v-model="scope.row.ticketsAmount"
                placeholder="请选择"
                :min="0"
                :step="0.1"
                clearable
                style="width: 100%"
                @change="invoiceAmountBlur(scope.row)"
              />
            </template>
          </el-table-column>
          <el-table-column
            label="未来票数"
            prop="futureTickets"
            :formatter="
              (row) =>
                row.futureTickets == null || row.futureTickets === ''
                  ? row.quantity
                  : row.futureTickets
            "
          >
          </el-table-column>
          <el-table-column
            label="未来票金额(元)"
            prop="futureTicketsAmount"
            :formatter="
              (row) =>
                row.futureTicketsAmount !== undefined &&
                row.futureTicketsAmount !== null &&
                row.futureTicketsAmount !== ''
                  ? row.futureTicketsAmount
                  : row.taxExclusiveTotalPrice
            "
          >
          </el-table-column>
        </el-table>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确认</el-button>
          <el-button @click="closeDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import pagination from "@/components/PIMTable/Pagination.vue";
import { onMounted, ref } from "vue";
import { ElMessageBox } from "element-plus";
import { userListNoPage } from "@/api/system/user.js";
import { productList } from "@/api/procurementManagement/procurementLedger.js";
import useUserStore from "@/store/modules/user";
import FileUpload from "@/components/Upload/FileUpload.vue";
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
const tableData = ref([]);
const productData = ref([]);
const selectedRows = ref([]);
const productSelectedRows = ref([]);
const userList = ref([]);
const purchaseLedgerList = ref([]);
const tableLoading = ref(false);
const page = reactive({
  current: 1,
  size: 100,
});
const total = ref(0);
const fileList = ref([]);
import {
  addOrUpdateRegistration,
  delRegistration,
  gePurchaseListPage,
  getInfo,
  getProduct,
  getPurchaseNoById,
  getRegistrationById,
} from "@/api/procurementManagement/invoiceEntry.js";
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref("");
const dialogFormVisible = ref(false);
const data = reactive({
  searchForm: {
    purchaseContractNumber: "",
  },
  form: {
    issueDate: "", // å¼€ç¥¨æ—¥æœŸ
    purchaseLedgerId: "",
    purchaseLedgerNo: "",
    issUerId: "", // å¼€ç¥¨äººid
    issUer: "", // å¼€ç¥¨äººå§“名
    invoiceNumber: "", // å‘票号
    invoiceAmount: "", // å‘票金额
    createTime: "", // å½•入日期
  },
  rules: {
    invoiceNumber: [
      { required: true, message: "请输入发票号", trigger: "blur" },
      { type: "string" },
    ],
    invoiceAmount: [
      { required: true, message: "请输入发票金额", trigger: "blur" },
    ],
  },
});
const { searchForm, form, rules } = toRefs(data);
// äº§å“è¡¨å•弹框数据
const productFormVisible = ref(false);
const productOperationType = ref("");
const currentId = ref("");
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1;
  getList();
};
const paginationChange = (obj) => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
const getList = () => {
  tableLoading.value = true;
  gePurchaseListPage({ ...searchForm.value, ...page })
    .then((res) => {
      tableLoading.value = false;
      tableData.value = res.records;
      tableData.value.map((item) => {
        item.children = [];
      });
      total.value = res.total;
      expandedRowKeys.value = [];
    })
    .catch(() => {
      tableLoading.value = false;
    });
};
const formattedNumber = (row, column, cellValue) => {
  return parseFloat(cellValue).toFixed(2) ?? 0;
};
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = (selection) => {
  selectedRows.value = selection.filter(
    (item) => item.purchaseContractNumber !== undefined
  );
};
const productSelected = (selectedRows) => {
  productSelectedRows.value = selectedRows;
};
const expandedRowKeys = ref([]);
// å±•开行
const expandChange = (row, expandedRows) => {
  if (expandedRows.length > 0) {
    expandedRowKeys.value = [];
    try {
      productList({ salesLedgerId: row.id, type: 2 }).then((res) => {
        const index = tableData.value.findIndex((item) => item.id === row.id);
        if (index > -1) {
          tableData.value[index].children = res;
        }
        expandedRowKeys.value.push(row.id);
      });
    } catch (error) {
      console.log(error);
    }
  } else {
    expandedRowKeys.value = [];
  }
};
// ä¸»è¡¨åˆè®¡æ–¹æ³•
const summarizeMainTable = (param) => {
  return proxy.summarizeTable(
    param,
    ["contractAmount", "receiptPaymentAmount", "unReceiptPaymentAmount"],
    {
      ticketsNum: { noDecimal: true }, // ä¸ä¿ç•™å°æ•°
      futureTickets: { noDecimal: true }, // ä¸ä¿ç•™å°æ•°
    }
  );
};
// å­è¡¨åˆè®¡æ–¹æ³•
const summarizeChildrenTable = (param) => {
  return proxy.summarizeTable(
    param,
    [
      "taxInclusiveUnitPrice",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
      "ticketsNum",
      "ticketsAmount",
      "futureTickets",
      "futureTicketsAmount",
    ],
    {
      ticketsNum: { noDecimal: true }, // ä¸ä¿ç•™å°æ•°
      futureTickets: { noDecimal: true }, // ä¸ä¿ç•™å°æ•°
    }
  );
};
const handleAdd = () => {
  if (selectedRows.value.length !== 1) {
    proxy.$modal.msgWarning("请先选中一条数据");
    return;
  }
  openForm("add", selectedRows.value[0]);
};
// æ‰“开弹框
const openForm = (type, row) => {
  invoiceNumBlur(row);
  operationType.value = type;
  form.value = {};
  productData.value = [];
  fileList.value = [];
  form.value.issUerId = userStore.id;
  form.value.issUer = userStore.name;
  form.value.issueDate = getNowFormatDate();
  userListNoPage().then((res) => {
    userList.value = res.data;
  });
  // æ–°å¢žæ—¶ä¼ å…¥å½“前行id并查询采购合同号
  if (type === "add" && row && row.id) {
    form.value.purchaseLedgerId = row.id;
    getPurchaseNoById({ id: row.id }).then((res) => {
      let result = res.data;
      purchaseLedgerList.value = result;
      form.value.purchaseLedgerNo = result.purchaseContractNumber;
      form.value.invoiceAmount = result.invoiceAmount;
      form.value.invoiceNumber = result.invoiceNumber;
      setInfo(result.id);
    });
  } else {
    getProduct().then((res) => {
      purchaseLedgerList.value = res;
    });
  }
  if (type === "edit") {
    currentId.value = row.id;
    getRegistrationById({ id: row.id }).then((res) => {
      const { code, data } = res;
      if (code == 200) {
        form.value.invoiceAmount = data.invoiceAmount;
        productData.value = data.productData;
        if (data.salesLedgerFiles) {
          fileList.value = data.salesLedgerFiles;
        } else {
          fileList.value = [];
        }
      }
    });
  }
  dialogFormVisible.value = true;
};
// é€‰æ‹©é‡‡è´­åˆåŒå·èµ‹å€¼
const setInfo = (value) => {
  getInfo({ id: value }).then((res) => {
    let result = res.data;
    form.value.salesContractNo = result.salesContractNo;
    form.value.projectName = result.projectName;
    productData.value = result.productData;
    form.value.supplierName = result.supplierName;
  });
};
// æäº¤è¡¨å•
const submitForm = () => {
  proxy.$refs["formRef"].validate((valid) => {
    if (valid) {
      form.value.productData = proxy.HaveJson(productData.value);
      addOrUpdateRegistration(form.value).then((res) => {
        proxy.$modal.msgSuccess("提交成功");
        closeDia();
        getList();
      });
    }
  });
};
// å…³é—­å¼¹æ¡†
const closeDia = () => {
  proxy.resetForm("formRef");
  dialogFormVisible.value = false;
};
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      proxy.download("/purchase/registration/export", {}, "来票登记.xlsx");
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
// åˆ é™¤
const handleDelete = () => {
  let ids = [];
  if (selectedRows.value.length > 0) {
    ids = selectedRows.value.map((item) => item.id);
  } else {
    proxy.$modal.msgWarning("请选择数据");
    return;
  }
  ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      delRegistration(ids).then((res) => {
        proxy.$modal.msgSuccess("删除成功");
        getList();
      });
    })
    .catch(() => {
      proxy.$modal.msg("已取消");
    });
};
//本次来票数失焦操作
const invoiceNumBlur = (row) => {
  if (!row.ticketsNum || row.ticketsNum === "") {
    row.ticketsNum = 0;
  }
  if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) {
    proxy.$modal.msgWarning("本次开票数不得大于未开票数");
    row.ticketsNum = 0;
    return;
  }
  // è®¡ç®—本次来票金额
  row.ticketsAmount = row.ticketsNum * row.taxInclusiveUnitPrice;
  // è®¡ç®—未来票数
  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
  // è®¡ç®—未来票金额
  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
  calculateinvoiceAmount();
};
// æœ¬æ¬¡æ¥ç¥¨é‡‘额失焦操作
const invoiceAmountBlur = (row) => {
  if (!row.ticketsAmount) {
    row.ticketsAmount = 0;
  }
  // è®¡ç®—是否超过来票总金额
  if (row.ticketsAmount > row.tempFutureTicketsAmount) {
    proxy.$modal.msgWarning("本次来票金额不得大于未来票金额");
    row.ticketsAmount = 0;
  }
  // è®¡ç®—本次来票数
  row.ticketsNum = (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2);
  // è®¡ç®—未来票数
  row.futureTickets = row.tempFutureTickets - row.ticketsNum;
  // è®¡ç®—未来票金额
  row.futureTicketsAmount = row.tempFutureTicketsAmount - row.ticketsAmount;
  calculateinvoiceAmount();
};
// èŽ·å–å½“å‰æ—¥æœŸå‡½æ•°
function getNowFormatDate() {
  let date = new Date(),
    year = date.getFullYear(), //获取完整的年份(4位)
    month = date.getMonth() + 1, //获取当前月份(0-11,0代表1月)
    strDate = date.getDate(); // èŽ·å–å½“å‰æ—¥(1-31)
  if (month < 10) month = `0${month}`; // å¦‚果月份是个位数,在前面补0
  if (strDate < 10) strDate = `0${strDate}`; // å¦‚果日是个位数,在前面补0
  return `${year}-${month}-${strDate}`;
}
function calculateinvoiceAmount() {
  console.log("productData", productData.value);
  var invoiceAmountTotal = 0;
  productData.value.forEach((item) => {
    if (item.ticketsAmount) {
      invoiceAmountTotal += item.ticketsAmount;
    }
  });
  form.value.invoiceAmount = invoiceAmountTotal.toFixed(2);
}
onMounted(() => {
  getList();
});
</script>
<style scoped lang="scss"></style>
src/views/procurementManagement/paymentEntry/index.vue
@@ -62,13 +62,14 @@
    </div>
    <div class="table_list">
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :isSelection="true"
        :isShowSummary="isShowSummarySon"
        :summaryMethod="summarizeMainTable1"
        :handleSelectionChange="handleSelectionChange"
        @selection-change="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="total"
src/views/procurementManagement/paymentHistory/index.vue
@@ -36,13 +36,14 @@
    </el-form>
    <div class="table_list">
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :isSelection="true"
        :isShowSummary="isShowSummarySon"
        :summaryMethod="summarizeMainTable1"
        :handleSelectionChange="handleSelectionChange"
        @selection-change="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="total"
src/views/procurementManagement/paymentLedger/index.vue
@@ -79,6 +79,7 @@
      <el-col :span="10">
        <div class="table_list">
          <PIMTable
            rowKey="id"
            :column="tableColumnSon"
            :tableData="originalTableDataSon"
            :isSelection="false"
src/views/procurementManagement/procurementInvoiceLedger/index.vue
@@ -42,23 +42,22 @@
    </el-form>
    <div class="table_list">
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableLoading="loading"
        :tableData="dataList"
        :isSelection="true"
        height="calc(100vh - 18.5em)"
        :isShowSummary="true"
        :summaryMethod="summarizeMainTable"
        :page="{
          current: pagination.currentPage,
          size: pagination.pageSize,
          total: pagination.total,
        }"
        :handleSelectionChange="handleSelectionChange"
        @selection-change="handleSelectionChange"
        @pagination="onCurrentChange"
      >
        <!-- <template #operation>
          <el-button type="primary" text @click="handleEdit" size="small">
            ç¼–辑
          </el-button>
        </template> -->
      </PIMTable>
    </div>
  </div>
@@ -177,6 +176,23 @@
  }
);
// ä¸»è¡¨åˆè®¡æ–¹æ³•
const summarizeMainTable = (param) => {
  return proxy.summarizeTable(
    param,
    [
      "taxInclusiveTotalPrice",
      "ticketsAmount",
      "unTicketsPrice",
      "invoiceAmount",
    ],
    {
      ticketsNum: { noDecimal: true }, // ä¸ä¿ç•™å°æ•°
      futureTickets: { noDecimal: true }, // ä¸ä¿ç•™å°æ•°
    }
  );
};
const handleSelectionChange = (val) => {
  multipleVal.value = val;
};
src/views/procurementManagement/procurementLedger/index.vue
@@ -646,11 +646,11 @@
  purchaseListPage({ ...searchForm.value, ...page })
    .then((res) => {
      tableLoading.value = false;
      tableData.value = res.records;
      tableData.value = res.data.records;
      tableData.value.map((item) => {
        item.children = [];
      });
      total.value = res.total;
      total.value = res.data.total;
      expandedRowKeys.value = [];
    })
    .catch(() => {
src/views/procurementManagement/thePaymentLedger/index.vue
@@ -4,93 +4,98 @@
      <div>
        <span class="search_title">供应商名称/合同号:</span>
        <el-input
            v-model="searchForm.supplierNameOrContractNo"
            style="width: 240px"
            placeholder="输入供应商名称/合同号搜索"
            @change="handleQuery"
            clearable
            :prefix-icon="Search"
          v-model="searchForm.supplierNameOrContractNo"
          style="width: 240px"
          placeholder="输入供应商名称/合同号搜索"
          @change="handleQuery"
          clearable
          :prefix-icon="Search"
        />
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>
        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
          >搜索</el-button
        >
      </div>
    </div>
    <div class="table_list">
      <PIMTable :column="tableColumn" :tableData="tableData" :page="page"
                :tableLoading="tableLoading" @pagination="pagination" :total="total"></PIMTable>
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="total"
      ></PIMTable>
    </div>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import {Search} from "@element-plus/icons-vue";
import {
  registrationList,
} from "@/api/procurementManagement/paymentEntry.js";
import { ref } from "vue";
import { Search } from "@element-plus/icons-vue";
import { registrationList } from "@/api/procurementManagement/paymentEntry.js";
const tableColumn = ref([
  {
    label: '付款日期',
    prop: 'paymentDate',
    label: "付款日期",
    prop: "paymentDate",
  },
  {
    label: '供应商名称',
    prop: 'supplierName',
    label: "供应商名称",
    prop: "supplierName",
  },
  {
    label: '付款金额',
    prop: 'currentPaymentAmount',
    label: "付款金额",
    prop: "currentPaymentAmount",
  },
  {
    label: '登记人',
    prop: 'registrant'
    label: "登记人",
    prop: "registrant",
  },
  {
    label: '登记日期',
    prop: 'registrationtDate'
    label: "登记日期",
    prop: "registrationtDate",
  },
])
const tableData = ref([])
const tableLoading = ref(false)
const purchaseLedgerList = ref([])
const invoiceNumberList = ref([])
]);
const tableData = ref([]);
const tableLoading = ref(false);
const purchaseLedgerList = ref([]);
const invoiceNumberList = ref([]);
const page = reactive({
  current: 1,
  size: 10,
})
const total = ref(0)
});
const total = ref(0);
// ç”¨æˆ·ä¿¡æ¯è¡¨å•弹框数据
const operationType = ref('')
const dialogFormVisible = ref(false)
const operationType = ref("");
const dialogFormVisible = ref(false);
const data = reactive({
  searchForm: {
    supplierNameOrContractNo: '',
    supplierNameOrContractNo: "",
  },
})
const { searchForm, form, rules } = toRefs(data)
});
const { searchForm, form, rules } = toRefs(data);
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1
  getList()
}
  page.current = 1;
  getList();
};
const pagination = ({ current, limit }) => {
  page.current = current;
  page.size = limit;
  getList()
}
  getList();
};
const getList = () => {
  tableLoading.value = true
  registrationList({...searchForm.value, ...page}).then(res => {
    tableLoading.value = false
    tableData.value = res.rows
    total.value = res.total
  })
}
getList()
  tableLoading.value = true;
  registrationList({ ...searchForm.value, ...page }).then((res) => {
    tableLoading.value = false;
    tableData.value = res.rows;
    total.value = res.total;
  });
};
getList();
</script>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>
src/views/reportAnalysis/projectProfit/index.vue
@@ -11,6 +11,7 @@
    </el-form>
    <div class="table_list">
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableLoading="loading"
        :tableData="dataList"
src/views/reportAnalysis/taxComparison/index.vue
@@ -20,6 +20,7 @@
    </el-form>
    <div class="table_list">
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableData="dataList"
        :page="{
src/views/salesManagement/receiptPaymentHistory/index.vue
@@ -48,16 +48,17 @@
    </el-form>
    <div class="table_list">
      <PIMTable
        rowKey="id"
        :column="tableColumn"
        :tableData="tableData"
        :page="page"
        :isSelection="true"
        :isShowSummary="isShowSummarySon"
        :summaryMethod="summarizeMainTable1"
        :handleSelectionChange="handleSelectionChange"
        :tableLoading="tableLoading"
        @pagination="pagination"
        :total="total"
        @pagination="pagination"
        @selection-change="handleSelectionChange"
      ></PIMTable>
    </div>
  </div>