index.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <script setup lang="ts">
  2. import { ref, reactive } from "vue";
  3. import { execlUpload as ExcelUpload } from "/@/components/execlUpload";
  4. import { columns, initialColumns, getPropertyAsLabel, convertInvoiceTitle, convertInvoiceTitleData, mockData, statusOptions } from "./columns";
  5. import { useCompany } from "/@/hooks/core/useCompany";
  6. import { httpList } from "/@/api/parameter/finance";
  7. import { useResponseHandle } from "/@/hooks";
  8. import { ElMessage } from "element-plus";
  9. import { isValidHeader, isImportDataValid } from "./validator"
  10. import { invoiceTypeList, useTypeOptions } from "/@/utils/status"
  11. import { utils, writeFile } from "xlsx";
  12. import InvoiceTitle from "./InvoiceTitle.vue"
  13. import ProcessModal from "./ProcessModal.vue"
  14. const emit = defineEmits(["onSuccess"]);
  15. const tableData = ref([]);
  16. const { currentCompany } = useCompany();
  17. const responseHandle = useResponseHandle();
  18. const state = reactive({ visible: false, loading: false })
  19. const sellerInvoiceTitle = ref<Record<string, string>>({});
  20. const purchaserInvoiceTitle = ref<Record<string, string>>({});
  21. const setSellerInvoiceTitle = handleInvoiceTitle.bind(null, true);
  22. const setPurchaserInvoiceTitle = handleInvoiceTitle.bind(null, false);
  23. function handleInvoiceTitle(_isSeller: boolean, invoiceTitle: Record<string, string>) {
  24. if (!invoiceTitle) { return _isSeller ? (sellerInvoiceTitle.value = {}) : (purchaserInvoiceTitle.value = {})}
  25. if (_isSeller) {
  26. //支持的开票方式
  27. const { invoiceType, denomination: _denomination } = invoiceTitle;
  28. const chunks = invoiceType.split(",");
  29. sellerInvoiceTitle.value = convertInvoiceTitleData(convertInvoiceTitle(invoiceTitle))
  30. } else {
  31. purchaserInvoiceTitle.value = convertInvoiceTitleData(convertInvoiceTitle(invoiceTitle));
  32. }
  33. }
  34. const importHeader = ref([])
  35. const initialHeader = initialColumns.slice(0, 7).map(({ label }) => label)
  36. function onUploadSuccess({ results, header }){
  37. if(!isValidHeader(initialHeader, header)){ return }
  38. const list = []
  39. for(const index in results){
  40. const result = results[index]
  41. const item: Record<string, any> = {}
  42. Object.keys(result).forEach(label => {
  43. const property = getPropertyAsLabel(label)
  44. const value = String(result[label]).trim()
  45. item[property] = value
  46. })
  47. list.push({...item, rawIndex: Number(index) + 1, status: 0 })
  48. }
  49. list.sort((a, b) => a.group - b.group)
  50. if(isImportDataValid(list)) tableData.value = list
  51. console.log(tableData.value)
  52. }
  53. const handleProcess = () => state.visible = true
  54. const clearData = () => tableData.value = []
  55. async function setTitle(companyNo, isSeller = true) {
  56. state.loading = true
  57. const { code, data, message } = await httpList({ companyNo });
  58. state.loading = false
  59. if(code === 0){
  60. console.log(data.list)
  61. isSeller ? setSellerInvoiceTitle(data.list[0]) : setPurchaserInvoiceTitle(data.list[0])
  62. } else {
  63. ElMessage.warning(message)
  64. }
  65. }
  66. async function initialData(){
  67. await (currentCompany.value.companyNo && setTitle(currentCompany.value.companyNo))
  68. await setTitle('GS2404151642335170', false)
  69. }
  70. function handleUpdateGroup(groupData){
  71. const { status, remark, group } = groupData
  72. tableData.value.forEach((item: any) => {
  73. if(item.group != group) return
  74. // 之前已经该过状态,不能改到成功状态去
  75. if(item.status == 3 && status != 0) return
  76. item.remark = remark;
  77. item.status = status
  78. })
  79. }
  80. function handleUpdateSequenceNo(sequenceData){
  81. const { status, remark, sequenceNo } = sequenceData
  82. tableData.value.forEach((item: any) => {
  83. if(item.sequenceNo == sequenceNo){ item.remark = remark; item.status = status; }
  84. })
  85. }
  86. function download(){
  87. const data = tableData.value.map((item: any, index) => ({
  88. '序号': Number(index) + 1,
  89. '分组': item.group,
  90. '发票类型': item.invtype,
  91. '电子邮箱': item.email,
  92. '订单编号': item.sequenceNo,
  93. '订单平台类型': item.platform_type,
  94. '开票金额': item.inv_fee,
  95. '平台采购PO': item.poCode,
  96. '状态': statusOptions.find(({ value }) => value == item.status)?.label,
  97. '备注': item.remark
  98. }))
  99. const workBook = utils.book_new();
  100. const workSheet = utils.json_to_sheet(data);
  101. utils.book_append_sheet(workBook, workSheet, "sheet");
  102. writeFile(workBook, `批量导入数据.xlsx`, { bookType: "xlsx" });
  103. }
  104. initialData()
  105. </script>
  106. <template>
  107. <div
  108. class="flex flex-col bg-white justify-start items-start"
  109. style="height:calc(100vh - 48px);width: 100%"
  110. v-loading="state.loading"
  111. >
  112. <div class="flex w-full">
  113. <ElForm label-width="120px" style="width:100%">
  114. <ElRow>
  115. <ElCol :span="12">
  116. <ElFormItem label="销售方公司抬头">
  117. <div class="flex flex-col w-full">
  118. <ElInput
  119. :modelValue="(sellerInvoiceTitle || {}).invoice_title"
  120. class="mb-[10px]"
  121. disabled
  122. />
  123. <InvoiceTitle :detail="sellerInvoiceTitle || {}" />
  124. </div>
  125. </ElFormItem>
  126. </ElCol>
  127. <ElCol :span="12">
  128. <ElFormItem label="购买方公司抬头">
  129. <div class="flex flex-col w-full">
  130. <ElInput
  131. :modelValue="(purchaserInvoiceTitle || {}).invoice_title"
  132. class="mb-[10px]"
  133. disabled
  134. />
  135. <InvoiceTitle :detail="purchaserInvoiceTitle || {}" />
  136. </div>
  137. </ElFormItem>
  138. </ElCol>
  139. </ElRow>
  140. </ElForm>
  141. </div>
  142. <ExcelUpload
  143. v-if="tableData.length === 0"
  144. style="height:auto !important"
  145. @onSuccess="onUploadSuccess"
  146. />
  147. <ElTag class="mb-[10px]">
  148. {{ tableData.length }} / 300
  149. </ElTag>
  150. <ElTable
  151. stripe
  152. border
  153. size="small"
  154. :data="tableData"
  155. max-height="500px"
  156. style="width: 100%"
  157. >
  158. <ElTableColumn v-for="(column, index) in columns" v-bind="column" :key="index" show-overflow-tooltip>
  159. <template #header>
  160. <span v-if="!column?.required">{{ column.label }}</span>
  161. <p v-else>
  162. <span style="color: #f56c6c; font-size: 14px">* </span>
  163. {{ column.label }}
  164. </p>
  165. </template>
  166. <template #="{ row }">
  167. <ElTag v-if="column.prop === 'status'" :type="statusOptions.find(({ value }) => value === row.status)?.type || ''">
  168. {{ statusOptions.find(({ value }) => value === row.status)?.label || '--' }}
  169. </ElTag>
  170. <span v-else>{{ row[column.prop] }}</span>
  171. </template>
  172. </ElTableColumn>
  173. </ElTable>
  174. <div class="w-full flex justify-end" v-if="tableData.length !== 0" style="padding: 10px 0 0 0">
  175. <ElButton @click="clearData">取消</ElButton>
  176. <ElButton
  177. type="primary"
  178. :loading="state.loading"
  179. @click="handleProcess"
  180. >批量创建</ElButton>
  181. </div>
  182. <ProcessModal
  183. :data="tableData"
  184. v-model:visible="state.visible"
  185. :companyNo="currentCompany.companyNo"
  186. :sellerInvoiceTitle="sellerInvoiceTitle"
  187. :purchaserInvoiceTitle="purchaserInvoiceTitle"
  188. @updateGroup="handleUpdateGroup"
  189. @updateSequenceNo="handleUpdateSequenceNo"
  190. @download="download"
  191. @refresh="clearData"
  192. />
  193. </div>
  194. </template>
  195. <style lang="scss" scoped>
  196. :deep(.el-upload-list__item) { display: none !important; }
  197. </style>