dialogCom.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <template>
  2. <el-dialog
  3. v-loading="defaultLoading"
  4. element-loading-background="rgba(0, 0, 0, 0.8)"
  5. :visible.sync="dialogVisible"
  6. :title="title"
  7. :before-close="handleCloses"
  8. :width="
  9. title === '异常详情' ? '750px' : title === '异常描述' ? '1120px' : '500px'
  10. "
  11. >
  12. <!-- 根据 emptyFlag 和 title 显示不同的内容 -->
  13. <!-- <slot v-if="emptyFlag" name="tableEl"></slot> -->
  14. <abnormal-detail
  15. v-if="title === '异常描述'"
  16. ref="abnormalDetailRef"
  17. :batchCode="rowInfo.batchCode"
  18. ></abnormal-detail>
  19. <div class="dialogBox" v-if="title === '异常详情'">
  20. <el-card shadow="always">
  21. <i class="el-icon-warning"></i> {{ errorInfo }}
  22. </el-card>
  23. </div>
  24. <div v-if="title === '上传报告'">
  25. <el-upload
  26. class="upload-demo"
  27. action=""
  28. multiple
  29. :http-request="customUpload"
  30. :on-remove="handleRemove"
  31. :on-change="handleChange"
  32. :before-upload="checkFileType"
  33. :show-file-list="false"
  34. :file-list="fileList"
  35. >
  36. <el-button size="small" type="primary">选择文件</el-button>
  37. <!-- <div slot="tip" class="el-upload__tip">只能上传pdf文件</div> -->
  38. </el-upload>
  39. <div>
  40. <span style="color: red">展示文件列表区域(双击修改文件名称):</span>
  41. <ul style="margin-top: 10px">
  42. <li v-for="(file, index) in fileList" :key="index">
  43. <el-select
  44. size="small"
  45. v-model="file.reportType"
  46. placeholder="请选择文件类型"
  47. >
  48. <el-option
  49. v-for="item in rportTypeList"
  50. :key="item.reportType"
  51. :label="item.reportTypeName"
  52. :value="item.reportType"
  53. >
  54. </el-option>
  55. </el-select>
  56. <!-- 双击切换编辑状态 -->
  57. <span v-if="editIndex !== index" @dblclick="editFileName(index)">
  58. {{ file.name }}
  59. </span>
  60. <!-- 输入框模式 -->
  61. <el-input
  62. style="width: 150px"
  63. v-if="editIndex === index"
  64. placeholder="请输入文件名"
  65. size="small"
  66. v-model="file.name"
  67. @blur="validateAndSaveFileName(file)"
  68. @keydown.enter="validateAndSaveFileName(file)"
  69. clearable
  70. ></el-input>
  71. <!-- 移除文件按钮 -->
  72. <el-button size="mini" type="text" @click="removeFile(index)">
  73. 移除
  74. </el-button>
  75. </li>
  76. </ul>
  77. </div>
  78. </div>
  79. <div
  80. slot="footer"
  81. v-if="title === '异常详情' || title === '上传报告'"
  82. class="dialog-footer"
  83. >
  84. <el-button @click="handleClose">取消</el-button>
  85. <el-button v-if="title === '上传报告'" @click="handleUpload">
  86. 确定上传
  87. </el-button>
  88. </div>
  89. </el-dialog>
  90. </template>
  91. <script>
  92. import AbnormalDetail from "./abnormalDetail.vue";
  93. import { uploadFile, saveReportBatch, getRportType } from "@/api/performance";
  94. export default {
  95. components: {
  96. AbnormalDetail,
  97. },
  98. props: {
  99. title: String,
  100. visible: Boolean, // 控制对话框显示隐藏
  101. errorInfo: String,
  102. rowInfo: {
  103. type: Object,
  104. default: () => ({}), // Set default value as an empty object
  105. },
  106. },
  107. data() {
  108. return {
  109. defaultLoading: false,
  110. dialogVisible: this.visible,
  111. emptyFlag: false,
  112. batchCode: "",
  113. input: "",
  114. fileList: [], // 文件列表
  115. editIndex: -1, // 当前处于编辑状态的文件索引
  116. rportTypeList: [], //文件类型
  117. };
  118. },
  119. created() {
  120. this.getfileRportType();
  121. },
  122. watch: {
  123. visible(newVal) {
  124. this.dialogVisible = newVal;
  125. this.checkEmptyFlag();
  126. },
  127. rowInfo: {
  128. handler(newVal, oldVal) {
  129. if (newVal && newVal.batchCode) {
  130. this.batchCode = newVal.batchCode;
  131. } else {
  132. console.warn("rowInfo or batchCode is undefined");
  133. }
  134. },
  135. deep: true,
  136. immediate: true,
  137. },
  138. },
  139. methods: {
  140. async getfileRportType() {
  141. try {
  142. const res = await getRportType();
  143. this.rportTypeList = res.data;
  144. } catch (err) {
  145. console.error(err);
  146. }
  147. },
  148. async handleUpload() {
  149. if (this.fileList.length > 0) {
  150. try {
  151. this.defaultLoading = true;
  152. const results = await this.uploadFiles();
  153. const fileDatas = results.map((item, ind) => {
  154. return {
  155. reportName: this.fileList[ind].name,
  156. reportAddr: item.data,
  157. batchCode: this.batchCode,
  158. reportType: this.fileList[ind].reportType
  159. ? this.fileList[ind].reportType
  160. : null,
  161. };
  162. });
  163. const reportTypes = new Set();
  164. let hasDuplicates = false;
  165. fileDatas.forEach((item) => {
  166. if (reportTypes.has(item.reportType)) {
  167. hasDuplicates = true;
  168. } else {
  169. reportTypes.add(item.reportType);
  170. }
  171. });
  172. const nullFileDatas = fileDatas.filter(
  173. (item) => item.reportType === null
  174. );
  175. if (nullFileDatas.length > 0) {
  176. this.defaultLoading = false;
  177. this.$message.warning("请检查是否选择了文件类型");
  178. } else {
  179. if (hasDuplicates) {
  180. this.defaultLoading = false;
  181. this.$message.warning("不可选择的相同文件类型,请重新选择!");
  182. } else {
  183. const res = await saveReportBatch(fileDatas);
  184. if (res.code === 200) {
  185. this.$message.success("保存成功");
  186. this.fileList = [];
  187. this.$emit("getTableList");
  188. this.handleClose();
  189. } else {
  190. this.$message.error(res.msg + "上传失败请重新上传");
  191. }
  192. this.defaultLoading = false;
  193. }
  194. }
  195. } catch (err) {
  196. this.defaultLoading = false;
  197. console.error("error");
  198. }
  199. } else {
  200. this.defaultLoading = false;
  201. this.$message.warning("请选择上传文件");
  202. }
  203. },
  204. //调用单个上传接口
  205. uploadFiles() {
  206. return Promise.all(
  207. this.fileList.map((item) => {
  208. const form = new FormData();
  209. form.append("file", item.raw);
  210. return uploadFile(form);
  211. })
  212. );
  213. },
  214. // 进入编辑模式
  215. editFileName(index) {
  216. this.editIndex = index;
  217. },
  218. //判断上传文件类型
  219. checkFileType(file) {
  220. const isPdf =
  221. file.type === "application/pdf" || file.name.endsWith(".pdf");
  222. if (!isPdf) {
  223. this.$message.error("只能上传PDF文件");
  224. }
  225. return isPdf;
  226. },
  227. //判断修改文件名称是否以.pdf 后缀
  228. validateAndSaveFileName(file) {
  229. if (file.name.trim().endsWith(".pdf")) {
  230. this.saveFileName(file);
  231. } else {
  232. this.$message.error("文件名必须以 .pdf 结尾");
  233. }
  234. },
  235. // 保存文件名并退出编辑模式
  236. saveFileName() {
  237. this.editIndex = -1; // 退出编辑模式
  238. },
  239. removeFile(index) {
  240. // const fileToRemove = this.fileList[index];
  241. this.fileList.splice(index, 1);
  242. },
  243. // 自定义上传方法
  244. customUpload(file) {
  245. const formData = new FormData();
  246. formData.append("file", file);
  247. // 使用 axios 自定义上传逻辑
  248. },
  249. // 移除文件时的处理
  250. handleRemove(file, fileList) {
  251. this.fileList = fileList;
  252. },
  253. // 文件变化时的处理
  254. handleChange(file, fileList) {
  255. this.fileList = fileList;
  256. },
  257. handleClose() {
  258. this.fileList = [];
  259. this.$emit("confirm");
  260. },
  261. handleCloses(done) {
  262. this.$confirm("确认关闭?")
  263. .then((_) => {
  264. done();
  265. this.fileList = [];
  266. this.$emit("confirm");
  267. })
  268. .catch((_) => {});
  269. },
  270. handleConfirm() {
  271. // 获取插槽内容并传递出去
  272. const slotContent = this.$slots.tableEl;
  273. this.$emit("confirm", slotContent);
  274. },
  275. checkEmptyFlag() {
  276. this.$nextTick(() => {
  277. if (this.$refs.abnormalDetailRef) {
  278. const tableData = this.$refs.abnormalDetailRef.tableData;
  279. this.emptyFlag = !tableData || tableData.length === 0;
  280. }
  281. });
  282. },
  283. },
  284. };
  285. </script>
  286. <style scoped>
  287. ::v-deep .el-loading-spinner .path {
  288. stroke: #009688 !important;
  289. }
  290. </style>