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.

1618 lines
60 KiB

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