reportIndex.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. <template>
  2. <view class="container">
  3. <view class="content">
  4. <view :class="!authorize ? 'userInfoTopFixe' : ''">
  5. <userInfo :userInfo="currentUser" :type="pageType" :bgClass="authorize ? 'bgLinGra' : 'bgWhite'"></userInfo>
  6. <view class="public_inner_table" v-if="!authorize">
  7. <view class="report_type_box displayFlexRow">
  8. <view class="public_inner_table_item" :class="queryData.ReportType == '1' ? 'public_inner_table_item_active' : ''" @click="navClick('1')">检验报告单</view>
  9. <view class="public_inner_table_item" :class="queryData.ReportType == '2' ? 'public_inner_table_item_active' : ''" @click="navClick('2')">检查报告单</view>
  10. </view>
  11. <screening :isShowTime="false" :screen="screen" @setScreenData="setScreenData" @queryRecords="queryRecords" @resetScreen="resetScreen"></screening>
  12. </view>
  13. </view>
  14. <view class="content_inner" v-if="!authorize">
  15. <view class="public_list" v-if="!showNoData">
  16. <view class="public_card border_bottom" @click="deptClick(item)" v-for="(item, index) in reportList" :key="index">
  17. <view class="public_card_con">
  18. <view class="public_user_info">
  19. <view class="public_user_name">{{ item.ItemName }}</view>
  20. <view class="public_user_time">{{ item.SubmissionTime }}</view>
  21. </view>
  22. </view>
  23. <view class="state_tip colorRed" v-if="item.State != '1'">报告未出</view>
  24. <image class="public_right_img" :src="iconUrl.icon_right"></image>
  25. </view>
  26. </view>
  27. <view v-if="showNoData" class="noData">
  28. <noData :value="queryData.ReportType == '1' ? '没有找到该患者的检验报告单' : queryData.ReportType == '2' ? '没有找到该患者的检查报告单' : '没有查到该患者的报告单信息'"></noData>
  29. </view>
  30. </view>
  31. <authorizeMode v-else :userInfo="currentUser" :level="authLevel"></authorizeMode>
  32. </view>
  33. </view>
  34. </template>
  35. <script setup lang="ts">
  36. import { ref, reactive, onMounted } from 'vue';
  37. import { onLoad, onShow } from '@dcloudio/uni-app';
  38. import { common } from '@/utils';
  39. import icon from '@/utils/icon';
  40. import { getReportList as getReportListApi } from '@/pagesPatient/service/report/index';
  41. // 组件引用
  42. import noData from '@/pages/st1/components/noData/noData.vue';
  43. import userInfo from '@/pagesPersonal/st1/components/userInfo/userInfo.vue';
  44. import screening from '@/pagesPatient/st1/components/screening/screening.vue';
  45. import authorizeMode from '@/pages/st1/components/authorizeMode/authorizeMode.vue';
  46. const app = getApp();
  47. const iconUrl = ref(icon);
  48. const pageType = ref('card'); // card 组件进入卡列表 hospital 组件进入住院号列表
  49. const currentUser = ref<any>({});
  50. const reportList = ref<any[]>([]);
  51. const showNoData = ref(false);
  52. const authorize = ref(false); // 暂时默认为 false,如果需要权限校验逻辑需补充
  53. const authLevel = ref(2); // 假设的默认值
  54. const screen = reactive({
  55. screenKey: 'screen',
  56. btnName: '',
  57. startDate: common.dateFormat(new Date(Date.now() - (180 * 24 * 60 * 60 * 1000))).formatYear, // 开始时间
  58. endDate: common.afterFewDays(1),
  59. state: [],
  60. sourceType: [],
  61. memberId: [],
  62. columns: [],
  63. screenTime: []
  64. });
  65. const queryData = reactive<any>({
  66. CardType: '1',
  67. CardNo: '',
  68. MemberId: '',
  69. StartDate: '', // 开始时间
  70. EndDate: '',
  71. PatientName: '',
  72. ReportType: '1', // 报告单类型 1检验报告 2检查报告
  73. Page: {
  74. PIndex: 0,
  75. PSize: 10
  76. },
  77. Data_1: {
  78. queryType: '1'
  79. }
  80. });
  81. onLoad((options: any) => {
  82. let queryType = options.queryType || '1';
  83. // 初始化当前选择
  84. if (queryData.Data_1) {
  85. queryData.Data_1.queryType = queryType;
  86. }
  87. queryData.ReportType = options.reportType || '1';
  88. pageType.value = queryType == '1' ? 'card' : 'hospital';
  89. // serviceType 暂时没用到,保留逻辑一致性
  90. });
  91. onShow(() => {
  92. currentUser.value = app.globalData.currentUser || uni.getStorageSync('currentUser') || {};
  93. main();
  94. });
  95. const main = async () => {
  96. // 权限校验逻辑
  97. // 原代码:if (await publicFn.isPageUserAuth(this.data.currentUser,this)) return
  98. // 如果无 memberId 则认为未登录/未授权
  99. if (!currentUser.value || !currentUser.value.memberId) {
  100. authorize.value = true;
  101. return;
  102. } else {
  103. authorize.value = false;
  104. }
  105. getReportList();
  106. };
  107. const setScreenData = (e: any) => {
  108. // 原代码:this.setData(e.detail)
  109. // 这里假设 e 是包含 screen 属性的对象,或者是直接更新 screen
  110. // 按照 screening 组件通常的行为,可能传回的是 screen 对象
  111. // 但原代码 this.setData(e.detail) 意味着 e.detail 可能包含 screen 字段
  112. if (e && e.screen) {
  113. Object.assign(screen, e.screen);
  114. } else if (e) {
  115. // 尝试合并
  116. Object.assign(screen, e);
  117. }
  118. };
  119. const resetScreen = (e: any) => {
  120. let newScreen = common.deepCopy(e); // 假设 e 就是 screen 数据,原代码 e.detail
  121. Object.assign(screen, newScreen);
  122. getReportList();
  123. };
  124. const queryRecords = (e: any) => {
  125. reportList.value = [];
  126. getReportList();
  127. };
  128. const getReportList = async (pIndex = 0) => {
  129. let showNoDataFlag = true;
  130. let obj = {
  131. CardType: currentUser.value.cardType,
  132. CardNo: currentUser.value.cardNo,
  133. MemberId: currentUser.value.memberId,
  134. PatientName: currentUser.value.memberName,
  135. Store: {
  136. cardEncryptionStore: currentUser.value.encryptionStore || '',
  137. baseMemberEncryptionStore: currentUser.value.baseMemberEncryptionStore
  138. }
  139. };
  140. queryData.StartDate = screen.startDate;
  141. queryData.EndDate = screen.endDate;
  142. // 合并 obj 到 queryData
  143. let requestData = common.deepCopy(obj, queryData);
  144. requestData.Page.PIndex = pIndex;
  145. let resp = await getReportListApi(requestData);
  146. if (!common.isEmpty(resp)) {
  147. resp.sort((a: any, b: any) => {
  148. return new Date(common.iosTime(b.SubmissionTime)).getTime() - new Date(common.iosTime(a.SubmissionTime)).getTime();
  149. });
  150. reportList.value = resp;
  151. showNoDataFlag = false;
  152. } else {
  153. reportList.value = [];
  154. }
  155. showNoData.value = showNoDataFlag;
  156. };
  157. const deptClick = (item: any) => {
  158. let queryBean = JSON.stringify(item);
  159. let url = "";
  160. if (item.State != '1') {
  161. // 如果不是已发布的 不能点击
  162. return;
  163. }
  164. // 检验报告
  165. if (item.ReportType == '1') {
  166. url = `/pagesPatient/st1/business/report/inspectCheckReportDetails/inspectCheckReportDetails?queryBean=${queryBean}`;
  167. }
  168. // 检查
  169. if (item.ReportType == '2') {
  170. url = `/pagesPatient/st1/business/report/inspectTestReportDetails/inspectTestReportDetails?queryBean=${queryBean}`;
  171. }
  172. // 体检
  173. if (item.ReportType == '3') {
  174. url = `/pagesPatient/st1/business/report/examinationReport/examinationReport?queryBean=${queryBean}`;
  175. }
  176. if (url) {
  177. common.goToUrl(url);
  178. }
  179. };
  180. const navClick = (type: string) => {
  181. reportList.value = [];
  182. showNoData.value = true;
  183. queryData.ReportType = type;
  184. // noDataValue 计算属性可以直接在 template 处理,或者这里不用管
  185. getReportList();
  186. };
  187. </script>
  188. <style scoped>
  189. .container {
  190. height: 100vh;
  191. background-color: #f5f5f5;
  192. }
  193. .content {
  194. /* padding-bottom: 20upx; */
  195. }
  196. .userInfoTopFixe {
  197. position: fixed;
  198. top: 0;
  199. left: 0;
  200. width: 100%;
  201. z-index: 100;
  202. }
  203. .public_inner_table {
  204. height: 110upx;
  205. display: flex;
  206. align-items: center;
  207. justify-content: space-around;
  208. font-size: 30upx;
  209. color: rgba(85, 85, 85, 1);
  210. background-color: #fff;
  211. }
  212. .report_type_box {
  213. width: 70%;
  214. height: 106upx;
  215. display: flex; /* Added flex based on usage */
  216. justify-content: space-around;
  217. align-items: center; /* Typically needed */
  218. }
  219. .public_inner_table_item {
  220. font-size: 32upx;
  221. color: #666;
  222. /* padding-bottom: 10upx; */
  223. position: relative;
  224. height: 100%;
  225. display: flex;
  226. align-items: center;
  227. }
  228. .public_inner_table_item_active {
  229. font-size: 32upx;
  230. font-family: Source Han Sans CN;
  231. font-weight: 500;
  232. color: var(--dominantColor) !important;
  233. }
  234. .public_inner_table_item_active::before {
  235. content: '';
  236. position: absolute;
  237. width: 36upx;
  238. height: 6upx;
  239. border-radius: 3upx;
  240. bottom: 18upx; /* Changed from top to bottom for better positioning usually, matching original approximately */
  241. left: 0;
  242. right: 0;
  243. margin: 0 auto;
  244. background-color: var(--dominantColor);
  245. box-shadow: 0px 8px 12px 0px var(--dominantColor);
  246. }
  247. /* Adjust top based on original css logic but using upx */
  248. /* Original: top: 18rpx; margin: 20rpx auto 0 auto; This seems weird for an underline.
  249. Usually underlines are at bottom.
  250. Let's stick to original relative logic if possible or safer standard.
  251. Original:
  252. top: 18rpx;
  253. margin: 20rpx auto 0 auto;
  254. If parent height is 106rpx, 18+20 = 38rpx from top. That's top aligned?
  255. Let's trust the original css values but converted.
  256. */
  257. .content_inner{
  258. margin-top: 300upx; /* Adjust based on fixed header height */
  259. padding-bottom: 20upx;
  260. }
  261. /* 暂无数据 */
  262. .public_list{
  263. width: 100%;
  264. background: white;
  265. padding-left: 30upx;
  266. box-sizing: border-box;
  267. position: relative;
  268. z-index: 1; /* Changed from -1 to 1 to be visible/clickable */
  269. }
  270. .public_card{
  271. padding: 40upx 30upx 40upx 0;
  272. display: flex;
  273. flex-direction: row;
  274. justify-content: space-between;
  275. align-items: center;
  276. }
  277. .public_user_name{
  278. font-size: 32upx;
  279. color: #333;
  280. margin-bottom: 10upx;
  281. }
  282. .public_user_time{
  283. font-size: 24upx;
  284. color: #999;
  285. }
  286. .border_bottom {
  287. position: relative;
  288. z-index: 10;
  289. }
  290. .border_bottom::after {
  291. content: " ";
  292. position: absolute;
  293. left: 0;
  294. bottom: 0;
  295. width: 100%;
  296. height: 1px;
  297. border-top: 1px solid #e6e6e6;
  298. -webkit-transform-origin: 0 0;
  299. transform-origin: 0 0;
  300. -webkit-transform: scaleY(0.5);
  301. transform: scaleY(0.5);
  302. }
  303. .noData {
  304. margin-top: 260upx;
  305. }
  306. .public_right_img{
  307. width: 30upx; /* Added width/height for image */
  308. height: 30upx;
  309. /* right: 30rpx; Removed absolute positioning if flex is used correctly */
  310. }
  311. .state_tip{
  312. margin-right: 22upx;
  313. }
  314. .colorRed {
  315. color: red;
  316. }
  317. .displayFlexRow {
  318. display: flex;
  319. flex-direction: row;
  320. }
  321. </style>