screen.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. <template>
  2. <view class="p_mask screen_dialog_mask" :class="{ fixed: !pMask }" v-if="screenDialogShow" @click="showScreenMask">
  3. <view class="screen_inner p_flexCenterCol" @click.stop="doNothing">
  4. <view class="screen_box p_format p_scroll">
  5. <!-- 时间 -->
  6. <view class="screen_item" v-if="showDatePicker">
  7. <view class="item_tit p_flexBetween">
  8. <view class="item_tit_val">咨询时间</view>
  9. </view>
  10. <view class="item_time_box p_flexBetween">
  11. <picker mode="date"
  12. :value="queryDataCopy.ConsultStartDate || queryDataCopy.BeginDate || queryDataCopy.StartTime"
  13. :start="start"
  14. :end="queryDataCopy.ConsultEndDate || queryDataCopy.EndDate || queryDataCopy.EndTime"
  15. @change="dateChange"
  16. :data-key="queryDataCopy.ConsultStartDate ? 'queryDataCopy.ConsultStartDate' : queryDataCopy.BeginDate ? 'queryDataCopy.BeginDate' : 'queryDataCopy.StartTime'">
  17. <view class="time_con p_flexCenter">
  18. {{ queryDataCopy.ConsultStartDate || queryDataCopy.BeginDate || queryDataCopy.StartTime }}
  19. </view>
  20. </picker>
  21. <view class="time_tip">至</view>
  22. <picker mode="date" :value="queryDataCopy.ConsultEndDate || queryDataCopy.EndDate || queryDataCopy.EndTime"
  23. :start="queryDataCopy.ConsultStartDate || queryDataCopy.BeginDate || queryDataCopy.StartTime"
  24. @change="dateChange"
  25. :data-key="queryDataCopy.ConsultEndDate ? 'queryDataCopy.ConsultEndDate' : queryDataCopy.EndDate ? 'queryDataCopy.EndDate' : 'queryDataCopy.EndTime'">
  26. <view class="time_con p_flexCenter">
  27. {{ queryDataCopy.ConsultEndDate || queryDataCopy.EndDate || queryDataCopy.EndTime }}
  28. </view>
  29. </picker>
  30. </view>
  31. </view>
  32. <!-- 单选多选 -->
  33. <view class="screen_item" v-for="(itemParent, indexParent) in screenListCopy" :key="indexParent">
  34. <view class="item_tit p_flexBetween">
  35. <view class="item_tit_val">{{ itemParent.title }}<text class="item_tit_subval p_color_9">({{ itemParent.type === '0' ? '单选' : itemParent.type === '1' ? '多选' : '' }})</text></view>
  36. </view>
  37. <view class="item_list">
  38. <view
  39. class="item_val p_flexCenter"
  40. :class="{ 'p_color p_border item_val_ac': isHas(index, itemParent.selectedInd) }"
  41. v-for="(item, index) in itemParent.list" :key="index" @click="itemClick"
  42. :data-index-parent="indexParent"
  43. :data-index="index" :data-item="item">{{ item.name }}</view>
  44. </view>
  45. </view>
  46. <!-- 医生职称 -->
  47. <view class="screen_item" v-if="showDoctorTitle">
  48. <view class="item_tit p_flexBetween">
  49. <view class="item_tit_val">医生职称</view>
  50. </view>
  51. <view class="item_list">
  52. <view
  53. class="item_val p_flexCenter"
  54. :class="{ 'p_color p_border item_val_ac': isHas(item.DoctorTitleCode, titleSelectedList) }"
  55. v-for="(item, index) in titleList" :key="index" @click="titleListClick" :data-item="item">{{ item.DoctorTitle }}
  56. </view>
  57. </view>
  58. </view>
  59. <!-- 就诊人 -->
  60. <view class="screen_item" v-if="showMember && memberList.length > 0">
  61. <view class="item_tit p_flexBetween">
  62. <view class="item_tit_val">选择就诊人</view>
  63. </view>
  64. <view class="item_list">
  65. <view
  66. class="item_val p_flexCenter"
  67. :class="{ 'p_color p_border item_val_ac': item.memberId == (queryDataCopy.memberId || queryDataCopy.MemberId) }"
  68. v-for="(item, index) in memberList" :key="index" @click="memberClick" :data-item="item">{{ item.memberName }}</view>
  69. </view>
  70. </view>
  71. </view>
  72. <!-- 按钮 -->
  73. <view class="btn_list p_flexCenter">
  74. <view class="btn_item btn_item_reset p_border p_color p_flexCenter" @click="btnClick" data-type="reset">重置</view>
  75. <view class="btn_item btn_item_confirm p_bgcolor p_flexCenter" @click="btnClick" data-type="confirm">确定</view>
  76. </view>
  77. </view>
  78. </view>
  79. </template>
  80. <script setup lang="ts">
  81. import { ref, reactive, watch, onMounted, getCurrentInstance, defineExpose } from 'vue';
  82. import { common } from '@/uni-app-base/utils';
  83. import icon from '@/utils/icon';
  84. import { deepCopy, copy as netHosCopy } from '/pagesNetHos/st1/static/js/netHosCommon';
  85. import { isHas } from '/pagesNetHos/st1/static/js/common';
  86. import { queryTitleInfoNew, queryBaseMemberList_V3 } from '/pagesNetHos/st1/service/doctor/index';
  87. const { proxy } = getCurrentInstance() as any;
  88. const app = getApp();
  89. const props = withDefaults(defineProps<{
  90. // 遮罩层定位方式
  91. pMask?: boolean;
  92. // 是否展示筛选组件
  93. screenDialogShow?: boolean;
  94. // 是否展示就诊人
  95. showMember?: boolean;
  96. // 是否展示全部就诊人按钮
  97. showAllMember?: boolean;
  98. // 是否展示医生筛选
  99. showDoctorTitle?: boolean;
  100. // 筛选值
  101. screenList?: any[];
  102. // 入参
  103. queryData?: any;
  104. // 是否展示日期
  105. showDatePicker?: boolean;
  106. // 开始日期
  107. start?: string;
  108. }>(), {
  109. pMask: true,
  110. screenDialogShow: false,
  111. showMember: false,
  112. showAllMember: true,
  113. showDoctorTitle: false,
  114. screenList: () => [],
  115. queryData: () => ({}),
  116. showDatePicker: false,
  117. start: ''
  118. });
  119. const emit = defineEmits(['screenConfirmClk', 'showScreenMask']);
  120. // 当前选中的list
  121. const selectedList = ref<any[]>([]);
  122. // list副本
  123. const screenListCopy = ref<any[]>([]);
  124. // 入参副本
  125. const queryDataCopy = reactive<any>({});
  126. // 就诊人列表
  127. const memberList = ref<any[]>([]);
  128. // 当前选中的就诊人
  129. const memberSelected = ref<any>({});
  130. // 医生职称列表
  131. const titleList = ref<any[]>([]);
  132. // 当前选择医生职称
  133. const titleSelectedList = ref<string[]>(['']);
  134. // 监听 queryData 变化
  135. watch(() => props.queryData, (val) => {
  136. console.log(val, "val");
  137. Object.assign(queryDataCopy, deepCopy(val));
  138. }, { immediate: true, deep: true });
  139. // 监听 screenList 变化
  140. watch(() => props.screenList, (val) => {
  141. if (val && val.length > 0) {
  142. screenListCopy.value = deepCopy(val);
  143. }
  144. }, { immediate: true, deep: true });
  145. // 监听 screenDialogShow 变化,显示时调用 main
  146. watch(() => props.screenDialogShow, (val) => {
  147. if (val) {
  148. main();
  149. }
  150. });
  151. onMounted(() => {
  152. if (props.screenDialogShow) {
  153. main();
  154. }
  155. });
  156. // 页面显示时调用
  157. // 注意:UniApp 组件没有 pageLifetimes,需要在父组件中处理
  158. const main = () => {
  159. screenListCopy.value = deepCopy(props.screenList);
  160. if (props.showMember) {
  161. getCardList();
  162. }
  163. if (props.showDoctorTitle) {
  164. getDoctorTitle();
  165. }
  166. };
  167. // 暴露方法供父组件调用
  168. defineExpose({
  169. main
  170. });
  171. // 获取医生职称
  172. const getDoctorTitle = async () => {
  173. let data = {
  174. HosId: (app.globalData as any).hosId,
  175. DeptCode: "",
  176. IsUsed: true
  177. };
  178. let titleListData: any[] = [];
  179. let { resp } = await queryTitleInfoNew(data);
  180. if (!common.isEmpty(resp)) {
  181. resp.unshift({
  182. DoctorTitle: '全部',
  183. DoctorTitleCode: ''
  184. });
  185. titleListData = resp;
  186. }
  187. titleList.value = titleListData;
  188. };
  189. // 点击状态选项 区分单选多选
  190. const itemClick = (e: any) => {
  191. let indexParent = e.currentTarget?.dataset?.indexParent;
  192. let itemParent = screenListCopy.value[indexParent];
  193. let item = e.currentTarget?.dataset?.item;
  194. let index = e.currentTarget?.dataset?.index;
  195. if (itemParent.type === '0' || item.name.indexOf('全部') !== -1) {
  196. // 单选 或 点击了全部
  197. itemParent.selectedInd = [index];
  198. } else if (itemParent.type === '1') {
  199. // 多选
  200. if (itemParent.selectedInd.includes(index)) {
  201. // 多选时 不能取消最后一个选择
  202. if (itemParent.selectedInd.length === 1) {
  203. return;
  204. }
  205. let ind = itemParent.selectedInd.findIndex((ind: number) => ind === index);
  206. itemParent.selectedInd.splice(ind, 1);
  207. } else {
  208. itemParent.selectedInd.push(index);
  209. }
  210. // 过滤含有 全部 的字段
  211. let allIndex = itemParent.list.findIndex((item: any) => item.name.indexOf('全部') !== -1);
  212. itemParent.selectedInd = itemParent.selectedInd.filter((item: number) => item !== allIndex);
  213. }
  214. };
  215. // 就诊人点击
  216. const memberClick = (e: any) => {
  217. let item = e.currentTarget?.dataset?.item;
  218. queryDataCopy.MemberId = item.memberId || item.MemberId || "";
  219. queryDataCopy.MemberIds = item.memberId || item.MemberId || "";
  220. };
  221. // 医生职称点击
  222. const titleListClick = (e: any) => {
  223. let item = e.currentTarget?.dataset?.item;
  224. let titleSelected = [...titleSelectedList.value];
  225. if (item.DoctorTitle === '全部') {
  226. titleSelected = [''];
  227. } else {
  228. if (titleSelected.includes(item.DoctorTitleCode)) {
  229. // 多选时不能清空所有字段
  230. if (titleSelected.length === 1) {
  231. return;
  232. }
  233. titleSelected = titleSelected.filter((cell: string) => cell !== item.DoctorTitleCode);
  234. } else {
  235. titleSelected.push(item.DoctorTitleCode);
  236. }
  237. // 过滤全部选项
  238. titleSelected = titleSelected.filter((item: string) => item !== '');
  239. }
  240. console.log(titleSelected);
  241. queryDataCopy.DoctorTitleCode = titleSelected.join(',');
  242. titleSelectedList.value = titleSelected;
  243. };
  244. // 获取就诊人列表
  245. const getCardList = async () => {
  246. let queryData = {
  247. HosId: (app.globalData as any).hosId,
  248. isEncrypt: true,
  249. };
  250. let { resp } = await queryBaseMemberList_V3(queryData);
  251. let list: any[] = [];
  252. if (!common.isEmpty(resp)) {
  253. if (props.showAllMember) {
  254. resp.unshift({
  255. memberName: '全部',
  256. memberId: '',
  257. });
  258. }
  259. list = resp;
  260. }
  261. memberList.value = list;
  262. };
  263. // 日期更改
  264. const dateChange = (e: any) => {
  265. let key = e.currentTarget?.dataset?.key;
  266. if (key) {
  267. const keys = key.split('.');
  268. if (keys.length === 2) {
  269. (queryDataCopy as any)[keys[1]] = e.detail.value;
  270. } else {
  271. queryDataCopy[key] = e.detail.value;
  272. }
  273. }
  274. };
  275. // 按钮点击
  276. const btnClick = (e: any) => {
  277. let type = e.currentTarget?.dataset?.type;
  278. if (type === 'confirm') {
  279. // 确定
  280. let data: any = {};
  281. let queryDataCopyNew = deepCopy(queryDataCopy);
  282. for (let item of screenListCopy.value) {
  283. for (let i of item.selectedInd) {
  284. data = copy(item.list[i].options, data);
  285. }
  286. }
  287. netHosCopy(data, queryDataCopyNew);
  288. // memberId 和 MemberIds 只传一个
  289. if (queryDataCopyNew.MemberIds == '') {
  290. let arr: string[] = [];
  291. memberList.value.map((item: any) => {
  292. arr.push(item.memberId);
  293. });
  294. queryDataCopyNew.MemberIds = arr.join(',');
  295. }
  296. emit('screenConfirmClk', queryDataCopyNew);
  297. showScreenMask();
  298. } else if (type === 'reset') {
  299. // 重置
  300. screenListCopy.value = deepCopy(props.screenList);
  301. Object.assign(queryDataCopy, deepCopy(props.queryData));
  302. queryDataCopy.DoctorTitleCode = '';
  303. queryDataCopy.MemberId = "";
  304. queryDataCopy.MemberIds = "";
  305. titleSelectedList.value = [''];
  306. }
  307. };
  308. // 展示筛选弹窗
  309. const showScreenMask = () => {
  310. emit('showScreenMask');
  311. };
  312. const doNothing = () => {
  313. // 阻止事件冒泡
  314. };
  315. // 如果对象key相同 将值push至复制对象中
  316. const copy = (obj: any, c: any = {}) => {
  317. for (var i in obj) {
  318. if (Object.keys(c).includes(i)) {
  319. let arr = c[i].split(',');
  320. arr.push(obj[i]);
  321. c[i] = arr.join(',');
  322. } else {
  323. c[i] = obj[i];
  324. }
  325. }
  326. return c;
  327. };
  328. </script>
  329. <style lang="scss" scoped>
  330. @import "@/pagesNetHos/st1/static/css/common.scss";
  331. .p_mask {
  332. height: 100vh;
  333. position: absolute;
  334. }
  335. .screen_inner {
  336. background-color: #fff;
  337. padding: 10upx 30upx 0;
  338. border-radius: 0px 0px 36upx 36upx;
  339. max-height: 800upx;
  340. }
  341. .screen_box {
  342. width: 100%;
  343. }
  344. .item_tit {
  345. margin: 30upx 0 10upx;
  346. }
  347. .item_tit_val {
  348. font-size: 32upx;
  349. font-weight: 500;
  350. }
  351. .item_tit_subval {
  352. font-size: 28upx;
  353. }
  354. .item_tit_img {
  355. width: 20upx;
  356. height: 20upx;
  357. }
  358. .item_list {
  359. display: flex;
  360. align-items: center;
  361. flex-wrap: wrap;
  362. }
  363. .item_val {
  364. padding: 0 20upx;
  365. width: 216upx;
  366. height: 68upx;
  367. background: #F7F7F7;
  368. border-radius: 34upx;
  369. font-size: 26upx;
  370. margin: 20upx 20upx 0 0;
  371. }
  372. .item_val:nth-child(3n) {
  373. margin-right: 0;
  374. }
  375. .item_val_ac {
  376. background-color: #E7F7F3;
  377. }
  378. .item_val_ac::after,
  379. .item_val_ac::before {
  380. border-color: #01BF8E;
  381. border-radius: 34px;
  382. }
  383. .time_con {
  384. width: 312upx;
  385. height: 68upx;
  386. background: #F7F7F7;
  387. border-radius: 8px;
  388. margin: 20upx 0;
  389. font-size: 26upx;
  390. }
  391. .time_tip {
  392. font-size: 26upx;
  393. }
  394. .btn_list {
  395. margin: 30upx 0;
  396. }
  397. .btn_item {
  398. width: 345upx;
  399. height: 92upx;
  400. background-color: #fff;
  401. border-radius: 46upx 0 0 46upx;
  402. font-size: 34upx;
  403. }
  404. .btn_item_reset::after,
  405. .btn_item_reset::before {
  406. border-color: #01BF8E;
  407. border-radius: 46px 0 0 46px;
  408. }
  409. .btn_item_confirm {
  410. border-radius: 0px 46upx 46upx 0px;
  411. }
  412. .fixed {
  413. position: fixed;
  414. }
  415. </style>