Index.vue 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <template>
  2. <div class="component-box-wrapper__half-transparent" :style="{ zIndex }">
  3. <div class="component-content-box__dialog-like box-width">
  4. <div class="component-header-box">
  5. <div class="component-header__title">{{ title }}</div>
  6. <div class="component-header__close-button">
  7. <el-button plain icon="Close" circle title="关闭" @click="close"></el-button>
  8. </div>
  9. </div>
  10. <div style="display: flex;align-items: center;">
  11. <div>检索依据:</div>
  12. <div>
  13. <el-select v-model="params.method" style="width: 70px">
  14. <el-option
  15. v-for="item in allMethods"
  16. :key="item.code"
  17. :label="item.name"
  18. :value="item.code"
  19. ></el-option>
  20. </el-select>
  21. </div>
  22. <div v-if="showMallType" style="margin-left: 4px">
  23. 项目类别:
  24. </div>
  25. <div v-if="showMallType">
  26. <el-select v-model="params.target" style="width: 60px">
  27. <el-option label="检验" value="JY" />
  28. <el-option label="检查" value="JC" />
  29. <el-option label="诊疗" value="ZL" />
  30. </el-select>
  31. </div>
  32. <div>
  33. <el-input
  34. ref="inputRef"
  35. v-model="params.content"
  36. clearable
  37. placeholder="请输入检索内容"
  38. style="width: 180px;margin-left: 4px"
  39. ></el-input>
  40. </div>
  41. </div>
  42. <div class="data-box">
  43. <el-table
  44. ref="resultRef"
  45. :data="data.list"
  46. stripe height="360px"
  47. highlight-current-row
  48. @row-click="clickItem"
  49. >
  50. <el-table-column prop="code" label="编码"></el-table-column>
  51. <el-table-column prop="name" label="名称"></el-table-column>
  52. <el-table-column v-if="showEmpDept" prop="deptName" label="科室"></el-table-column>
  53. <el-table-column v-if="showYbCode" prop="ybCode" label="医保赋码"></el-table-column>
  54. <el-table-column v-if="showOpScale" prop="opScale" label="手术/操作级别" align="center"></el-table-column>
  55. <el-table-column v-if="showOpType" prop="opTypeName" label="手术/操作类型"></el-table-column>
  56. </el-table>
  57. <el-pagination
  58. @current-change="handleCurrentChange"
  59. :current-page="params.page"
  60. :page-size="params.pageSize"
  61. layout="total, pager, next"
  62. :total="data.totalSize"
  63. ></el-pagination>
  64. </div>
  65. </div>
  66. <el-dialog title="请确认诊断类别" v-model="showDiagType" width="360px">
  67. <div style="margin-top: 8px">
  68. 诊断编码:
  69. <el-input v-model="diagItem.icdCode" disabled style="width: 220px"></el-input>
  70. </div>
  71. <div style="margin-top: 8px">
  72. 诊断名称:
  73. <el-input v-model="diagItem.icdText" disabled style="width: 220px"></el-input>
  74. </div>
  75. <div style="margin-top: 8px">
  76. 诊断类别:
  77. <el-select v-model="diagItem.diagType" style="width: 220px">
  78. <el-option v-for="item in diagTypes" :key="item.code" :value="item.code" :label="item.name"></el-option>
  79. </el-select>
  80. </div>
  81. <div style="margin-top: 8px; width: 100%; text-align: right; padding: 8px 20px 8px 0">
  82. <el-button type="primary" icon="Check" @click="confirmDiaginfo">确定</el-button>
  83. </div>
  84. </el-dialog>
  85. </div>
  86. </template>
  87. <script setup>
  88. import { reactive, ref, watch } from 'vue'
  89. import { searchFromServer } from '@/api/inpatient/dictionary'
  90. import { diagTypes } from '@/data'
  91. import Sleep from '@/utils/sleep'
  92. import {useZIndex} from "element-plus";
  93. const props = defineProps({
  94. width: {
  95. type: String,
  96. default: '420px'
  97. },
  98. title: {
  99. type: String,
  100. required: true,
  101. },
  102. target: {
  103. type: String,
  104. required: true,
  105. },
  106. medType: {
  107. type: String,
  108. default: '',
  109. },
  110. showEmpDept: {
  111. type: Boolean,
  112. default: false
  113. },
  114. showYbCode: {
  115. type: Boolean,
  116. default: false
  117. },
  118. showOpScale: {
  119. type: Boolean,
  120. default: false
  121. },
  122. showOpType: {
  123. type: Boolean,
  124. default: false
  125. },
  126. showMallType: {
  127. type: Boolean,
  128. default: false
  129. }
  130. })
  131. const emits = defineEmits(['close', 'clickItem'])
  132. const width = props.width
  133. const inputRef = ref(null)
  134. const resultRef = ref(null)
  135. const allMethods = [
  136. { code: 'alpha', name: '拼音' },
  137. { code: 'code', name: '编码' },
  138. { code: 'name', name: '名称' },
  139. ]
  140. const params = reactive({
  141. method: 'alpha',
  142. target: props.target,
  143. medType: props.medType,
  144. page: 1,
  145. pageSize: 10,
  146. content: '',
  147. })
  148. const data = reactive({
  149. list: [],
  150. totalSize: 0,
  151. })
  152. const showDiagType = ref(false)
  153. const diagItem = reactive({
  154. icdCode: null,
  155. icdText: null,
  156. diagType: null,
  157. })
  158. const executeSearch = () => {
  159. if (params.content.trim().length > 1) {
  160. searchFromServer(params).then((res) => {
  161. data.list = res.list
  162. data.totalSize = res.totalSize
  163. currentIndex.value = currentIndex.value > data.list.length - 1 ? data.list.length - 1 : currentIndex.value
  164. resultRef.value.setCurrentRow(data.list[currentIndex.value])
  165. })
  166. } else {
  167. data.list = []
  168. data.totalSize = 0
  169. }
  170. }
  171. const currentIndex = ref(0)
  172. const handleCurrentChange = (val) => {
  173. params.page = val
  174. executeSearch()
  175. }
  176. const confirmDiaginfo = () => {
  177. emits('clickItem', diagItem)
  178. }
  179. const clickItem = (item) => {
  180. if (props.target === 'diag' || props.target === 'injurydiag') {
  181. diagItem.icdCode = item.code
  182. diagItem.icdText = item.name
  183. diagItem.diagType = '1'
  184. showDiagType.value = true
  185. } else if (props.showMallType) {
  186. item.type = params.target
  187. emits('clickItem', item)
  188. }
  189. }
  190. const close = () => {
  191. emits('close')
  192. }
  193. watch(
  194. () => params.content,
  195. () => {
  196. executeSearch()
  197. }
  198. )
  199. const zIndex = ref(0)
  200. onMounted(async () => {
  201. zIndex.value = useZIndex().nextZIndex()
  202. await Sleep(100)
  203. inputRef.value.focus()
  204. document.onkeydown = (e) => {
  205. switch (e.code) {
  206. case 'ArrowUp':
  207. resultRef.value.setCurrentRow(data.list[currentIndex.value === 0 ? 0 : --currentIndex.value])
  208. return false
  209. case 'ArrowDown':
  210. resultRef.value.setCurrentRow(data.list[currentIndex.value === data.list.length - 1 ? data.list.length - 1 : ++currentIndex.value])
  211. return false
  212. case 'ArrowLeft':
  213. if (params.page > 1) {
  214. handleCurrentChange(params.page - 1)
  215. }
  216. return false
  217. case 'ArrowRight':
  218. if (params.page * params.pageSize < data.totalSize) {
  219. handleCurrentChange(params.page + 1)
  220. }
  221. return false
  222. case 'Enter':
  223. clickItem(data.list[currentIndex.value])
  224. break
  225. case 'Escape':
  226. close()
  227. break
  228. }
  229. }
  230. })
  231. </script>
  232. <style scoped>
  233. .box-width {
  234. width: v-bind(width);
  235. }
  236. .data-box {
  237. margin-top: 16px;
  238. overflow-y: auto;
  239. border-top: 1px solid rgb(231, 231, 231);
  240. }
  241. </style>