You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1799 lines
69 KiB

3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
4 months ago
2 years ago
2 years ago
4 months ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
4 months ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
4 months ago
4 months ago
4 months ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
4 months ago
4 months ago
4 months ago
4 months ago
2 years ago
2 years ago
2 years ago
4 months ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
  1. <template>
  2. <div>
  3. <!--主体-->
  4. <div>
  5. <div class="middlebox">
  6. <div class="contenttitle">
  7. 体检登记 /
  8. <span class="contenttitleBold">批量预登记</span>
  9. </div>
  10. </div>
  11. <div style="margin-bottom: 15px;display: flex;justify-content: space-between;
  12. background-color: #fff;border-radius: 8px;padding: 15px;margin-top: 7px;">
  13. <div></div>
  14. <div style="display: flex;">
  15. <div style="padding: 0 5px;" v-show="checkPagePriv(pagePriv.privs, '下载导入模版')">
  16. <a :underline="false" href="/files/单位体检人员名单导入模板.xlsx"><el-button class="commonbutton"
  17. size="small">下载导入模版</el-button></a>
  18. </div>
  19. <div style="padding: 0 5px;" v-show="checkPagePriv(pagePriv.privs, '下载职业病导入模版')">
  20. <a :underline="false" href="/files/职业病体检人员名单导入模板.xlsx"><el-button class="commonbutton"
  21. size="small" style="width:140px;">下载职业病导入模版</el-button></a>
  22. </div>
  23. <div style="padding: 0 5px;" v-show="checkPagePriv(pagePriv.privs, '导入')">
  24. <el-button class="commonbutton" @click="seq = 0" size="small">导入</el-button>
  25. </div>
  26. <div style="padding: 0 5px;" v-show="checkPagePriv(pagePriv.privs, '导入后结果状态导出')">
  27. <el-button class="commonbutton" @click="btnExport('tableData')" size="small"
  28. style="width:140px;">导入后结果状态导出</el-button>
  29. </div>
  30. </div>
  31. </div>
  32. <div id="tableData" style="padding: 15px;background-color: #fff;border-radius: 8px;">
  33. <el-table :data="tableData" v-if="mode == '10' || mode == '30'" :row-class-name="importRowClassName"
  34. :height="window.pageHeight < 600 ? 440 : (window.pageHeight - 210)" highlight-current-row size="small"
  35. :summary-method="getSummaries" show-summary>
  36. <el-table-column type="index" label="序号" width="40" align="center" />
  37. <el-table-column prop="importState" label="导入状态" min-width="80" sortable />
  38. <el-table-column prop="importDes" label="导入描述" min-width="180" sortable />
  39. <el-table-column v-for="(item, index) in importCols" :key="`col${index}`" :prop="item.dispLabel" align="center"
  40. :label="item.dataLabel || item.dispLabel" min-width="100" />
  41. </el-table>
  42. <el-table :data="tableData" border v-if="mode == '20'" :row-class-name="importRowClassName"
  43. :height="window.pageHeight < 600 ? 440 : (window.pageHeight - 210)" highlight-current-row size="small"
  44. :summary-method="getSummaries" show-summary>
  45. <el-table-column type="index" label="序号" width="40" align="center" />
  46. <el-table-column prop="importState" label="导入状态" min-width="80" sortable />
  47. <el-table-column prop="importDes" label="导入描述" min-width="180" sortable />
  48. <el-table-column prop="patientNo" align="center" label="档案号" min-width="80" />
  49. <el-table-column prop="medicalTimes" align="center" label="体检次数" min-width="80" />
  50. <el-table-column prop="patientName" align="center" label="姓名" min-width="80" />
  51. <el-table-column prop="sexId" align="center" label="性别" min-width="40">
  52. <template slot-scope="scope">
  53. <div>{{ dddw(dict.sex, "id", scope.row.sexId, "displayName") }}</div>
  54. </template>
  55. </el-table-column>
  56. <el-table-column prop="birthDate" align="center" label="出生日期" min-width="80">
  57. <template slot-scope="scope">
  58. <div>{{ scope.row.birthDate ? moment(new Date(scope.row.birthDate)).format('yyyy-MM-DD') : '' }}</div>
  59. </template>
  60. </el-table-column>
  61. <el-table-column prop="age" align="center" label="年龄" min-width="40" />
  62. <el-table-column prop="customerOrgParentName" align="center" label="单位" min-width="150" />
  63. <el-table-column prop="customerOrgName" align="center" label="部门" min-width="120" />
  64. <el-table-column prop="telephone" align="center" label="电话" min-width="100" />
  65. <el-table-column prop="mobileTelephone" align="center" label="手机" min-width="100" />
  66. <el-table-column prop="creatorName" align="center" label="登记人员" min-width="80" />
  67. <el-table-column prop="creationTime" align="center" label="登记日期" min-width="80">
  68. <template slot-scope="scope">
  69. <div>{{ scope.row.birthDate ? moment(new Date(scope.row.creationTime)).format('yyyy-MM-DD') : '' }}</div>
  70. </template>
  71. </el-table-column>
  72. </el-table>
  73. </div>
  74. </div>
  75. <!--弹窗-->
  76. <div>
  77. <el-dialog title="请选择导入方式" :visible.sync="dialogGroup.mode" width="700px" :show-close="false" :append-to-body="true"
  78. :close-on-click-modal="false">
  79. <div style="height:400px;margin-left: 200px;">
  80. <br /><el-radio v-model="mode" label="10">从Excle导入</el-radio>
  81. <br />
  82. <br /><el-radio v-model="mode" label="30">从Excle导入职业病</el-radio>
  83. <br />
  84. <br /><el-radio v-model="mode" label="20">从以往体检资料中导入</el-radio>
  85. </div>
  86. <span slot="footer" class="dialog-footer">
  87. <el-button type="primary" @click="btnFirst" class="commonbutton">下一步</el-button>
  88. <el-button @click="seq = -1" class="commonbutton">关闭</el-button>
  89. </span>
  90. </el-dialog>
  91. <el-dialog title="导入EXCEL注意事项" :visible.sync="dialogGroup.fileReadme" width="700px" :show-close="false"
  92. :append-to-body="true" :close-on-click-modal="false">
  93. <div style="height:400px;padding: 0 20px; ">
  94. <br />导入Excel时Excel的格式必须符合一定规范该格式的模板文件可通过下载模板获取
  95. <br />注意事项如下:
  96. <br />
  97. <div style="margin-left: 25px;">1姓名不能为空其余数据可根据实际情况选择是否填写
  98. <br />2部门单位分组性别婚姻状况人员类别体检类别民族必须与本软件系统中的名称完全一致
  99. <br />3年龄和出生日期可以只填一栏系统将自动对年龄和出生日期进行相互转换
  100. <br />4Excel中标题列不能有单元格合并
  101. </div>
  102. </div>
  103. <span slot="footer" class="dialog-footer">
  104. <el-button class="commonbutton" type="primary" @click="seq--">上一步</el-button>
  105. <el-button class="commonbutton" type="primary" @click="seq++">下一步</el-button>
  106. <el-button class="commonbutton" @click="seq = -1">关闭</el-button>
  107. </span>
  108. </el-dialog>
  109. <el-dialog title="选择文件" :visible.sync="dialogGroup.fileChoose" width="700px" :show-close="false"
  110. :append-to-body="true" :close-on-click-modal="false">
  111. <div style="height:400px;padding: 0 50px; ">
  112. <!-- webkitdirectory 选择文件属性 multiple 多选属性-->
  113. <div><input id="fileNames" type="file" accept=".xlsx,.xls" @change="changeFileChoose" @focus="fileGetFocus" />
  114. </div>
  115. <div style="margin: 5px 70px;width:240px;">
  116. <el-table :data="sheetNames" border ref="sheetNames" height="300" row-click="chooseSheetName"
  117. highlight-current-row size="small">
  118. <el-table-column prop="sheetName" label="Excel表单名" min-width="200" align="center" />
  119. </el-table>
  120. </div>
  121. <div style="display: flex;flex-wrap: wrap;">
  122. <span style="margin-top: 6px;">标题行 </span>
  123. <el-input type="number" v-model="readDataOpts.titleRow" size="small" style="width:60px;margin: 0 5px;" />
  124. <span style="margin-top: 6px;"></span>
  125. </div>
  126. </div>
  127. <span slot="footer" class="dialog-footer">
  128. <el-button class="commonbutton" type="primary" @click="seq--">上一步</el-button>
  129. <el-button class="commonbutton" type="primary" @click="seq++">下一步</el-button>
  130. <el-button class="commonbutton" @click="seq = -1">关闭</el-button>
  131. </span>
  132. </el-dialog>
  133. <el-dialog title="选择待导入的客户信息" :visible.sync="dialogGroup.fileDataOpr" width="700px" :show-close="false"
  134. :close-on-click-modal="false"> <!--:append-to-body="true" -->
  135. <div style="height:400px;">
  136. <div style="margin-top: -10px;">
  137. 1在标题列右击鼠标可设置列名标题列有 才参与数据导入<br>
  138. 2身份证号有值且合法时将以身份证号为主自动换算性别出生日期及年龄<br>
  139. 3按住 Ctr1 Shift 键可进行多选<br>
  140. </div>
  141. <div style="margin: 5px 0px 0px;" @contextmenu.prevent=""> <!-- -->
  142. <el-table :data="excelData" border ref="excelData" @header-contextmenu="headerContextmenu" height="340"
  143. @row-click="chooseDataImport" row-key="id" highlight-current-row size="small"
  144. :row-class-name="handleRowClassName">
  145. <el-table-column type="index" align="center" label="序号" min-width="40" />
  146. <!--
  147. <el-table-column prop="choosed" align="center" label="选中" min-width="40"/>
  148. -->
  149. <el-table-column v-for="(item, index) in excelCols" :key="`col_${index}`" :prop="item.dispLabel"
  150. align="center" :label="(item.val ? '√ ' : '') + (item.dataLabel || item.dispLabel)"
  151. :min-width="100 + index" />
  152. </el-table>
  153. </div>
  154. </div>
  155. <span slot="footer" class="dialog-footer">
  156. <div style="display: flex;justify-content: space-between;">
  157. <div style="display: flex;">
  158. <el-button class="commonbutton" type="primary" @click="btnChoose('excelData', 'all')">全选</el-button>
  159. <el-button class="commonbutton" type="primary" @click="btnChoose('excelData')">取消全选</el-button>
  160. </div>
  161. <div style="display: flex;">
  162. <el-button class="commonbutton" type="primary" @click="seq--">上一步</el-button>
  163. <el-button class="commonbutton" type="primary" @click="seq++">下一步</el-button>
  164. <el-button class="commonbutton" @click="seq = -1">关闭</el-button>
  165. </div>
  166. </div>
  167. </span>
  168. </el-dialog>
  169. <el-dialog title="选择单位" :visible.sync="dialogGroup.fileDataOpts" width="700px" :show-close="false"
  170. :close-on-click-modal="false"> <!--:append-to-body="true" -->
  171. <div style="height:400px;">
  172. <div style="margin-top: -10px;">
  173. 选择的人员信息必须直接属于该单位或者是该单位的一级部门,如果人员信息直接属于该单位请将Exce1文件中该人员信息的部门名称设为空
  174. </div>
  175. <div style="display: flex;margin:20px;">
  176. <div>
  177. <span>体检单位</span>
  178. <el-cascader v-model="customerOrgIds" :options="customerOrgTree" popper-class="example" style="width:260px;"
  179. @change="changeCustomerOrg" filterable
  180. :props="{ checkStrictly: true, expandTrigger: 'hover', ...customerOrg.treeprops, }"
  181. :show-all-levels="true" size="small">
  182. </el-cascader>
  183. </div>
  184. <div style="margin-left: 20px">
  185. <span>单位体检次数</span>
  186. <el-select v-model="customerOrgRegister" placeholder="次数" style="width: 60px; margin-left: 10px"
  187. size="small" value-key="id">
  188. <el-option v-for="item in customerOrgRegisterList" :key="item.id" :label="item.medicalTimes"
  189. :value="item" />
  190. </el-select>
  191. </div>
  192. </div>
  193. <div style="display: flex;margin:20px;">
  194. <span>相同姓名的人员</span>
  195. <div style="display: flex;margin-top:20px;">
  196. <el-radio v-model="dataImportOpts.nameType" label="1">同名病人提示</el-radio>
  197. <el-radio v-model="dataImportOpts.nameType" label="2">本单位同名提示</el-radio>
  198. <el-radio v-model="dataImportOpts.nameType" label="3">不提示</el-radio>
  199. </div>
  200. </div>
  201. <div style="display: flex;margin:20px;">
  202. <span>登记状态</span>
  203. <div style="display: flex;margin-top:20px;">
  204. <el-radio v-model="dataImportOpts.completeFlag" label="0">预登记</el-radio>
  205. <el-radio v-model="dataImportOpts.completeFlag" label="1">正式登记</el-radio>
  206. </div>
  207. </div>
  208. <!-- 2024-04-09 取消此选项 -->
  209. <div style="display: flex;margin:20px;" v-if="false">
  210. <span>工卡号</span>
  211. <div style="display: block;margin-top:20px;">
  212. <div style="display: flex;">
  213. <el-checkbox v-model="dataImportOpts.isAutoCreatePatientNo" />
  214. <span style="margin-left:5px;">工卡号作为档案号</span>
  215. </div>
  216. <div style="display: flex;" v-if="dataImportOpts.isAutoCreatePatientNo">
  217. <span style="margin-top:6px;">工卡号开始位置</span>
  218. <el-input type="number" v-model="dataImportOpts.cardStartNum" size="small"
  219. style="width:60px;margin: 0 10px 0 0;" />
  220. <span style="margin-top:6px;">长度</span>
  221. <el-input type="number" v-model="dataImportOpts.cardLength" size="small"
  222. style="width:60px;margin: 0 10px 0 0;" />
  223. <span style="margin-top:6px;"> 不足长度时前面补0</span>
  224. </div>
  225. </div>
  226. </div>
  227. <div style="display: flex;margin:20px;">
  228. <span>是否自动创建部门</span>
  229. <el-checkbox v-model="dataImportOpts.isAutoCreateDepartment" />
  230. </div>
  231. </div>
  232. <span slot="footer" class="dialog-footer">
  233. <el-button class="commonbutton" type="primary" @click="seq--">上一步</el-button>
  234. <el-button class="commonbutton" type="primary" @click="btnImport">确定导入</el-button>
  235. <el-button class="commonbutton" @click="seq = -1">关闭</el-button>
  236. </span>
  237. </el-dialog>
  238. <el-dialog title="同名人员信息确认" :visible.sync="dialogSameMan" width="500px" :show-close="false"
  239. :close-on-click-modal="false"> <!--:append-to-body="true" -->
  240. <div style="margin: 5px 0px 0px;"> <!-- -->
  241. <el-table :data="sameMans" border ref="sameMans" height="260" @row-click="rowClickSameMan" row-key="patientId"
  242. highlight-current-row size="small">
  243. <el-table-column type="index" align="center" label="序号" min-width="40" />
  244. <el-table-column prop="patientNo" align="center" label="档案号" min-width="80" />
  245. <el-table-column prop="displayName" align="center" label="姓名" min-width="80" />
  246. <el-table-column prop="sexId" align="center" label="性别" min-width="40" />
  247. <el-table-column prop="idNo" align="center" label="身份证号" min-width="150" />
  248. <el-table-column prop="birthDate" align="center" label="出生日期" min-width="110" />
  249. <el-table-column prop="telephone" align="center" label="电话" min-width="100" />
  250. <el-table-column prop="mobileTelephone" align="center" label="手机" min-width="100" />
  251. </el-table>
  252. </div>
  253. <span slot="footer" class="dialog-footer">
  254. <el-button class="commonbutton" type="primary" @click="btnOldMan">按档案人员导入</el-button>
  255. <el-button class="commonbutton" type="primary" @click="btnNewMan">按新人方式导入</el-button>
  256. </span>
  257. </el-dialog>
  258. <!--从历史数据库中查询导入-->
  259. <el-dialog title="选择单位查询条件" :visible.sync="dialogGroup.query" width="700px" :show-close="false"
  260. :close-on-click-modal="false"> <!--:append-to-body="true" -->
  261. <div style="height:400px;">
  262. <div style="margin-top: -10px;">
  263. 选择单位时必须选择其体检次数
  264. </div>
  265. <div style="display: flex;margin:20px;">
  266. <span class="spanLeftClass">体检单位</span>
  267. <el-cascader v-model="query.customerOrgIds" :options="customerOrgTree" style="width:260px;"
  268. @change="changeQueryCustomerOrg" filterable popper-class="example"
  269. :props="{ checkStrictly: true, expandTrigger: 'hover', ...customerOrg.treeprops, }" :show-all-levels="true"
  270. size="small">
  271. </el-cascader>
  272. <div style="margin-left: 20px">
  273. <span>单位体检次数</span>
  274. <el-select v-model="query.customerOrgRegister" placeholder="次数" style="width: 60px; margin-left: 10px"
  275. size="small" value-key="id">
  276. <el-option v-for="item in query.customerOrgRegisterList" :key="item.id" :label="item.medicalTimes"
  277. :value="item" />
  278. </el-select>
  279. </div>
  280. </div>
  281. <div style="display: flex;margin:20px;">
  282. <span class="spanLeftClass">登记日期</span>
  283. <el-date-picker v-model="query.startDate" type="date" placeholder="起始日期" size="small" style="width:130px;" />
  284. <span class="spanMidClass"></span>
  285. <el-date-picker v-model="query.endDate" type="date" placeholder="截止日期" size="small" style="width:130px;" />
  286. </div>
  287. <div style="display: flex;margin:20px;">
  288. <span class="spanLeftClass">档案号</span>
  289. <el-input placeholder="起始档案号" v-model="query.patientNoStart" size="small" clearable style="width: 130px" />
  290. <span class="spanMidClass"></span>
  291. <el-input placeholder="截止档案号" v-model="query.patientNoEnd" size="small" clearable style="width: 130px" />
  292. </div>
  293. <div style="display: flex;margin:20px;">
  294. <span class="spanLeftClass">姓名</span>
  295. <el-input placeholder="姓名" v-model="query.patientName" size="small" clearable style="width: 130px" />
  296. <span class="spanMidClass">性别</span>
  297. <el-select v-model="query.sexId" placeholder="请选择" style="width: 130px" size="small">
  298. <el-option label="全部" value="A" />
  299. <el-option v-for="item in dict.sex" :key="item.id" :label="item.displayName" :value="item.id" />
  300. </el-select>
  301. </div>
  302. <div style="display: flex;margin:20px;">
  303. <span class="spanLeftClass">状态</span>
  304. <el-select v-model="query.completeFlag" placeholder="请选择" clearable style="width: 130px" size="small">
  305. <el-option v-for="item in dict.completeFlag" :key="item.id" :label="item.displayName" :value="item.id" />
  306. </el-select>
  307. </div>
  308. </div>
  309. <span slot="footer" class="dialog-footer">
  310. <el-button class="commonbutton" type="primary" @click="seq--">上一步</el-button>
  311. <el-button class="commonbutton" type="primary" @click="seq++">下一步</el-button>
  312. <el-button class="commonbutton" @click="seq = -1">关闭</el-button>
  313. </span>
  314. </el-dialog>
  315. <!--选择历史档案客户信息-->
  316. <el-dialog title="选择历史档案客户信息" :visible.sync="dialogGroup.oldMansChoose" width="700px" :show-close="false"
  317. :close-on-click-modal="false"> <!--:append-to-body="true" -->
  318. <div style="height:400px;">
  319. <div style="margin-top: -10px;">
  320. 按住 Ctr1 Shift 键可进行多选<br>
  321. </div>
  322. <div style="margin: 5px 0px 0px;"> <!-- -->
  323. <el-table :data="prList" border ref="prList" height="375" @row-click="rowClickPrList" highlight-current-row
  324. size="small" :row-class-name="handleRowClassName">
  325. <el-table-column type="index" align="center" label="序号" min-width="40" />
  326. <el-table-column prop="patientNo" align="center" label="档案号" min-width="80" />
  327. <el-table-column prop="medicalTimes" align="center" label="体检次数" min-width="80" />
  328. <el-table-column prop="patientName" align="center" label="姓名" min-width="80" />
  329. <el-table-column prop="sexId" align="center" label="性别" min-width="40">
  330. <template slot-scope="scope">
  331. <div>{{ dddw(dict.sex, "id", scope.row.sexId, "displayName") }}</div>
  332. </template>
  333. </el-table-column>
  334. <el-table-column prop="birthDate" align="center" label="出生日期" min-width="80">
  335. <template slot-scope="scope">
  336. <div>{{ scope.row.birthDate ? moment(new Date(scope.row.birthDate)).format('yyyy-MM-DD') : '' }}</div>
  337. </template>
  338. </el-table-column>
  339. <el-table-column prop="age" align="center" label="年龄" min-width="40" />
  340. <el-table-column prop="customerOrgParentName" align="center" label="单位" min-width="150" />
  341. <el-table-column prop="customerOrgName" align="center" label="部门" min-width="120" />
  342. <el-table-column prop="telephone" align="center" label="电话" min-width="100" />
  343. <el-table-column prop="mobileTelephone" align="center" label="手机" min-width="100" />
  344. <el-table-column prop="creatorName" align="center" label="登记人员" min-width="80" />
  345. <el-table-column prop="creationTime" align="center" label="登记日期" min-width="80">
  346. <template slot-scope="scope">
  347. <div>{{ scope.row.birthDate ? moment(new Date(scope.row.creationTime)).format('yyyy-MM-DD') : '' }}
  348. </div>
  349. </template>
  350. </el-table-column>
  351. <!--
  352. "patientRegisterNo": "T4724",
  353. "patientId": "3a0eeeeb-55b6-86d7-a578-a9c9e332e7ed",
  354. "medicalTimes": 1,
  355. "customerOrgId": "3a0eeeeb-5647-6fee-6052-c3c8cde65b92",
  356. "customerOrgGroupId": "3a0e77cf-dfb7-2c35-1310-982136ca6c0c",
  357. "medicalPackageId": null,
  358. "patientName": "刘一",
  359. "sexId": "M",
  360. "birthDate": "10/1/1967",
  361. "age": 57,
  362. "jobCardNo": null,
  363. "medicalCardNo": null,
  364. "maritalStatusId": "9",
  365. "medicalTypeId": null,
  366. "personnelTypeId": null,
  367. "jobPost": null,
  368. "jobTitle": null,
  369. "photo": null,
  370. "salesman": null,
  371. "sexHormoneTermId": null,
  372. "interposeMeasure": null,
  373. "medicalConclusionId": "00000000-0000-0000-0000-000000000000",
  374. "reportPrintTimes": 0,
  375. "isUpload": "N",
  376. "completeFlag": "0",
  377. "isMedicalStart": "N",
  378. "medicalStartDate": "11/16/2023",
  379. "isRecoverGuide": "N",
  380. "summaryDate": "",
  381. "summaryDoctor": null,
  382. "isAudit": "N",
  383. "auditDoctor": null,
  384. "auditDate": "",
  385. "isLock": "N",
  386. "isNameHide": "N",
  387. "isPhoneFollow": "N",
  388. "isVip": "N",
  389. "thirdInfo": null,
  390. "guidePrintTimes": null,
  391. "remark": null,
  392. "medicalCenterId": "68f2d834-2bf0-4978-ad54-d2133c12a333",
  393. "customerOrgRegisterId": "3a0d5dfa-3e3f-b781-6d82-779e872d1b2a",
  394. "patientNo": "T4719",
  395. "patientPassword": "",
  396. "displayName": "刘一",
  397. "nationId": null,
  398. "birthPlaceId": null,
  399. "idNo": null,
  400. "postalCode": null,
  401. "email": null,
  402. "telephone": "15510826***",
  403. "mobileTelephone": null,
  404. "address": null,
  405. "customerOrgName": "部1",
  406. "customerOrgParentId": "3a0c5101-a6a6-e48a-36ec-33e7567a99e6",
  407. "customerOrgParentName": "神豚集团",
  408. "creatorName": "",
  409. "lastModifierName": "",
  410. "lastModificationTime": "2023-11-17T18:05:53.63381",
  411. "lastModifierId": "3a0c4180-107c-0c89-b25b-0bd34666dcec",
  412. "creationTime": "2023-11-17T18:05:53.633769",
  413. "creatorId": "3a0c4180-107c-0c89-b25b-0bd34666dcec",
  414. "id": "3a0eeeeb-565d-8a44-a2b7-a1c81cf43f2d"
  415. -->
  416. </el-table>
  417. </div>
  418. </div>
  419. <span slot="footer" class="dialog-footer">
  420. <div style="display: flex;justify-content: space-between;">
  421. <div style="display: flex;">
  422. <el-button class="commonbutton" type="primary" @click="btnChoose('prList', 'all')">全选</el-button>
  423. <el-button class="commonbutton" type="primary" @click="btnChoose('prList')">取消全选</el-button>
  424. </div>
  425. <div style="display: flex;">
  426. <el-button class="commonbutton" type="primary" @click="seq--">上一步</el-button>
  427. <el-button class="commonbutton" type="primary" @click="seq++">下一步</el-button>
  428. <el-button class="commonbutton" @click="seq = -1">关闭</el-button>
  429. </div>
  430. </div>
  431. </span>
  432. </el-dialog>
  433. <el-dialog title="选择单位" :visible.sync="dialogGroup.oldMansOpts" width="700px" :show-close="false"
  434. :close-on-click-modal="false"> <!--:append-to-body="true" -->
  435. <div style="height:400px;">
  436. <div style="margin-top: -10px;margin-left: 20px;">
  437. 如果是新单位或部门选择的病人将直接导入该单位而不是其子单位
  438. </div>
  439. <div style="display: flex;margin:20px;">
  440. <div style="margin:7px 0;">
  441. <el-radio v-model="newCustomerOrgFlag" :label="false">单位或部门不变</el-radio>
  442. <el-radio v-model="newCustomerOrgFlag" :label="true">新单位或部门</el-radio>
  443. </div>
  444. <div style="margin-left:5px;" v-if="newCustomerOrgFlag">
  445. <el-cascader v-model="customerOrgIds" :options="customerOrgTree" popper-class="example" style="width:260px;"
  446. @change="changeCustomerOrg" filterable
  447. :props="{ checkStrictly: true, expandTrigger: 'hover', ...customerOrg.treeprops, }"
  448. :show-all-levels="true" size="small">
  449. </el-cascader>
  450. </div>
  451. </div>
  452. <div style="margin-top: 20px;margin-left:20px;">
  453. <span>单位体检次数</span>
  454. <el-select v-model="customerOrgRegister" placeholder="次数" style="width: 80px;" size="small" value-key="id">
  455. <el-option v-for="item in customerOrgRegisterList" :key="item.id" :label="item.medicalTimes"
  456. :value="item" />
  457. </el-select>
  458. </div>
  459. <div style="margin-top: 20px;margin-left:20px;">
  460. <span>单位体检分组</span>
  461. <el-select v-model="curGroup" filterable clearable value-key="id" style="width:192px;" placeholder="请选择分组"
  462. size="small">
  463. <el-option v-for="item in groups" :key="item.id" :label="item.displayName" :value="item" />
  464. </el-select>
  465. </div>
  466. <div style="margin-top:20px;margin-left:20px;">
  467. <span>登记状态</span>
  468. <el-radio v-model="dataImportOpts.completeFlag" label="0">预登记</el-radio>
  469. <el-radio v-model="dataImportOpts.completeFlag" label="1">正式登记</el-radio>
  470. </div>
  471. <div style="margin-top:20px;margin-left:20px;">
  472. <span>支付方式</span>
  473. <el-select v-model="payTypeFlag" placeholder="请选择" style="width: 130px" size="small">
  474. <el-option v-for="item in dict.payType" :key="item.id" :label="item.displayName" :value="item.id" />
  475. </el-select>
  476. </div>
  477. </div>
  478. <span slot="footer" class="dialog-footer">
  479. <el-button class="commonbutton" type="primary" @click="seq--">上一步</el-button>
  480. <el-button class="commonbutton" type="primary" @click="btnImportFromDataBase">确定导入</el-button>
  481. <el-button class="commonbutton" @click="seq = -1">关闭</el-button>
  482. </span>
  483. </el-dialog>
  484. <!-- 通用进度条 -->
  485. <el-dialog title="数据处理中……" :visible.sync="elProgress.display" width="700px" height="400" :show-close="false"
  486. :close-on-click-modal="false" :append-to-body="true">
  487. <ElProgressOCX />
  488. </el-dialog>
  489. </div>
  490. </div>
  491. </template>
  492. <script>
  493. import moment from "moment"
  494. import { mapState, mapActions } from "vuex";
  495. import { read, readFile, utils } from "xlsx";
  496. import FileSaver from 'file-saver';
  497. import { getapi, postapi, putapi, deletapi } from "@/api/api";
  498. import { getPagePriv, checkPagePriv, deepCopy, arrayExistObj, arrayFilter, dddw, tcdate } from '../../utlis/proFunc';
  499. import ElProgressOCX from "../../components/report/ElProgressOCX.vue";
  500. export default {
  501. components: {
  502. ElProgressOCX,
  503. },
  504. data() {
  505. return {
  506. pagePriv: {
  507. routeUrlorPageName: 'patientRegisterBatch', //当前页面归属路由或归属页面权限名称
  508. privs: [] // 页面权限
  509. },
  510. customerOrgTree: [],
  511. customerOrgIds: [], //选中单位节点
  512. customerOrgRegisterList: [], //体检次数列表
  513. customerOrgRegister: {}, //体检次数
  514. peisid: null,
  515. startPoint: -1, // 多选起点 -1 表示未选择
  516. endPoint: -1, // 多选终点 -1 表示未选择
  517. rClickRow: null, //右击的行
  518. rClickColumn: null, //右击的列(预留)
  519. dialogGroup: {
  520. mode: true, //选模式 10 开始 文件导入,20开始 从数据库中导入
  521. fileReadme: false, //导入EXCEL注意事项
  522. fileChoose: false, //选择文件
  523. fileDataOpr: false, //文件数据分析操作
  524. fileDataOpts: false, //文件数据导入前参数设定
  525. query: false, //单位查询条件
  526. oldMansChoose: false, //选择历史数据导入
  527. oldMansOpts: false, //历史数据导入前参数设定
  528. },
  529. oldSeq: -2, //旧的步骤(辅助区分上一步,下一步)
  530. seq: 0, //当前显示窗口
  531. mode: '10', //模式 10 开始 文件导入,20开始 从数据库中导入 ,30 开始职业病
  532. excelCols: [{ dispLabel: '', val: '', dataLabel: '' }], //excel数据列名 {dispLabel:'',val:'',dataLabel:''}
  533. importCols: [], //实际导入的列(即有设置与 dataCols 匹配的列)
  534. excelData: [], //excel表格数据
  535. choosedData: [], // 选中的待导入的数据
  536. dataCols: [
  537. { dispLabel: '不设置', val: '' },
  538. { dispLabel: '工卡号', val: 'jobCardNo' },
  539. { dispLabel: '部门', val: 'departmentName' },
  540. { dispLabel: '分组', val: 'customerOrgGroupName' },
  541. { dispLabel: '姓名', val: 'patientName' },
  542. { dispLabel: '性别', val: 'sexName' },
  543. { dispLabel: '年龄', val: 'age' },
  544. { dispLabel: '出生日期', val: 'birthDate' },
  545. { dispLabel: '婚姻状况', val: 'maritalStatusName' },
  546. { dispLabel: '民族', val: 'nationName' },
  547. { dispLabel: '身份证号', val: 'idNo' },
  548. { dispLabel: '体检卡号', val: 'medicalCardNo' },
  549. { dispLabel: '电话', val: 'telephone' },
  550. { dispLabel: '手机', val: 'mobileTelephone' },
  551. { dispLabel: '电子邮件', val: 'email' },
  552. { dispLabel: '邮编', val: 'postalCode' },
  553. { dispLabel: '地址', val: 'address' },
  554. { dispLabel: '职务', val: 'jobPost' },
  555. { dispLabel: '职称', val: 'jobTitle' },
  556. { dispLabel: '人员类别', val: 'personnelTypeName' },
  557. { dispLabel: '体检类别', val: 'medicalTypeName' },
  558. { dispLabel: '工种', val: 'jobType' },
  559. { dispLabel: '检查类别', val: 'ocCheckTypeName' },
  560. { dispLabel: '接害因素', val: 'poisons' },
  561. { dispLabel: '备注', val: 'remark' },
  562. { dispLabel: '介绍人', val: 'salesman' },
  563. { dispLabel: '支付方式', val: 'payTypeFlag' },
  564. ],
  565. masterCols:{}, // 批量导入必填的项目
  566. tableData: [], //导入数据状态显示
  567. workBook: null, //EXCEL 工作薄
  568. sheetNames: [], //EXCEL 工作薄中的表单 {sheetName:}
  569. readDataOpts: {
  570. file: '', //选中的文件名
  571. sheetNameChoosed: '', //当前选中的表格
  572. titleRow: 1, //标题行
  573. },
  574. readDataOptsInit: {},
  575. dataImportOpts: {
  576. customerOrgId: '', //单位ID
  577. nameType: '2', //同名病人处理(1.同名病人提示,只要存在同名就提示 2.本单位同名提示,单位内部同名就提示 3.不提示,所有数据创建)
  578. completeFlag: '0', //完成标志 0:预登记 1:未检 2:部份已检 3:已总检 默认未检
  579. isAutoCreateDepartment: true, // 是否自动创建部门 Y N( N:按名字查找部门,如果未找到就提示 Y:未找到就创建)
  580. isAutoCreatePatientNo: false, // 工卡号作为档案号 Y/N (根据工卡号生成,可以指定起始位置跟位数)
  581. cardStartNum: 1,
  582. cardLength: 6,
  583. startRow: 0, //从 excelData 的第几行开始导入
  584. },
  585. dataImportOptsInit: {},
  586. dialogSameMan: false, //同名人员确认窗口
  587. sameMans: [], //同名人员列表
  588. choosedSameMan: {}, // 当前选中同名人员信息
  589. query: { //单位查询条件
  590. customerOrgIds: [],
  591. customerOrgId: '',
  592. customerOrgRegisterList: [],
  593. customerOrgRegister: {},
  594. customerOrgRegisterId: '',
  595. startDate: null,
  596. endDate: null,
  597. startPatientNo: '',
  598. endPatientNo: '',
  599. patientName: '',
  600. sexId: 'A',
  601. completeFlag: '',
  602. },
  603. prList: [], //查询出符合条件的历史档案人员信息
  604. groups: [], //体检分组列表
  605. curGroup: null, //当前选中要导入的分组 {}
  606. newCustomerOrgFlag: false, // [false]单位或部门不变 or [true]新单位或部门
  607. payTypeFlag: '1', // 默认单位
  608. };
  609. },
  610. //组件创建完成,一般页面初始布局放在这里
  611. created() {
  612. //获取用户当前页面的权限
  613. let userPriv = window.sessionStorage.getItem('userPriv')
  614. if (userPriv) this.pagePriv.privs = deepCopy(getPagePriv(this.pagePriv.routeUrlorPageName))
  615. if (!checkPagePriv(this.pagePriv.privs, '导入')) this.seq = -1
  616. this.peisid = window.sessionStorage.getItem('peisid');
  617. if (!this.peisid || this.peisid == 'null') {
  618. this.seq = -1
  619. }
  620. this.readDataOptsInit = Object.assign({}, this.readDataOpts)
  621. this.dataImportOptsInit = Object.assign({}, this.dataImportOpts)
  622. },
  623. //页面挂载完成,一般页面渲染数据放在这里
  624. mounted() {
  625. this.dictInit()
  626. },
  627. computed: {
  628. ...mapState(["window", "dict", "elProgress", "patientRegister", "customerOrg"]),
  629. },
  630. methods: {
  631. dddw, moment, checkPagePriv,
  632. dictInit() {
  633. // 获取单位列表树
  634. this.getCustomerOrgTree()
  635. //性别(查询 仅档案用)
  636. getapi("/api/app/sex").then((res) => {
  637. if (res.code == 1) {
  638. this.dict.sex = res.data;
  639. }
  640. });
  641. // 获取系统参数 -- 人员登记必填列
  642. postapi('/api/app/SysParmValue/GetSysParmValueBySysParmId', { sysParmId: 'patient_register_required_field' })
  643. .then(res => {
  644. if (res.code > -1) {
  645. try {
  646. this.masterCols = JSON.parse(res.data)
  647. } catch (error) {
  648. console.error(error)
  649. }
  650. }
  651. })
  652. .finally(() => {
  653. this.masterCols.patientName = "姓名"
  654. })
  655. },
  656. //清空进度数据数据
  657. clearProcess() {
  658. let elo = document.getElementById('fileNames')
  659. if(elo) elo.value = ''; // 清空选择的文件
  660. this.workBook = null //EXCEL 工作薄
  661. this.sheetNames = [] //EXCEL 工作薄中的表单 {sheetName:}
  662. this.readDataOpts = Object.assign({}, this.readDataOptsInit)
  663. this.dataImportOpts = Object.assign({}, this.dataImportOptsInit)
  664. this.customerOrgIds = [] //选中单位节点
  665. this.customerOrgRegisterList = [] //体检次数列表
  666. this.customerOrgRegister = {} //体检次数
  667. this.startPoint = -1 // 多选起点 -1 表示未选择
  668. this.endPoint = -1 // 多选终点 -1 表示未选择
  669. },
  670. // 获取单位列表树
  671. getCustomerOrgTree() {
  672. getapi("/api/app/customerorg/getbycodeall?IsHidePerson=1").then((res) => {
  673. // console.log("res.data", res.data);
  674. if (res.code != -1) {
  675. this.customerOrgTree = res.data;
  676. let lfind = arrayExistObj(this.customerOrgTree, 'id', this.dict.personOrgId)
  677. if (lfind > -1) this.customerOrgTree.splice(lfind, 1)
  678. tcdate(this.customerOrgTree)
  679. }
  680. });
  681. },
  682. //选择单位
  683. changeCustomerOrg(v) {
  684. this.chooseCustomerOrg(v)
  685. },
  686. //选择单位查询条件
  687. changeQueryCustomerOrg(v) {
  688. this.chooseCustomerOrg(v, 'query')
  689. },
  690. chooseCustomerOrg(v, obj) {
  691. let id = ''
  692. if (typeof v == 'string') {
  693. id = v
  694. } else {
  695. id = v[0]
  696. }
  697. getapi(
  698. `/api/app/customerorgregister/getlistincustomerorgid?CustomerOrgId=${id}`
  699. ).then((res) => {
  700. if (res.code != -1) {
  701. if (obj == 'query') {
  702. this.query.customerOrgRegisterList = res.data
  703. if (this.query.customerOrgRegisterList.length > 0) {
  704. this.query.customerOrgRegister = this.query.customerOrgRegisterList[this.query.customerOrgRegisterList.length - 1];
  705. } else {
  706. this.query.customerOrgRegister = {};
  707. // this.customerOrgGroups = [];
  708. }
  709. }
  710. this.customerOrgRegisterList = arrayFilter(res.data, 'isComplete', 'N') //不显示已完成的体检次数
  711. if (this.customerOrgRegisterList.length > 0) {
  712. this.customerOrgRegister = this.customerOrgRegisterList[this.customerOrgRegisterList.length - 1];
  713. // this.getCustomerOrgGroup(this.customerOrgRegister.id);
  714. } else {
  715. this.customerOrgRegister = {};
  716. // this.customerOrgGroups = [];
  717. }
  718. }
  719. });
  720. },
  721. //第一次点下一步
  722. btnFirst() {
  723. if (!this.peisid || this.peisid == 'null') {
  724. this.$message.warning("该用户未选归属体检中心,不能执行此操作!");
  725. return
  726. }
  727. this.seq = parseInt(this.mode)
  728. },
  729. // 导入过程 上一步,下一步
  730. async btnProcess(seq) {
  731. let keys = Object.keys(this.dialogGroup)
  732. let count = 0 //选中待导入的人员数
  733. if (seq == 9 || seq == 29) {
  734. this.workBook = null
  735. this.sheetNameChoosed = ''
  736. seq = 0
  737. }
  738. if (seq == 19) seq = 0
  739. // console.log('keys',keys)
  740. switch (seq) {
  741. case -1:
  742. //关闭所有弹窗
  743. keys.forEach(e => {
  744. this.dialogGroup[e] = false
  745. })
  746. this.clearProcess()
  747. break;
  748. case 0:
  749. //显示 选择导入方式
  750. keys.forEach(e => {
  751. if (e == 'mode') {
  752. this.dialogGroup[e] = true
  753. } else {
  754. this.dialogGroup[e] = false
  755. }
  756. })
  757. this.excelCols = []
  758. this.tableData = []
  759. this.prList = []
  760. this.startPoint = -1 // 多选起点 -1 表示未选择
  761. this.endPoint = -1 // 多选终点 -1 表示未选择
  762. break;
  763. case 10:
  764. case 30:
  765. //显示 EXCEL 导入
  766. keys.forEach(e => {
  767. if (e == 'fileReadme') {
  768. this.dialogGroup[e] = true
  769. } else {
  770. this.dialogGroup[e] = false
  771. }
  772. })
  773. break;
  774. case 11:
  775. case 31:
  776. //显示 文件选择 窗口
  777. keys.forEach(e => {
  778. if (e == 'fileChoose') {
  779. this.dialogGroup[e] = true
  780. } else {
  781. this.dialogGroup[e] = false
  782. }
  783. })
  784. break;
  785. case 12:
  786. case 32:
  787. // 从后面退回时,无需读数据
  788. if (this.oldSeq < seq) {
  789. if (!this.readData()) {
  790. this.seq--
  791. break;
  792. }
  793. }
  794. //显示 数据分析操作 窗口
  795. keys.forEach(e => {
  796. if (e == 'fileDataOpr') {
  797. this.dialogGroup[e] = true
  798. } else {
  799. this.dialogGroup[e] = false
  800. }
  801. })
  802. break;
  803. case 13:
  804. case 33:
  805. count = 0
  806. this.excelData.forEach(e => {
  807. if (e.choosed) count++
  808. })
  809. if (count == 0) {
  810. this.$message.warning("未选中要导入的记录")
  811. this.seq--
  812. break;
  813. }
  814. //显示 文件数据导入前参数设定 窗口
  815. keys.forEach(e => {
  816. if (e == 'fileDataOpts') {
  817. this.dialogGroup[e] = true
  818. } else {
  819. this.dialogGroup[e] = false
  820. }
  821. })
  822. break;
  823. case 20:
  824. //显示 单位查询条件 导入
  825. keys.forEach(e => {
  826. if (e == 'query') {
  827. this.dialogGroup[e] = true
  828. } else {
  829. this.dialogGroup[e] = false
  830. }
  831. })
  832. break;
  833. case 21:
  834. //显示 选择要导入的 档案人员
  835. if (this.oldSeq < seq) {
  836. if (!await this.getPrList()) {
  837. console.log('this.seq break', this.seq)
  838. this.seq--
  839. break
  840. }
  841. }
  842. keys.forEach(e => {
  843. if (e == 'oldMansChoose') {
  844. this.dialogGroup[e] = true
  845. } else {
  846. this.dialogGroup[e] = false
  847. }
  848. })
  849. break;
  850. case 22:
  851. //显示 选择新的体检单位及分组
  852. count = 0
  853. this.prList.forEach(e => {
  854. if (e.choosed) count++
  855. })
  856. if (count == 0) {
  857. this.$message.warning("未选中要导入的记录")
  858. this.seq--
  859. break;
  860. }
  861. keys.forEach(e => {
  862. if (e == 'oldMansOpts') {
  863. this.dialogGroup[e] = true
  864. } else {
  865. this.dialogGroup[e] = false
  866. }
  867. })
  868. break;
  869. default:
  870. break;
  871. }
  872. },
  873. //导入完后,导入状态显示
  874. importRowClassName({ row, rowIndex }) {
  875. if (row.importState == '导入失败') {
  876. return "danger";
  877. } else {
  878. return "";
  879. }
  880. },
  881. //多选 颜色标记
  882. handleRowClassName({ row, rowIndex }) {
  883. if (row.choosed) {
  884. return "current-row";
  885. } else {
  886. return "";
  887. }
  888. },
  889. // 导入完后,状态统计
  890. getSummaries(param) {
  891. const { columns, data } = param;
  892. const sumCol = [2]; //需合计的列
  893. const sums = [];
  894. let success = 0, fail = 0;
  895. columns.forEach((column, index) => {
  896. //显示合计列
  897. if (index === 1) {
  898. sums[index] = "导入合计";
  899. return;
  900. }
  901. //不合计的列
  902. if (sumCol.indexOf(index) == -1) {
  903. sums[index] = "";
  904. return;
  905. }
  906. data.forEach((item) => {
  907. console.log('item,column.property',item,column.property)
  908. if (item[column.property]) {
  909. fail++
  910. } else {
  911. success++
  912. }
  913. });
  914. });
  915. sums[2] = `成功:${success} 条,失败:${fail} 条。`
  916. return sums;
  917. },
  918. //清除所选文件
  919. fileGetFocus(e) {
  920. console.log('fileGetFocus(e)', e)
  921. e.value = '' //未起作用的
  922. // e.target.files = []
  923. },
  924. // 获取选择的文件
  925. changeFileChoose(e) {
  926. if (e.target.files.length <= 0) return;
  927. // console.log('file',e.target.files[0])
  928. this.readDataOpts.file = e.target.files[0];
  929. // 调用导入Excel文件的方法
  930. // File {name: 'vulkan-1.dll',
  931. // console.log('file',file,file.type)
  932. let fileName = this.readDataOpts.file.name.split('.')
  933. let fileNameExt = fileName[fileName.length - 1].toLowerCase()
  934. if (fileNameExt != 'xls' && fileNameExt != 'xlsx') {
  935. this.$message.warning("你选的文件可能不是标准的Excel文件!")
  936. }
  937. this.readFile(this.readDataOpts.file);
  938. },
  939. //sheetjs 读取文件
  940. readFile(file) {
  941. const reader = new FileReader();
  942. // reader.readAsArrayBuffer(file);
  943. // 定义读取文件
  944. reader.onload = (e) => {
  945. let data = e.target.result;
  946. // let typedArray = new Uint8Array(data);
  947. // var workBook = read(typedArray,{type:'array'})
  948. // this.workBook = read(data,{type:'binary',cellDates:true}) //日期将转成 标准 日期格式,显示会 undefined
  949. this.workBook = read(data, { type: 'binary' })
  950. // var workBook = readFile(file); //后端读法
  951. this.sheetNames = []
  952. this.workBook.SheetNames.forEach(e => {
  953. this.sheetNames.push({ sheetName: e })
  954. })
  955. this.$nextTick(() => {
  956. this.$refs['sheetNames'].setCurrentRow(this.sheetNames[0]);
  957. this.chooseSheetName(this.sheetNames[0])
  958. })
  959. }
  960. // 错误处理
  961. reader.onerror = function (event) {
  962. // 读取失败时执行的代码
  963. console.error("File could not be read!" + event.target.error);
  964. };
  965. reader.readAsBinaryString(file);
  966. },
  967. //选择要导入的Excel表单名
  968. chooseSheetName(row) {
  969. this.readDataOpts.sheetNameChoosed = row.sheetName
  970. },
  971. //读取数据
  972. readData() {
  973. let ret = 1
  974. if (!this.readDataOpts.file || !this.workBook || !this.readDataOpts.sheetNameChoosed) {
  975. this.$message.warning("请选择文件及要导入的表格")
  976. return 0
  977. }
  978. if (this.readDataOpts.titleRow <= 0) {
  979. this.$message.warning("标题行不能小于1")
  980. return 0
  981. }
  982. let worksheet = this.workBook.Sheets[this.readDataOpts.sheetNameChoosed];
  983. //分析标题信息
  984. let head = utils.sheet_to_json(worksheet, { header: 1 });
  985. this.excelCols = []
  986. head[this.readDataOpts.titleRow - 1].forEach(e => {
  987. let lfind = arrayExistObj(this.dataCols, 'dispTitle', e), val = '', dataLabel = '';
  988. if (lfind > -1) {
  989. val = this.dataCols[lfind].val
  990. dataLabel = this.dataCols[lfind].dataLabel
  991. }
  992. this.excelCols.push({
  993. dispLabel: e,
  994. val,
  995. dataLabel
  996. })
  997. })
  998. //console.log('head,',head,this.excelCols)
  999. this.excelData = utils.sheet_to_json(worksheet, { raw: false, range: this.readDataOpts.titleRow - 1 }); //raw:false,range:1 从第1行开始读取
  1000. this.excelData.forEach((e, index) => {
  1001. e.choosed = false;
  1002. e.index = index;
  1003. e.id = 'excelData' + index;
  1004. });
  1005. //console.log('this.excelCols',this.excelCols)
  1006. // console.log('sheet_to_json excelData',this.excelData)
  1007. // 导入后,批量分析Excel列 与 数据字段 的匹配关系
  1008. this.parseExcelData()
  1009. return ret
  1010. },
  1011. //选择要导入的数据
  1012. chooseDataImport(row) {
  1013. // console.log("this.excelData",this.excelData);
  1014. // 按住了shift键
  1015. if (this.window.shift) {
  1016. //清除所有选择
  1017. this.excelData.forEach((e, index) => {
  1018. e.choosed = false;
  1019. e.index = index;
  1020. });
  1021. if (this.startPoint == -1) {
  1022. this.excelData[row.index].choosed = true;
  1023. this.startPoint = row.index;
  1024. } else {
  1025. if (this.startPoint > row.index) {
  1026. for (let i = row.index; i <= this.startPoint; i++) {
  1027. this.excelData[i].choosed = true;
  1028. }
  1029. } else if (this.startPoint <= row.index) {
  1030. for (let i = this.startPoint; i <= row.index; i++) {
  1031. this.excelData[i].choosed = true;
  1032. }
  1033. }
  1034. }
  1035. } else if (this.window.ctrl) { // 按住了ctrl 键
  1036. this.excelData[row.index].choosed = true;
  1037. if (this.startPoint == -1) {
  1038. this.startPoint = row.index;
  1039. }
  1040. } else {
  1041. // 未按住了ctrl 、shift 键
  1042. //清除所有选择
  1043. console.log("清除所有选择");
  1044. this.excelData.forEach((e, index) => {
  1045. e.choosed = false;
  1046. e.index = index;
  1047. });
  1048. // console.log(this.excelData,row.index);
  1049. // console.log(this.excelData[row.index].choosed);
  1050. this.excelData[row.index].choosed = true;
  1051. this.startPoint = row.index;
  1052. }
  1053. },
  1054. // 全选(取消全选)
  1055. btnChoose(refName, type) {
  1056. let choosed = false
  1057. if (type && type == 'all') {
  1058. choosed = true
  1059. }
  1060. this[refName].forEach(e => {
  1061. e.choosed = choosed
  1062. if (choosed) {
  1063. this.$refs[refName].setCurrentRow(e)
  1064. }
  1065. })
  1066. if (!choosed) {
  1067. this.$refs[refName].setCurrentRow()
  1068. }
  1069. },
  1070. //右击标题
  1071. headerContextmenu(column, event) {
  1072. let chooseCol = column.minWidth - 100
  1073. let items = [] //菜单
  1074. this.dataCols.forEach(e => {
  1075. items.push({
  1076. label: e.dispLabel,
  1077. onClick: () => {
  1078. this.setColumn(chooseCol, e)
  1079. },
  1080. })
  1081. })
  1082. //右击显示的菜单
  1083. this.$contextmenu({
  1084. items,
  1085. event,
  1086. //x: event.clientX,
  1087. //y: event.clientY,
  1088. customClass: "custom-class",
  1089. zIndex: 30000, //够大再能在最上面显示
  1090. minWidth: 80,
  1091. height: 20
  1092. });
  1093. return false;
  1094. },
  1095. //设置真实数据字段列
  1096. setColumn(oldColNum, newColObj) {
  1097. // console.log('oldColNum,newColObj',oldColNum,newColObj)
  1098. //如果数据字段已设置过,则将之前设置的先清空
  1099. if (newColObj.dispLabel != "不设置") {
  1100. let lfind = arrayExistObj(this.excelCols, 'dataLabel', newColObj.dispLabel)
  1101. if (lfind > -1) {
  1102. this.excelCols[lfind].dataLabel = ''
  1103. this.excelCols[lfind].val = ''
  1104. }
  1105. }
  1106. this.excelCols[oldColNum].dataLabel = newColObj.dispLabel
  1107. this.excelCols[oldColNum].val = newColObj.val
  1108. // console.log('newColObj.val',newColObj.val)
  1109. let tempDate = ''
  1110. if (newColObj.val == 'birthDate') {
  1111. this.excelData.forEach(e => {
  1112. tempDate = e[this.excelCols[oldColNum].dispLabel]
  1113. // console.log('birthDate',tempDate)
  1114. e[this.excelCols[oldColNum].dispLabel] = tempDate ? moment(new Date(tempDate)).format('yyyy-MM-DD') : ''
  1115. })
  1116. }
  1117. },
  1118. // 选择EXCEL文件后,批量分析Excel列 与 数据字段 的匹配关系
  1119. parseExcelData() {
  1120. let lfind = -1
  1121. this.excelCols.forEach((e, i) => {
  1122. lfind = arrayExistObj(this.dataCols, 'dispLabel', e.dispLabel)
  1123. if (lfind > -1) this.setColumn(i, this.dataCols[lfind])
  1124. });
  1125. },
  1126. // 确定导入数据库
  1127. btnImport() {
  1128. if (!this.customerOrgIds || this.customerOrgIds.length == 0) {
  1129. this.$message.warning("请选择单位")
  1130. return
  1131. }
  1132. if (!this.customerOrgRegister || !this.customerOrgRegister.id) {
  1133. this.$message.warning("请选择单位体检次数")
  1134. return
  1135. }
  1136. this.elProgress.display = true;
  1137. this.elProgress.percentage = 0;
  1138. this.importCols = []
  1139. this.excelCols.forEach(e => {
  1140. if (e.val) {
  1141. this.importCols.push(e)
  1142. }
  1143. })
  1144. this.tableData = [] // 记录导入后结果状态
  1145. this.choosedData = [] //选中待导入的数据
  1146. this.excelData.forEach(e => {
  1147. if (e.choosed) this.choosedData.push(e)
  1148. });
  1149. //导入进行中
  1150. this.importing(this.dataImportOpts.startRow, this.dataImportOpts.nameType)
  1151. // 开始导入时,清除选择的 文件
  1152. document.getElementById('fileNames').value = '';
  1153. },
  1154. // 导入必填项验证
  1155. checkValide(body){
  1156. let msg = ''
  1157. // patientName,personnelTypeName,medicalTypeName,salesman
  1158. let keys = Object.keys(this.masterCols)
  1159. for (let i = 0; i < keys.length; i++) {
  1160. const key = keys[i];
  1161. switch (key) {
  1162. case 'patientName':
  1163. case 'name':
  1164. if(!body.patientName) msg = this.masterCols[key] + ' 未填值'
  1165. break;
  1166. case 'medicalTypeId': //体检类别
  1167. if(!body.medicalTypeName) msg = this.masterCols[key] + ' 未填值'
  1168. break;
  1169. case 'personnelTypeId': //人员类别
  1170. if(!body.personnelTypeName) msg = this.masterCols[key] + ' 未填值'
  1171. break;
  1172. case 'salesman': //介绍人
  1173. if(!body.salesman) msg = this.masterCols[key] + ' 未填值'
  1174. break;
  1175. default:
  1176. break;
  1177. }
  1178. if(msg) break;
  1179. }
  1180. return msg
  1181. },
  1182. //导入进行时
  1183. // startRow : 从第几行开始导入,同名判断交互时,续接导入
  1184. // startRowNameType : 续接导入的第1行,执行 同名判断模式, 3.不提示,按新人导入(前端不用管)
  1185. async importing(startRow, startRowNameType) {
  1186. let body = {}
  1187. for (let i = startRow; i < this.choosedData.length; i++) {
  1188. this.elProgress.percentage = Math.floor(
  1189. ((i + 1) * 100) / this.choosedData.length
  1190. );
  1191. // 将Excel的数据转换成接口的数据
  1192. body = this.excelDataToApiBody(this.choosedData[i])
  1193. if (i == startRow) body.nameType = startRowNameType
  1194. console.log(`this.choosedData[${i}],startRowNameType,body`)
  1195. // 判断是否必填:
  1196. let msg = this.checkValide(body)
  1197. if(msg){
  1198. this.tableData.push(Object.assign({ importState: '导入失败', importDes: msg }, this.choosedData[i]))
  1199. }else{
  1200. try {
  1201. // 同一人判断
  1202. if (this.choosedSameMan.patientNo) {
  1203. // 上一次循环已经判断是否同一人,此次循环不需再判断了
  1204. if (this.choosedSameMan.patientNo == '$newPatient$') {
  1205. body.nameType = '3'
  1206. } else {
  1207. body.patientNo = this.choosedSameMan.patientNo
  1208. }
  1209. } else if (startRowNameType != '3') {
  1210. let result = await this.isSamePatient(startRowNameType, body)
  1211. if (result.isContinue) {
  1212. if (result.err) {
  1213. this.tableData.push(Object.assign({ importState: '导入失败', importDes: result.err }, this.choosedData[i]))
  1214. }
  1215. } else {
  1216. this.dataImportOpts.startRow = i
  1217. break; // 跳出循环,重新从 i 开执行 this.importing
  1218. }
  1219. }
  1220. // 旧接口:/api/app/patientregister/createpatientregisterexcel
  1221. let res = await postapi('/api/app/patientregister/CreatePatientRegisterFromExcel', body)
  1222. this.choosedSameMan = {} // 清除选择同一人员的记录
  1223. if (res.code >= 0) {
  1224. this.tableData.push(Object.assign({ importState: '导入成功' }, this.choosedData[i]))
  1225. } else {
  1226. this.tableData.push(Object.assign({ importState: '导入失败', importDes: res.message }, this.choosedData[i]))
  1227. }
  1228. } catch (error) {
  1229. this.tableData.push(Object.assign({ importState: '导入失败', importDes: `${error}` }, this.choosedData[i]))
  1230. }
  1231. }
  1232. // 结束导入
  1233. if (i == this.choosedData.length - 1) {
  1234. this.elProgress.display = false;
  1235. this.seq = -1
  1236. }
  1237. }
  1238. },
  1239. // 同一人判断
  1240. async isSamePatient(startRowNameType, body) {
  1241. console.log('isSamePatient', startRowNameType, body)
  1242. let result = {
  1243. isContinue: true,
  1244. err: ''
  1245. }
  1246. let res
  1247. if (body.idNo) {
  1248. try {
  1249. res = await postapi('/api/app/patient/GetByIdNo', { idNo: body.idNo })
  1250. if (res.code < 0) {
  1251. result.err = `身份证号查重错误,原因:${res.message}`
  1252. return result
  1253. } else if (res.code == 1) {
  1254. body.patientNo = res.data.patientNo
  1255. return result
  1256. }
  1257. } catch (error) {
  1258. result.err = `身份证号查重错误,原因:${error}`
  1259. return result
  1260. }
  1261. }
  1262. // 没有身份证号或身份证号未找到同名人员时,按姓名查重
  1263. let url, localBody = {
  1264. customerOrgId: body.customerOrgId,
  1265. name: body.patientName
  1266. }
  1267. switch (startRowNameType) {
  1268. case '1':
  1269. case '2':
  1270. if (startRowNameType == '1') url = '/api/app/patientregister/GetSameNamePatient'
  1271. if (startRowNameType == '2') url = '/api/app/patientregister/GetCustomerOrgSameNamePatient'
  1272. res = await postapi(url, localBody)
  1273. if (res.code >= 0) {
  1274. if (res.data.length > 0) {
  1275. result.isContinue = false
  1276. this.sameMans = res.data
  1277. this.dialogSameMan = true
  1278. }
  1279. } else {
  1280. result.err = `${startRowNameType == '2' ? '同单位内' : ''}同名查重错误,原因:${res.message}`
  1281. }
  1282. break;
  1283. default:
  1284. break;
  1285. }
  1286. return result
  1287. // if (this.choosedSameMan.patientNo) {
  1288. // body.patientNo = this.choosedSameMan.patientNo
  1289. // // body.patientId = this.choosedSameMan.patientId
  1290. // this.choosedSameMan = {} // 清除选择人员
  1291. // }
  1292. // try {
  1293. // switch (key) {
  1294. // case value:
  1295. // break;
  1296. // default:
  1297. // break;
  1298. // }
  1299. // { dispLabel: '姓名', val: 'patientName' },
  1300. // { dispLabel: '性别', val: 'sexName' },
  1301. // { dispLabel: '年龄', val: 'age' },
  1302. // { dispLabel: '出生日期', val: 'birthDate' },
  1303. // { dispLabel: '婚姻状况', val: 'maritalStatusName' },
  1304. // { dispLabel: '民族', val: 'nationName' },
  1305. // { dispLabel: '身份证号', val: 'idNo' },
  1306. },
  1307. //将Excel的数据转换成接口的数据
  1308. excelDataToApiBody(ExcelData) {
  1309. let body = {
  1310. customerOrgId: this.customerOrgIds[this.customerOrgIds.length - 1],
  1311. customerOrgRegisterId: this.customerOrgRegister.id,
  1312. medicalCenterId: this.peisid,
  1313. nameType: this.dataImportOpts.nameType,
  1314. completeFlag: this.dataImportOpts.completeFlag,
  1315. isAutoCreateDepartment: this.dataImportOpts.isAutoCreateDepartment ? 'Y' : 'N',
  1316. isAutoCreatePatientNo: this.dataImportOpts.isAutoCreatePatientNo ? 'Y' : 'N',
  1317. cardStartNum: this.dataImportOpts.cardStartNum,
  1318. cardLength: this.dataImportOpts.cardLength
  1319. }
  1320. this.excelCols.forEach(e => {
  1321. if (e.val) {
  1322. switch (e.val) {
  1323. case 'age':
  1324. if (ExcelData[e.dispLabel]) body[e.val] = parseInt(ExcelData[e.dispLabel])
  1325. break;
  1326. // case 'birthDate':
  1327. // if(ExcelData[e.dispLabel]) body[e.val] = moment(new Date(ExcelData[e.dispLabel])).format('yyyy-MM-DD')
  1328. // break;
  1329. case 'poisons':
  1330. if (ExcelData[e.dispLabel]) body[e.val] = ExcelData[e.dispLabel].replaceAll(",", ",").split(",")
  1331. break;
  1332. default:
  1333. body[e.val] = ExcelData[e.dispLabel]
  1334. break;
  1335. }
  1336. }
  1337. })
  1338. if(this.seq > 30){
  1339. body.isOccupationalDisease = 'Y'
  1340. body.isDefaultMedicalType = 'Y'
  1341. }
  1342. return body
  1343. },
  1344. //选中同名人员档案
  1345. rowClickSameMan(row) {
  1346. this.choosedSameMan = deepCopy(row)
  1347. },
  1348. // 同名人员,按档案人员导入
  1349. btnOldMan() {
  1350. if (!this.choosedSameMan.patientNo) {
  1351. this.$message.warning("请选择要导入的档案人员")
  1352. return
  1353. }
  1354. this.importing(this.dataImportOpts.startRow, this.dataImportOpts.nameType)
  1355. this.dialogSameMan = false
  1356. },
  1357. // 同名人员,按新人方式导入
  1358. btnNewMan() {
  1359. this.choosedSameMan = { patientNo: '$newPatient$' } // 约定按新人导入
  1360. this.importing(this.dataImportOpts.startRow, this.dataImportOpts.nameType)
  1361. this.dialogSameMan = false
  1362. },
  1363. // 查询档案人员
  1364. async getPrList() {
  1365. let ret = false
  1366. if (!this.query.customerOrgIds || this.query.customerOrgIds.length == 0) {
  1367. this.$message.warning("请选择单位或部门")
  1368. return false
  1369. }
  1370. if (!this.query.customerOrgRegister || !this.query.customerOrgRegister.id) {
  1371. this.$message.warning("请选择单位体检次数")
  1372. return false
  1373. }
  1374. this.query.customerOrgId = this.query.customerOrgIds[this.query.customerOrgIds.length - 1]
  1375. this.query.customerOrgRegisterId = this.query.customerOrgRegister.id
  1376. let body = Object.assign({}, this.query)
  1377. delete body.customerOrgIds
  1378. delete body.customerOrgRegister
  1379. delete body.customerOrgRegisterList
  1380. if (!body.completeFlag) delete body.completeFlag
  1381. if (!body.patientName) delete body.patientName
  1382. if (!body.startPatientNo && !body.endPatientNo) {
  1383. delete body.startPatientNo
  1384. delete body.endPatientNo
  1385. } else if (!body.startPatientNo) {
  1386. this.$message.warning("请填写起始档案号")
  1387. return false
  1388. } else if (!body.endPatientNo) {
  1389. this.$message.warning("请填写截止档案号")
  1390. return false
  1391. }
  1392. if (!body.startDate && !body.endDate) {
  1393. delete body.startDate
  1394. delete body.endDate
  1395. } else if (!body.startDate) {
  1396. this.$message.warning("请填写起始登记日期")
  1397. return false
  1398. } else if (!body.endDate) {
  1399. this.$message.warning("请填写截止登记日期")
  1400. return false
  1401. } else {
  1402. body.startDate = moment(new Date(body.startDate)).format('yyyy-MM-DD')
  1403. body.endDate = moment(new Date(body.endDate)).format('yyyy-MM-DD')
  1404. }
  1405. const loading = this.$loading({
  1406. lock: true,
  1407. text: "Loading",
  1408. spinner: "el-icon-loading",
  1409. background: "rgba(0, 0, 0, 0.7)",
  1410. });
  1411. try {
  1412. let res = await postapi('/api/patientregister/getpatientregisterimportlist', body)
  1413. if (res.code != -1) {
  1414. this.prList = res.data
  1415. if (res.data.length == 0) {
  1416. this.$message.warning("没有符合条件的数据")
  1417. } else {
  1418. ret = true
  1419. }
  1420. }
  1421. } catch (error) {
  1422. //
  1423. }
  1424. loading.close()
  1425. return ret
  1426. },
  1427. //选择要导入的数据
  1428. rowClickPrList(row) {
  1429. // console.log("this.excelData",this.excelData);
  1430. // 按住了shift键
  1431. if (this.window.shift) {
  1432. //清除所有选择
  1433. this.prList.forEach((e, index) => {
  1434. e.choosed = false;
  1435. e.index = index;
  1436. });
  1437. if (this.startPoint == -1) {
  1438. this.prList[row.index].choosed = true;
  1439. this.startPoint = row.index;
  1440. } else {
  1441. if (this.startPoint > row.index) {
  1442. for (let i = row.index; i <= this.startPoint; i++) {
  1443. this.prList[i].choosed = true;
  1444. }
  1445. } else if (this.startPoint <= row.index) {
  1446. for (let i = this.startPoint; i <= row.index; i++) {
  1447. this.prList[i].choosed = true;
  1448. }
  1449. }
  1450. }
  1451. } else if (this.window.ctrl) { // 按住了ctrl 键
  1452. this.prList[row.index].choosed = true;
  1453. if (this.startPoint == -1) {
  1454. this.startPoint = row.index;
  1455. }
  1456. } else {
  1457. // 未按住了ctrl 、shift 键
  1458. //清除所有选择
  1459. console.log("清除所有选择");
  1460. this.prList.forEach((e, index) => {
  1461. e.choosed = false;
  1462. e.index = index;
  1463. });
  1464. // console.log(this.excelData,row.index);
  1465. // console.log(this.excelData[row.index].choosed);
  1466. this.prList[row.index].choosed = true;
  1467. this.startPoint = row.index;
  1468. }
  1469. },
  1470. //获取分组
  1471. getGroups(customerOrgRegisterId) {
  1472. ///api/app/customerorggroup/getlistinfilter?CustomerOrgRegisterId=3fa85f64-5717-4562-b3fc-2c963f66afa6
  1473. getapi(`/api/app/customerorggroup/getlistinfilter?CustomerOrgRegisterId=${customerOrgRegisterId}`).then(res => {
  1474. if (res.code != - 1) {
  1475. this.groups = res.data;
  1476. this.curGroup = null //清除已选分组
  1477. }
  1478. })
  1479. },
  1480. //确定从档案中导入数据
  1481. async btnImportFromDataBase() {
  1482. let customerOrgIds = []
  1483. let customerOrgId = ""
  1484. if (this.newCustomerOrgFlag) {
  1485. customerOrgIds = this.customerOrgIds
  1486. } else {
  1487. customerOrgIds = this.query.customerOrgIds
  1488. }
  1489. if (customerOrgIds && customerOrgIds.length > 0) customerOrgId = customerOrgIds[customerOrgIds.length - 1]
  1490. if (!customerOrgId) {
  1491. this.$message.warning("请选择新导入的体检单位或部门")
  1492. return
  1493. }
  1494. if (!this.curGroup || !this.customerOrgRegister) {
  1495. this.$message.warning("请选择新导入的体检次数与分组")
  1496. return
  1497. }
  1498. let body = {
  1499. customerOrgRegisterId: this.customerOrgRegister.id,
  1500. customerOrgGroupId: this.curGroup.id,
  1501. completeFlag: this.dataImportOpts.completeFlag,
  1502. payTypeFlag: this.payTypeFlag,
  1503. medicalCenterId: this.peisid,
  1504. }
  1505. //{
  1506. // "patientRegisterId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  1507. // "customerOrgId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  1508. // "customerOrgRegisterId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  1509. // "customerOrgGroupId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  1510. // "completeFlag": "string",
  1511. // "payTypeFlag": "string",
  1512. // "medicalCenterId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  1513. // }
  1514. this.elProgress.display = true
  1515. this.elProgress.percentage = 0
  1516. for (let i = 0; i < this.prList.length; i++) {
  1517. this.elProgress.percentage = Math.floor(((i + 1) * 100) / this.prList.length);
  1518. if (!this.prList[i].choosed) continue
  1519. body.patientRegisterId = this.prList[i].id
  1520. body.customerOrgId = this.newCustomerOrgFlag ? customerOrgId : this.prList[i].customerOrgId
  1521. try {
  1522. // 旧接口:/api/app/patientregister/createpatientregisterhistory
  1523. let res = await postapi('/api/app/patientregister/CreatePatientRegisterFromHistory', body)
  1524. if (res.code >= 0) {
  1525. this.tableData.push(Object.assign({ importState: '导入成功' }, this.prList[i]))
  1526. } else {
  1527. this.tableData.push(Object.assign({ importState: '导入失败', importDes: res.message }, this.prList[i]))
  1528. }
  1529. } catch (error) {
  1530. this.tableData.push(Object.assign({ importState: '导入失败', importDes: res.message }, this.prList[i]))
  1531. }
  1532. }
  1533. this.elProgress.display = false
  1534. this.seq = -1
  1535. },
  1536. //通用导出
  1537. btnExport(elId) {
  1538. let table = document.getElementById(elId);
  1539. let tableData = table.innerHTML
  1540. let fileName = moment(new Date()).format('yyyyMMDDHHmmss') + '.xls'
  1541. let blob = new Blob([tableData], { type: "text/plain;charset=utf-8" });
  1542. FileSaver.saveAs(blob, fileName);
  1543. },
  1544. },
  1545. watch: {
  1546. "seq": {
  1547. immediate: true, // 立即执行
  1548. // // deep: true, // 深度监听复杂类型内变化
  1549. handler(newVal, oldVal) {
  1550. console.log('watch:seq:', newVal, oldVal)
  1551. if (!oldVal && oldVal != 0) {
  1552. this.oldSeq = -2
  1553. } else {
  1554. this.oldSeq = oldVal
  1555. }
  1556. if (newVal != oldVal) {
  1557. this.btnProcess(newVal);
  1558. }
  1559. }
  1560. },
  1561. "readDataOpts.titleRow": {
  1562. // immediate: true, // 立即执行
  1563. // deep: true, // 深度监听复杂类型内变化
  1564. handler(newVal, oldVal) {
  1565. console.log('watch:readDataOpts.titleRow:', newVal, oldVal)
  1566. if (newVal && newVal != oldVal) {
  1567. if (this.seq == 11) this.readData()
  1568. }
  1569. }
  1570. },
  1571. //所选体检次数改变时,自动获取登记日期
  1572. "query.customerOrgRegister.id": {
  1573. // immediate: true, // 立即执行
  1574. // deep: true, // 深度监听复杂类型内变化
  1575. handler(newVal, oldVal) {
  1576. if (newVal && newVal != oldVal) {
  1577. this.query.startDate = new Date(this.query.customerOrgRegister.beginTime)
  1578. this.query.endDate = this.query.customerOrgRegister.isComplete == 'N' ? new Date() : new Date(this.query.customerOrgRegister.endTime)
  1579. }
  1580. }
  1581. },
  1582. //选体检新体检次数改变时,获取分组数据
  1583. "customerOrgRegister.id": {
  1584. // immediate: true, // 立即执行
  1585. // deep: true, // 深度监听复杂类型内变化
  1586. handler(newVal, oldVal) {
  1587. if (newVal && newVal != oldVal) {
  1588. this.getGroups(newVal)
  1589. }
  1590. }
  1591. },
  1592. },
  1593. };
  1594. </script>
  1595. <style scoped>
  1596. @import '../../assets/css/global_button.css';
  1597. @import '../../assets/css/global_card.css';
  1598. @import '../../assets/css/global_dialog.css';
  1599. @import '../../assets/css/global_form.css';
  1600. @import '../../assets/css/global_input.css';
  1601. @import '../../assets/css/global_table.css';
  1602. @import '../../assets/css/global_menu.css';
  1603. @import '../../assets/css/global.css';
  1604. .spanLeftClass {
  1605. margin-top: 6px;
  1606. width: 70px;
  1607. }
  1608. .spanMidClass {
  1609. text-align: center;
  1610. margin-top: 6px;
  1611. width: 50px;
  1612. }
  1613. /* type=number 显示微调按钮 */
  1614. ::v-deep input[type="number"]::-webkit-inner-spin-button,
  1615. input[type="number"]::-webkit-outer-spin-button {
  1616. -webkit-appearance: button !important;
  1617. margin: 0 -12px 0 0 !important;
  1618. }
  1619. ::v-deep .el-table__header th {
  1620. font-family: "Microsoft YaHei";
  1621. }
  1622. </style>