|
@@ -1,11 +1,237 @@
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
|
+import { createReusableTemplate } from '@vueuse/core';
|
|
|
|
|
|
|
|
+import { useForm, useRequest, useWatcher } from 'alova/client';
|
|
|
|
+import { getPutawayDataMethod, notifyGetawayDataMethod, setGetawayDataMethod, setPutawayDataMethod } from '@/api/pda.api.ts';
|
|
|
|
+
|
|
|
|
+import { useStepStore } from '@/stores';
|
|
|
|
+
|
|
|
|
+import { type ScanData, scanKey } from '@/core/hook/useScan.ts';
|
|
|
|
+import { showConfirmDialog, showFailToast, showSuccessToast } from 'vant';
|
|
|
|
+
|
|
|
|
+const emits = defineEmits<{ back: [delta?: number] }>();
|
|
|
|
+
|
|
|
|
+const storeStore = useStepStore();
|
|
|
|
+const { dataset } = storeToRefs(storeStore);
|
|
|
|
+
|
|
|
|
+const {
|
|
|
|
+ loading: submitting,
|
|
|
|
+ form: model,
|
|
|
|
+ send, reset,
|
|
|
|
+} = useForm(setPutawayDataMethod, { immediate: false, initialForm: { no: '', cabinet: '' } })
|
|
|
|
+ .onSuccess(({ data: { cabinet } }) => {
|
|
|
|
+ data.value.cabinet = cabinet;
|
|
|
|
+ showSuccessToast(`操作成功`);
|
|
|
|
+ })
|
|
|
|
+ .onError(({ error: message }) => {
|
|
|
|
+ model.value.cabinet = '';
|
|
|
|
+ showFailToast({ message });
|
|
|
|
+ })
|
|
|
|
+ .onComplete(() => {
|
|
|
|
+ panelHeight.value = panelAnchors[panelAnchors.length - 1];
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+const { data, loading } = useWatcher(() => getPutawayDataMethod(dataset.value?.no!), [dataset], {
|
|
|
|
+ immediate: true,
|
|
|
|
+ initialData: {},
|
|
|
|
+ middleware: (_, next) => dataset.value?.no && next(),
|
|
|
|
+})
|
|
|
|
+ .onSuccess(({ data }) => {
|
|
|
|
+ const patient = dataset.value?.patient;
|
|
|
|
+ const prescription = dataset.value?.prescription;
|
|
|
|
+ if (patient) Object.assign(patient, data.patient);
|
|
|
|
+ if (prescription) Object.assign(prescription, data.prescription);
|
|
|
|
+
|
|
|
|
+ model.value.no = data.no;
|
|
|
|
+ })
|
|
|
|
+ .onError(({ error: message }) => {
|
|
|
|
+ showDialog({ title: '温馨提示', message, closeOnClickOverlay: true }).then(() => emits('back'));
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+const { loading: getawayLoading, send: _getaway } = useRequest(() => setGetawayDataMethod(data.value), { immediate: false }).onSuccess(({ data }) => {
|
|
|
|
+ showSuccessToast(data);
|
|
|
|
+ emits('back');
|
|
|
|
+});
|
|
|
|
+const { loading: broadcastLoading, send: _broadcast } = useRequest(() => notifyGetawayDataMethod(data.value), { immediate: false }).onSuccess(({ data }) => {
|
|
|
|
+ showSuccessToast(data);
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+const getaway = () => {
|
|
|
|
+ showConfirmDialog({
|
|
|
|
+ title: '确认取药吗?',
|
|
|
|
+ confirmButtonText: '取药',
|
|
|
|
+ }).then(_getaway)
|
|
|
|
+}
|
|
|
|
+const broadcast = () => {
|
|
|
|
+ showConfirmDialog({
|
|
|
|
+ title: '确认通知取药吗?',
|
|
|
|
+ confirmButtonText: '通知',
|
|
|
|
+ }).then(_broadcast)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* 可上架 */
|
|
|
|
+const setable = computed(() => data.value?.cabinet == null);
|
|
|
|
+/* 可扫描 */
|
|
|
|
+const scannable = computed(() => setable && panelHeight.value > 0);
|
|
|
|
+const scan = inject(scanKey, void 0);
|
|
|
|
+
|
|
|
|
+defineExpose({
|
|
|
|
+ getScan: () =>
|
|
|
|
+ scannable.value
|
|
|
|
+ ? (data: ScanData) => {
|
|
|
|
+ model.value.cabinet = data.code;
|
|
|
|
+ send();
|
|
|
|
+ }
|
|
|
|
+ : void 0,
|
|
|
|
+ reset,
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+const [DefineTemplate, ReuseTemplate] = createReusableTemplate<{ show?: boolean }>();
|
|
|
|
+
|
|
|
|
+const panelHeight = ref(0);
|
|
|
|
+const panelAnchors = reactive([0, 100, Math.min(window.innerHeight * 0.8, 480)]);
|
|
|
|
+
|
|
|
|
+const start = () => {
|
|
|
|
+ if (!data.value.cabinet) {
|
|
|
|
+ panelHeight.value = 100;
|
|
|
|
+ nextTick(() => scan?.());
|
|
|
|
+ }
|
|
|
|
+};
|
|
</script>
|
|
</script>
|
|
|
|
|
|
<template>
|
|
<template>
|
|
- $END$
|
|
|
|
|
|
+ <van-toast :show="loading" type="loading" forbid-click />
|
|
|
|
+
|
|
|
|
+ <DefineTemplate v-slot="{ show }">
|
|
|
|
+ <div class="card-wrapper">
|
|
|
|
+ <div class="flex" v-if="data?.cabinet || show">
|
|
|
|
+ <div class="cell"></div>
|
|
|
|
+ <div class="row flex-auto text-center">行{{ data?.cabinet?.row }}</div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex">
|
|
|
|
+ <div v-if="data?.cabinet || show" class="col flex flex-col justify-center text-center">列{{ data?.cabinet?.col }}</div>
|
|
|
|
+ <div class="flex-auto">
|
|
|
|
+ <van-button v-if="data?.cabinet" type="success" block @click="getaway()">柜号:{{ data?.cabinet?.no }}</van-button>
|
|
|
|
+ <van-cell-group>
|
|
|
|
+ <van-cell title="患者">
|
|
|
|
+ <template #value>
|
|
|
|
+ <div>
|
|
|
|
+ <span v-if="dataset?.patient?.name" class="font-semibold" data-snippet=",">{{ dataset?.patient?.name }}</span>
|
|
|
|
+ <span v-if="dataset?.patient?.gender" class="font-semibold" data-snippet=",">{{ dataset?.patient?.gender }}</span>
|
|
|
|
+ <span v-if="dataset?.patient?.age" class="font-semibold" data-snippet=",">{{ dataset?.patient?.age }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ </van-cell>
|
|
|
|
+ <van-cell title="出生日期" :value="dataset?.patient?.birthdate" />
|
|
|
|
+ <van-cell title="类型" :value="dataset?.prescription?.classes ?? dataset?.prescription?.category" />
|
|
|
|
+ <van-cell title="剂数" :value="dataset?.prescription?.count" />
|
|
|
|
+ <van-cell title="是否代煎" :value="dataset?.prescription?.decoction" />
|
|
|
|
+ <van-cell title="开方医生" :value="dataset?.doctor?.name" />
|
|
|
|
+ </van-cell-group>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <van-cell v-if="data?.cabinet" title="温馨提示:" label="若需要解绑处方,请通过 PC 端处理!" />
|
|
|
|
+ </DefineTemplate>
|
|
|
|
+
|
|
|
|
+ <div class="wrapper">
|
|
|
|
+ <ReuseTemplate />
|
|
|
|
+
|
|
|
|
+ <template v-if="!loading">
|
|
|
|
+ <div class="flex my-4 px-4 gap-4">
|
|
|
|
+ <van-button type="warning" block :loading="broadcastLoading" @click="broadcast()">通知取药</van-button>
|
|
|
|
+ <van-button type="success" block :loading="getawayLoading" @click="getaway()">取药</van-button>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-if="setable" class="flex my-4 px-4 gap-4">
|
|
|
|
+ <van-button type="primary" block @click="start()">上柜</van-button>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+
|
|
|
|
+ <van-overlay :show="scannable" @click.self="panelHeight = 0">
|
|
|
|
+ <van-floating-panel lock-scroll v-model:height="panelHeight" :anchors="panelAnchors">
|
|
|
|
+ <template #header>
|
|
|
|
+ <div class="van-floating-panel__header flex-col">
|
|
|
|
+ <div class="van-floating-panel__header-bar"></div>
|
|
|
|
+ <div class="mt-2">上柜</div>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+
|
|
|
|
+ <van-field
|
|
|
|
+ v-if="setable"
|
|
|
|
+ label="扫描柜号"
|
|
|
|
+ :readonly="submitting || !!data.cabinet"
|
|
|
|
+ placeholder="请使用设备按钮进行扫码"
|
|
|
|
+ input-align="center"
|
|
|
|
+ v-model="model.cabinet"
|
|
|
|
+ enterkeyhint="done"
|
|
|
|
+ @keydown.enter="send()"
|
|
|
|
+ :right-icon="setable ? 'scan' : ''"
|
|
|
|
+ @click-right-icon="scan && scan()"
|
|
|
|
+ />
|
|
|
|
+ <div class="mt-4 px-4">
|
|
|
|
+ <ReuseTemplate :show="true" />
|
|
|
|
+ <div v-if="setable" class="mt-4">
|
|
|
|
+ <van-button class="mt-2" type="primary" block :loading="submitting" @click="send()">上柜</van-button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </van-floating-panel>
|
|
|
|
+ </van-overlay>
|
|
|
|
+ </div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
<style scoped lang="scss">
|
|
|
|
+span[data-snippet] + span[data-snippet]::before {
|
|
|
|
+ content: attr(data-snippet);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.wrapper {
|
|
|
|
+ padding: var(--van-cell-vertical-padding) var(--van-cell-horizontal-padding);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.card-wrapper {
|
|
|
|
+ $border: 1px solid var(--van-cell-border-color);
|
|
|
|
+
|
|
|
|
+ --p: 8px;
|
|
|
|
+ --s: calc(var(--p) * 2 + 1em);
|
|
|
|
+ --van-cell-border-color: var(--van-border-color);
|
|
|
|
+
|
|
|
|
+ .cell {
|
|
|
|
+ width: var(--s);
|
|
|
|
+ height: var(--s);
|
|
|
|
+ border-right: $border;
|
|
|
|
+ border-bottom: $border;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .row {
|
|
|
|
+ padding: calc(var(--p) - 1px) 0;
|
|
|
|
+ font-weight: 600;
|
|
|
|
+ line-height: 1em;
|
|
|
|
+ letter-spacing: 0.5em;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .col {
|
|
|
|
+ padding: 0 calc(var(--p) - 1px);
|
|
|
|
+ width: calc(1em + 1px);
|
|
|
|
+ font-weight: 600;
|
|
|
|
+ line-height: 2em;
|
|
|
|
+ box-sizing: content-box;
|
|
|
|
+ border-right: $border;
|
|
|
|
+ border-bottom: $border;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ :deep(.van-cell) {
|
|
|
|
+ .van-cell__title {
|
|
|
|
+ color: var(--van-cell-value-color);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .van-cell__value {
|
|
|
|
+ color: var(--van-cell-text-color);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
|
|
+.van-floating-panel__header {
|
|
|
|
+ --van-floating-panel-header-height: 50px;
|
|
|
|
+ color: var(--van-text-color-2);
|
|
|
|
+}
|
|
</style>
|
|
</style>
|