consumableList.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <template>
  2. <view class="consumableList">
  3. <view class="head" >
  4. <uni-search-bar v-model="dataInfo.keyWord" placeholder="请搜索耗材" bgColor="#F8F8F8" @input="search" cancelButton="none" focus :radius="18" />
  5. </view>
  6. <view class="body" v-if="dataInfo.list.length">
  7. <view class="body_item ellipsis" v-for="data in dataInfo.list" :key="data.id" @click="numberClick(data, 'addConsumable')">
  8. {{data.name}}
  9. <template v-if="data.model">({{data.model}})</template>
  10. <template v-if="data.unit">({{data.unit}})</template>
  11. <template v-if="data.price">({{data.price}}元)</template>
  12. </view>
  13. </view>
  14. <view class="zanwu" v-else>
  15. <text class="newicon newicon-zanwu"></text>
  16. </view>
  17. <view class="foot_common_btns">
  18. <button @click="goBack" type="default" class="primaryButton btn">返回</button>
  19. </view>
  20. <NumberModal v-if="dataInfo.isNumber" @cancelEmit="cancelNumber" @confirmEmit="conformNumber" :selectData="dataInfo.selectData" :selectType="dataInfo.selectType"></NumberModal>
  21. </view>
  22. </template>
  23. <script setup>
  24. import { debounce, uniqBy } from 'lodash-es'
  25. import { ref, reactive} from 'vue'
  26. import NumberModal from '@/components/NumberModal.vue';
  27. import { onLoad, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
  28. import { api_consumable, getFetchDataList, api_incidentDetail,
  29. api_addSummaryDoc, api_incidentCategoryConsumable, api_in_consumables } from "@/http/api.js"
  30. import { defaultColor } from '@/static/js/theme.js'
  31. import { useSetTitle } from '@/share/useSetTitle.js'
  32. import { useLoginUserStore } from '@/stores/loginUser'
  33. import { useGoBack } from '@/share/useGoBack.js'
  34. useSetTitle();
  35. const loginUserStore = useLoginUserStore();
  36. const { goBack } = useGoBack();
  37. // 主题颜色
  38. const primaryColor = ref(defaultColor)
  39. // 数据
  40. const dataInfo = reactive({
  41. list: [],//工单列表
  42. idx: 0,//页码
  43. hasMore: true,//是否有更多数据
  44. incidentId: undefined,//事件ID
  45. summaryId: undefined,//汇总单ID
  46. categoryId: undefined,//故障现象ID
  47. incidentData: {},//事件对象
  48. keyWord: '',//搜索的关键词
  49. isNumber: false,//修改数量弹窗
  50. evtNumber: 1,//弹窗返回的数量
  51. selectData: {},//选择的对象
  52. selectType: {},//选择的对象类型
  53. itsmZeroStock:null, //是否支持零库存
  54. itsmParentConsumable:null //是否支持父级科室耗材
  55. })
  56. // 点击修改数量
  57. function numberClick(data, type){
  58. console.log(data)
  59. dataInfo.isNumber = true;
  60. dataInfo.selectData = {
  61. consumableBrandModel: data.brandModel,
  62. consumableUnit: data.unit,
  63. consumableEndPrice: data.price,
  64. consumableId: data.id,
  65. consumableName: data.name,
  66. };
  67. dataInfo.selectType = type;
  68. }
  69. // 确认修改数量
  70. function conformNumber(evtNumber){
  71. dataInfo.evtNumber = evtNumber;
  72. dataInfo.isNumber = false;
  73. addSummaryDoc();
  74. }
  75. // 关闭修改数量
  76. function cancelNumber(){
  77. dataInfo.isNumber = false;
  78. }
  79. // 添加耗材
  80. function addSummaryDoc(){
  81. uni.showLoading({
  82. title: "加载中",
  83. mask: true,
  84. });
  85. let postData = {
  86. "consumableList": [
  87. {
  88. "consumablesId": dataInfo.selectData.consumableId,
  89. "consumablesNum": dataInfo.evtNumber
  90. }
  91. ],
  92. "summaryId": dataInfo.summaryId
  93. };
  94. api_addSummaryDoc(postData).then(res => {
  95. uni.hideLoading();
  96. if(res.status == 200){
  97. uni.showToast({
  98. icon: 'none',
  99. title: '添加耗材成功',
  100. mask: true,
  101. });
  102. setTimeout(() => {
  103. uni.navigateTo({
  104. url: `/pages/handler/handler?incidentId=${dataInfo.incidentId}`,
  105. })
  106. }, 1500)
  107. }else{
  108. uni.showToast({
  109. icon: 'none',
  110. title: res.msg || '请求数据失败!'
  111. });
  112. }
  113. })
  114. }
  115. // 获取事件详情
  116. function getIncidentDetail(){
  117. uni.showLoading({
  118. title: "加载中",
  119. mask: true,
  120. });
  121. api_incidentDetail(dataInfo.incidentId).then(res => {
  122. uni.hideLoading();
  123. if(res.status == 200){
  124. dataInfo.incidentData = res.data || {};
  125. getHosConfig()
  126. }else{
  127. uni.showToast({
  128. icon: 'none',
  129. title: res.msg || '请求数据失败!'
  130. });
  131. }
  132. })
  133. }
  134. // 获取常用耗材
  135. function getInConsumables(){
  136. uni.showLoading({
  137. title: "加载中",
  138. mask: true,
  139. });
  140. api_in_consumables(dataInfo.categoryId).then(res => {
  141. uni.hideLoading();
  142. if(res.status == 200){
  143. dataInfo.list = res.data || {};
  144. }else{
  145. uni.showToast({
  146. icon: 'none',
  147. title: res.msg || '请求数据失败!'
  148. });
  149. }
  150. })
  151. }
  152. // 搜索
  153. const search = debounce(getList.bind(null, 0), 500);
  154. // 是否没有故障耗材配置
  155. const isFlag = ref(false);
  156. // 获取故障耗材配置
  157. async function getIncidentCategoryConsumable(){
  158. uni.showLoading({
  159. title: "加载中",
  160. mask: true,
  161. });
  162. let postData = {
  163. idx: 0,
  164. sum: 20,
  165. incidentCategoryConsumable: {
  166. duty: dataInfo.incidentData.duty.id,
  167. category: dataInfo.incidentData.category,
  168. }
  169. }
  170. let res = await api_incidentCategoryConsumable(postData);
  171. uni.hideLoading();
  172. uni.stopPullDownRefresh();
  173. if(res.status == 200){
  174. let list = res.list || [];
  175. if(list.length){
  176. isFlag.value = false;
  177. let arr = list.map(v => v.consumableDTOS).flat();
  178. dataInfo.list = uniqBy(arr, 'id');
  179. }else{
  180. isFlag.value = true;
  181. }
  182. }else{
  183. isFlag.value = false;
  184. uni.showToast({
  185. icon: 'none',
  186. title: res.msg || '请求数据失败!'
  187. });
  188. }
  189. }
  190. // 获取列表信息
  191. function getList(idx){
  192. // 判断是否满足故障耗材配置
  193. // await getIncidentCategoryConsumable();
  194. // if(!isFlag.value){
  195. // return;
  196. // }
  197. if(dataInfo.keyWord.trim() === ''){
  198. dataInfo.list = [];
  199. uni.stopPullDownRefresh();
  200. getInConsumables();
  201. return;
  202. }
  203. uni.showLoading({
  204. title: "加载中",
  205. mask: true,
  206. });
  207. dataInfo.idx = idx === undefined ? dataInfo.idx : idx;
  208. if(dataInfo.idx === 0){
  209. dataInfo.list = [];
  210. }
  211. let postData = {
  212. idx: dataInfo.idx,
  213. sum: 20,
  214. consumable: {
  215. name: dataInfo.keyWord,
  216. upHosId:loginUserStore.loginUser.user.currentHospital.id,
  217. hosId: loginUserStore.loginUser.user.currentHospital.id
  218. }
  219. }
  220. if(dataInfo.itsmParentConsumable.value==1){
  221. delete postData.consumable.hosId
  222. }else{
  223. delete postData.consumable.upHosId
  224. }
  225. getFetchDataList("simple/data", "consumable", postData)
  226. .then((res) => {
  227. uni.hideLoading();
  228. uni.stopPullDownRefresh();
  229. if(res.status == 200){
  230. let list = res.list || [];
  231. if(list.length){
  232. dataInfo.hasMore = true;
  233. if(dataInfo.itsmZeroStock.value==0){
  234. let arr = dataInfo.idx === 0 ? list : dataInfo.list.concat(list)
  235. dataInfo.list = arr.filter(i=>i.stock!=0)
  236. }else{
  237. dataInfo.list = dataInfo.idx === 0 ? list : dataInfo.list.concat(list);
  238. }
  239. }else{
  240. dataInfo.hasMore = false;
  241. getInConsumables();
  242. }
  243. }else{
  244. uni.showToast({
  245. icon: 'none',
  246. title: res.msg || '请求数据失败!'
  247. });
  248. }
  249. });
  250. }
  251. // 获取院区配置是否支持零库存/是否支持父级科室耗材
  252. function getHosConfig(){
  253. let postData = {
  254. idx: 0,
  255. sum: 9999,
  256. hospitalConfig:{
  257. hosId: loginUserStore.loginUser.user.currentHospital.id,
  258. model: "itsm"
  259. }
  260. };
  261. getFetchDataList("simple/data", "hospitalConfig", postData)
  262. .then((res) => {
  263. dataInfo.itsmZeroStock = res.list.find(i=>i.key=='itsmZeroStock')
  264. dataInfo.itsmParentConsumable = res.list.find(i=>i.key=='itsmParentConsumable')
  265. getInConsumables();
  266. });
  267. }
  268. onLoad((option) => {
  269. dataInfo.incidentId = option.incidentId;
  270. dataInfo.summaryId = option.summaryId;
  271. dataInfo.categoryId = option.categoryId;
  272. getIncidentDetail();
  273. })
  274. onPullDownRefresh(() => {
  275. getList(0)
  276. })
  277. onReachBottom(() => {
  278. dataInfo.idx += 1;
  279. if (dataInfo.hasMore) {
  280. getList(); // 当触底时加载更多数据
  281. }
  282. })
  283. </script>
  284. <style lang="scss" scoped>
  285. .consumableList{
  286. display: flex;
  287. flex-direction: column;
  288. justify-content: space-between;
  289. .head{
  290. height: 88rpx;
  291. display: flex;
  292. align-items: center;
  293. justify-content: center;
  294. padding: 0 24rpx;
  295. position: fixed;
  296. z-index: 99;
  297. width: 100%;
  298. box-sizing: border-box;
  299. background: linear-gradient( 90deg, #58CF66 0%, #DDE9FC 100%);
  300. }
  301. .body{
  302. margin-bottom: 140rpx;
  303. margin-top: 88rpx;
  304. font-size: 26rpx;
  305. .body_item{
  306. border-bottom: 1rpx solid #DEDEDE;
  307. padding: 24rpx;
  308. }
  309. }
  310. .zanwu{
  311. margin-bottom: 140rpx;
  312. margin-top: 88rpx;
  313. display: flex;
  314. justify-content: center;
  315. .newicon-zanwu{
  316. font-size: 256rpx;
  317. color: #D6D6D6;
  318. margin-top: 140rpx;
  319. }
  320. }
  321. .foot_common_btns{
  322. position: fixed;
  323. left: 0;
  324. bottom: 0;
  325. background-color: #fff;
  326. }
  327. }
  328. </style>