index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. <script setup lang="ts">
  2. import { ref, onMounted } from "vue";
  3. import { useRoute, useRouter } from "vue-router";
  4. import * as XLSX from "xlsx";
  5. import {
  6. assessmentDownloadDataRosterTemplateApi,
  7. importAssessmentQuotaDisplayBackData,
  8. postImportAssessmentTemplate
  9. } from "@/api/download";
  10. import { ElMessage } from "element-plus";
  11. defineOptions({
  12. name: "IndexDefineImport"
  13. });
  14. const route = useRoute();
  15. const router = useRouter();
  16. const emit = defineEmits(["handleImport"]);
  17. const uploadShow = ref(true);
  18. const query = ref({});
  19. const fileDocument = ref<File | null>(null); // 存储文件
  20. const assessmentType = ref();
  21. onMounted(() => {
  22. // assessmentType
  23. Object.assign(query.value, route.query);
  24. assessmentType.value = Number(query.value.assessmentType);
  25. console.log("111", query.value);
  26. });
  27. const uploadFile = () => {};
  28. const tableHeaders = ref<any>([]);
  29. const tableData = ref<any>([]);
  30. const handleUploadChange = async (file: File) => {
  31. fileDocument.value = file; // 保存文件
  32. const formData = new FormData();
  33. formData.append("file", fileDocument.value);
  34. const fileToSend = formData.get("file");
  35. const { code, data, msg } = await importAssessmentQuotaDisplayBackData({
  36. file: fileToSend,
  37. type: route.query.assessmentType,
  38. assessmentId: route.query.id
  39. });
  40. const reader = new FileReader();
  41. let fileType = file.name.slice(-4);
  42. // if (fileType == "xlsx") {
  43. if (data.code == 200) {
  44. uploadShow.value = false; // 隐藏上传区域,显示数据表
  45. tableData.value = data.data;
  46. // reader.onload = e => {
  47. // const data = new Uint8Array(e.target?.result as ArrayBuffer);
  48. // const workbook = XLSX.read(data, { type: "array" }); // 读取 Excel 文件
  49. // const firstSheetName = workbook.SheetNames[0]; // 获取第一个工作表名
  50. // const worksheet = workbook.Sheets[firstSheetName]; // 获取第一个工作表
  51. // const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); // 将工作表转为 JSON
  52. // if (
  53. // jsonData[1].length == 6 &&
  54. // (query.value.assessmentType == 0 || query.value.assessmentType == 1)
  55. // ) {
  56. // tableHeaders.value = jsonData[1];
  57. // const arr = jsonData.slice(2).map(row => {
  58. // if (row[0] && row[1] && row[2] && row[3]) {
  59. // const rowData = {};
  60. // tableHeaders.value.forEach((header, index) => {
  61. // if (row[index]) {
  62. // rowData[header] = row[index];
  63. // }
  64. // });
  65. // return rowData;
  66. // }
  67. // });
  68. // tableData.value = arr.filter(item => item);
  69. // ElMessage.success("文件上传成功");
  70. // uploadShow.value = false; // 隐藏上传区域,显示数据表
  71. // } else if (query.value.assessmentType == 2) {
  72. // tableHeaders.value = [
  73. // "用户组",
  74. // "用户组编号",
  75. // "考核模板",
  76. // "指标名称",
  77. // "完成值",
  78. // "得分"
  79. // ]; // 表头
  80. // const arr = jsonData.slice(2).map(row => {
  81. // if (row[0] && row[1] && row[2] && row[3]) {
  82. // const rowData = {};
  83. // tableHeaders.value.forEach((header, index) => {
  84. // if (row[index]) {
  85. // rowData[header] = row[index];
  86. // }
  87. // });
  88. // return rowData;
  89. // }
  90. // });
  91. // tableData.value = arr.filter(item => item);
  92. // ElMessage.success("文件上传成功");
  93. // uploadShow.value = false; // 隐藏上传区域,显示数据表
  94. // } else {
  95. // ElMessage.error("文件为空或格式不正确");
  96. // }
  97. // };
  98. console.log(data);
  99. } else {
  100. ElMessage.error(data.msg);
  101. }
  102. // } else {
  103. // ElMessage.error("请上传xlsx文件");
  104. // }
  105. reader.readAsArrayBuffer(file); // 读取文件为 ArrayBuffer
  106. };
  107. // 上传
  108. const postImportAssessmentTemplateApi = async data => {
  109. if (!fileDocument.value) {
  110. ElMessage.error("请先上传文件");
  111. return;
  112. }
  113. try {
  114. const formData = new FormData();
  115. // 将 tableData 转换为 XLSX 格式
  116. // const ws = XLSX.utils.json_to_sheet(tableData.value); // 将表格数据转为工作表
  117. // const wb = XLSX.utils.book_new(); // 创建一个新的工作簿
  118. // XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); // 将工作表添加到工作簿
  119. // // 将工作簿转换为二进制的 XLSX 文件数据
  120. // const xlsxData = XLSX.write(wb, { bookType: "xlsx", type: "array" });
  121. // // 创建一个 Blob 对象,指定 MIME 类型为 XLSX 格式
  122. // const blob = new Blob([xlsxData], {
  123. // type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  124. // });
  125. // // 创建一个文件对象
  126. // const file = new File([blob], "tableData.xlsx", {
  127. // type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  128. // });
  129. // 将生成的文件添加到 FormData 中
  130. formData.append("file", fileDocument.value);
  131. // 获取文件并执行上传
  132. const fileToSend = formData.get("file");
  133. // 调用 API 上传文件
  134. const { data } = await postImportAssessmentTemplate({
  135. file: fileToSend,
  136. type: route.query.assessmentType,
  137. assessmentId: route.query.id
  138. });
  139. if (data.code === 200) {
  140. // 根据后端返回的 code 判断是否成功
  141. ElMessage.success(data.msg);
  142. // 重置上传状态
  143. router.back();
  144. uploadShow.value = !uploadShow.value;
  145. tableHeaders.value = []; // 清空表头
  146. tableData.value = [
  147. { name: "" },
  148. { defin: "" },
  149. { caliber: "" },
  150. { type: "" },
  151. { from: "" }
  152. ]; // 清空表格数据
  153. } else {
  154. ElMessage.error(data.msg);
  155. }
  156. } catch (error) {
  157. ElMessage.error("上传失败,请重试");
  158. console.error(error);
  159. }
  160. };
  161. const backDefine = () => {
  162. router.back();
  163. };
  164. </script>
  165. <template>
  166. <div>
  167. <div class="w-3/4 m-auto mt-4">
  168. <div class="w-full bg p-3">
  169. <h5>1.下载导入模板</h5>
  170. <p class="text-xs mt-2 text">根据提升信息完善表格内容</p>
  171. <el-button class="mt-2"
  172. ><el-icon> <Download /> </el-icon
  173. ><a
  174. v-if="query.assessmentType == 0 || query.assessmentType == 3"
  175. href="http://172.16.9.165:8765/download/考核数据导入模板-人员.xlsx"
  176. download="考核数据导入模板-人员.xlsx"
  177. >下载空的模板表格</a
  178. >
  179. <a
  180. v-if="query.assessmentType == 1"
  181. href="http://172.16.9.165:8765/download/考核数据导入模板-部门.xlsx"
  182. download="考核数据导入模板-部门.xlsx"
  183. >下载空的模板表格</a
  184. >
  185. <a
  186. v-if="query.assessmentType == 2"
  187. href="http://172.16.9.165:8765/download/考核数据导入模板-用户组.xlsx"
  188. download="考核数据导入模板-用户组.xlsx"
  189. >下载空的模板表格</a
  190. ></el-button
  191. >
  192. </div>
  193. <div class="w-full mt-4 bg p-3">
  194. <h5>2.上传完善后的模板</h5>
  195. <p class="text-xs mt-2 text mb-2">
  196. 更新信息的模板中,如有空的数据列,则相应字段信息会被清空,请谨慎填写
  197. </p>
  198. <div v-if="uploadShow">
  199. <el-upload
  200. class="upload-demo"
  201. drag
  202. action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
  203. :before-upload="file => handleUploadChange(file)"
  204. :show-file-list="false"
  205. >
  206. <el-icon class="el-icon--upload"><upload-filled /></el-icon>
  207. <div class="el-upload__text">
  208. 点击<em>图标选择上传</em>或者将文件拖拽到此区域
  209. </div>
  210. </el-upload>
  211. </div>
  212. <div v-else class="mb-2">
  213. <el-table
  214. v-if="query.assessmentType == 0 || query.assessmentType == 3"
  215. :data="tableData"
  216. border
  217. style="width: 100%"
  218. max-height="250"
  219. >
  220. <el-table-column label="工号" prop="hospitalCode" />
  221. <el-table-column label="人员" prop="realName" />
  222. <el-table-column label="考核模板" prop="tpName" />
  223. <el-table-column label="指标名称" prop="quotaName" />
  224. <el-table-column label="完成值" prop="finalValue" />
  225. <el-table-column label="得分" prop="score" />
  226. </el-table>
  227. <el-table
  228. v-if="query.assessmentType == 1"
  229. :data="tableData"
  230. border
  231. style="width: 100%"
  232. max-height="250"
  233. >
  234. <el-table-column label="部门" prop="deptName" />
  235. <el-table-column label="部门编号" prop="hospitalCode" />
  236. <el-table-column label="考核模板" prop="tpName" />
  237. <el-table-column label="指标名称" prop="quotaName" />
  238. <el-table-column label="完成值" prop="finalValue" />
  239. <el-table-column label="得分" prop="score" />
  240. </el-table>
  241. <el-table
  242. v-if="query.assessmentType == 2"
  243. :data="tableData"
  244. border
  245. style="width: 100%"
  246. max-height="250"
  247. >
  248. <el-table-column label="用户组" prop="groupName" />
  249. <el-table-column label="用户组编号" prop="hospitalCode" />
  250. <el-table-column label="考核模板" prop="tpName" />
  251. <el-table-column label="指标名称" prop="quotaName" />
  252. <el-table-column label="完成值" prop="finalValue" />
  253. <el-table-column label="得分" prop="score" />
  254. </el-table>
  255. </div>
  256. <div class="float-right">
  257. <el-button @click="backDefine">取消</el-button>
  258. <el-button type="primary" @click="postImportAssessmentTemplateApi"
  259. >确认</el-button
  260. >
  261. </div>
  262. <p class="h-11 no-select">.</p>
  263. </div>
  264. </div>
  265. </div>
  266. </template>
  267. <style lang="scss" scoped>
  268. .bg {
  269. background-color: #f8f9fa;
  270. }
  271. .text {
  272. color: #999;
  273. }
  274. .upoload {
  275. float: right;
  276. }
  277. .no-select {
  278. color: rgb(255 255 255 / 0%);
  279. user-select: none;
  280. }
  281. </style>