From 223644ebb8c5546c7b55ea86ff972898c0de835a Mon Sep 17 00:00:00 2001
From: zhangchen <1652267879@qq.com>
Date: 星期四, 24 七月 2025 21:09:30 +0800
Subject: [PATCH] ID1625-暂存
---
src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue | 12 +
src/views/mobile/bedsideAuxiliaryScreen/components/ScheduledTask.vue | 334 +++++++++++++++++++++++++++++++++++++
src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue | 29 +-
src/views/mobile/bedsideAuxiliaryScreen/components/TimePicker.vue | 119 +++++++++++++
4 files changed, 479 insertions(+), 15 deletions(-)
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
index 515c59b..f8d9a68 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
@@ -26,7 +26,7 @@
</template>
</div>
<div class="header-right">
- <img :src="atRegularTimeImg" class="btn-img" alt="" />
+ <img :src="atRegularTimeImg" class="btn-img" alt="" @click="openScheduledTaskDialog" />
<img
:src="setUpImg"
class="btn-img"
@@ -38,6 +38,8 @@
</div>
<!-- 设置设备编号组件 -->
<SettingDeviceDialog ref="settingDeviceDialogRef" />
+ <!-- 定时任务组件 -->
+ <ScheduledTaskDialog ref="scheduledTaskDialogRef" />
</template>
<script lang="ts" setup name="Header">
@@ -45,6 +47,9 @@
const SettingDeviceDialog = defineAsyncComponent(
() => import("./SettingDeviceDialog.vue")
);
+const ScheduledTaskDialog = defineAsyncComponent(
+ () => import("./ScheduledTask.vue")
+)
import atRegularTimeImg from "../../../../img/dingshi.png";
import setUpImg from "../../../../img/shezhi.png";
import userImg from "../../../../img/user.png";
@@ -56,6 +61,7 @@
const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
const settingDeviceDialogRef = ref<any>(null);
+const scheduledTaskDialogRef = ref<any>(null);
const pageType = computed(() => {
return bedsideAuxiliaryScreenStore.deviceData.pageType;
@@ -80,6 +86,10 @@
settingDeviceDialogRef.value?.openDialog();
};
+const openScheduledTaskDialog = () => {
+ scheduledTaskDialogRef.value?.openDialog();
+};
+
const openLoginDialog = () => {
ElMessage({
message: "功能开发中,敬请期待!",
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/ScheduledTask.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/ScheduledTask.vue
index e69de29..f284fa8 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/components/ScheduledTask.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/ScheduledTask.vue
@@ -0,0 +1,334 @@
+<template>
+ <div class="scheduled-task-container">
+ <el-dialog
+ v-model="isShow"
+ center
+ title="定时任务"
+ width="80%"
+ :show-close="false"
+ >
+ <template #header>
+ <div class="scheduled-task-header">
+ <span class="header-title">创建定时任务</span>
+ <img
+ :src="closeImg"
+ class="header-close"
+ @click="handleCancel"
+ alt=""
+ />
+ </div>
+ </template>
+ <div class="scheduled-task-content">
+ <div class="content-left">
+ <div class="content-left-date">
+ <TimePicker v-model="timeValue" />
+ <div class="date-btn"></div>
+ </div>
+ <div class="content-left-stereotyped-writing">
+ <div class="stereotyped-writing">
+ <input
+ v-model="taskName"
+ type="text"
+ :disabled="isInpDisabled"
+ class="stereotyped-writing-input"
+ placeholder="请输入自定义内容"
+ />
+ </div>
+ <div class="stereotyped-writing-list">
+ <div
+ v-for="(item, index) in taskOptions"
+ :key="index"
+ class="my-button list-item"
+ @click="onStereotypedWritingClick(item)"
+ :class="taskItemCheck === item.value ? 'check' : ''"
+ >
+ {{ item.label }}
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="content-right"></div>
+ </div>
+ <template #footer>
+ <div class="my-button cancel" @click="handleCancel">取消</div>
+ <div class="my-button confirm" @click="handleConfirm">确认</div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script lang="ts" setup>
+import { computed, ref } from "vue";
+// @ts-ignore
+import TimePicker from './TimePicker.vue'
+
+import closeImg from "@/img/close.png";
+import alertbaojin from "@/assets/alert.wav";
+import cxybaojing from "@/assets/cxy.mp3";
+import gybaojing from "@/assets/gy.mp3";
+import kclbaojing from "@/assets/kcl.mp3";
+import tdddbaojing from "@/assets/tzddd.mp3";
+import tzxllbaojing from "@/assets/tzxll.mp3";
+import cgbaojing from "@/assets/cg.mp3";
+
+interface TaskItem {
+ label: string;
+ value: string;
+ backgroundColor: string;
+ promptTone: string;
+}
+
+interface DateItem {
+ label: string;
+ value: number;
+}
+
+const isShow = ref(false);
+
+const taskName = ref(""); // 任务名称
+const isInpDisabled = ref(false); // 输入框是否禁用
+
+const timeValue = ref('19:16');
+
+const detaCheck = ref<number | null>(); // 这个是判断时间按钮的
+
+const taskOptions = ref<TaskItem[]>([
+ {
+ label: "测血压",
+ value: "测血压",
+ backgroundColor: "#E6A23C",
+ promptTone: cxybaojing,
+ },
+ {
+ label: "开超滤",
+ value: "开超滤",
+ backgroundColor: "#E6A23C",
+ promptTone: kclbaojing,
+ },
+ {
+ label: "给药",
+ value: "给药",
+ backgroundColor: "#E6A23C",
+ promptTone: gybaojing,
+ },
+ {
+ label: "调电导度",
+ value: "调电导度",
+ backgroundColor: "#E6A23C",
+ promptTone: tdddbaojing,
+ },
+ {
+ label: "调血流量",
+ value: "调血流量",
+ backgroundColor: "#E6A23C",
+ promptTone: tzxllbaojing,
+ },
+ {
+ label: "冲管",
+ value: "冲管",
+ backgroundColor: "#E6A23C",
+ promptTone: cgbaojing,
+ },
+]);
+
+
+const dateOptions = ref<DateItem[]>([
+ { label: '15分钟', value: 15 },
+ { label: '30分钟', value: 30 },
+ { label: '45分钟', value: 45 },
+ { label: '60分钟', value: 60 },
+]);
+
+const taskItemCheck = computed(() => {
+ return taskOptions.value.find((e) => e.value === taskName.value)?.value || "";
+});
+
+const openDialog = () => {
+ isShow.value = true;
+};
+
+const onStereotypedWritingClick = (item: TaskItem) => {
+ if (taskName.value === item.value) {
+ taskName.value = "";
+ isInpDisabled.value = false;
+ } else {
+ taskName.value = item.value;
+ isInpDisabled.value = true;
+ }
+};
+
+const handleCancel = () => {
+ isShow.value = false;
+};
+
+const handleConfirm = () => {};
+
+defineExpose({
+ openDialog,
+});
+</script>
+
+<style lang="less" scoped>
+* {
+ box-sizing: border-box;
+}
+.scheduled-task-container {
+ ::v-deep(.el-dialog) {
+ padding: 0;
+ border-radius: 6px;
+ overflow: hidden;
+ }
+ ::v-deep(.el-dialog__footer) {
+ padding: 4px;
+ }
+ ::v-deep(.el-upload-dragger) {
+ height: 65px;
+ padding: 0 !important;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ ::v-deep(.el-upload-dragger .el-icon--upload) {
+ display: none;
+ }
+ ::v-deep(.el-dialog__header) {
+ padding-bottom: 6px;
+ }
+ .scheduled-task-header {
+ position: relative;
+ height: 16px;
+ background: #ff7472;
+ .header-title {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translateX(-50%) translateY(-50%);
+ font-family: AlibabaPuHuiTi, AlibabaPuHuiTi;
+ font-weight: 500;
+ font-size: 8px;
+ color: #ffffff;
+ line-height: 11px;
+ text-align: center;
+ }
+ .header-close {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ right: 6px;
+ width: 15px;
+ height: 15px;
+ transition: transform 0.2s;
+
+ &:active {
+ opacity: 0.6;
+ transform: translateY(-50%) scale(0.95);
+ }
+ }
+ }
+ .scheduled-task-content {
+ padding: 0 12px 0px;
+ margin-bottom: 4px;
+ border-bottom: 1px solid #d8d8d8;
+ display: flex;
+ .content-left {
+ flex: 1;
+ border-right: 1px solid #d8d8d8;
+ padding-bottom: 6px;
+ padding-right: 12px;
+ .content-left-date {
+ border-bottom: 1px solid #d8d8d8;
+
+ }
+ .content-left-stereotyped-writing {
+ .stereotyped-writing {
+ position: relative;
+ height: 16px;
+ padding-top: 6px;
+ margin-bottom: 6px;
+ border-radius: 2px;
+ border: 1px solid #979797;
+ overflow: hidden;
+ .stereotyped-writing-input {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ border: none;
+ outline: none;
+ padding: 0 4px;
+ line-height: 16px;
+ font-size: 9px;
+ font-family: PingFangSC, PingFang SC;
+ vertical-align: middle;
+ box-sizing: border-box; // 避免padding撑高
+
+ &::placeholder {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+ color: #aaaaaa;
+ opacity: 1;
+ }
+ &:disabled {
+ background-color: #f5f5f5; // 灰色背景
+ color: #999999; // 灰色文字
+ cursor: not-allowed;
+ }
+ }
+ }
+ .stereotyped-writing-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 7px;
+ .list-item {
+ width: 40px;
+ margin-left: 0;
+ padding-left: 0;
+ padding-right: 0;
+ background-color: #e6a23c;
+ &.check {
+ background-color: #bbc6dd;
+ }
+ }
+ }
+ }
+ }
+ .content-right {
+ width: 59px;
+ }
+ }
+ .my-button {
+ display: inline-block;
+ border-radius: 2px;
+ padding: 0px 10px;
+ font-family: PingFangSC, PingFang SC;
+ font-weight: 500;
+ font-size: 7px;
+ color: #ffffff;
+ line-height: 16px;
+ letter-spacing: 1px;
+ text-align: center;
+ font-style: normal;
+ transition: transform 0.1s ease, opacity 0.1s ease;
+ cursor: pointer;
+ &:active {
+ transform: scale(0.95);
+ opacity: 0.8;
+ }
+
+ &:not(:first-child) {
+ margin-left: 6px;
+ }
+ &.cancel {
+ background: #bbc6dd;
+ }
+ &.confirm {
+ background: #769aff;
+ }
+ &.refresh {
+ background: #e6a23c;
+ }
+ }
+}
+</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/TimePicker.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/TimePicker.vue
new file mode 100644
index 0000000..74479f7
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/TimePicker.vue
@@ -0,0 +1,119 @@
+<template>
+ <div class="time-picker">
+ <div class="picker-column" ref="hourRef" @scroll="onScroll('hour')">
+ <div v-for="h in hours" :key="h" class="picker-item" :class="{ active: h === selectedHour }">{{ h.toString().padStart(2, '0') }}</div>
+ </div>
+ <span class="colon">:</span>
+ <div class="picker-column" ref="minuteRef" @scroll="onScroll('minute')">
+ <div v-for="m in minutes" :key="m" class="picker-item" :class="{ active: m === selectedMinute }">{{ m.toString().padStart(2, '0') }}</div>
+ </div>
+ </div>
+</template>
+
+<script setup lang="ts">
+import { ref, watch, onMounted, nextTick } from 'vue'
+
+interface Props {
+ modelValue: string // 格式为 "HH:mm"
+}
+const props = defineProps<Props>()
+const emit = defineEmits(['update:modelValue'])
+
+const selectedHour = ref(0)
+const selectedMinute = ref(0)
+const hourRef = ref<HTMLDivElement | null>(null)
+const minuteRef = ref<HTMLDivElement | null>(null)
+
+const hours = Array.from({ length: 24 }, (_, i) => i)
+const minutes = Array.from({ length: 60 }, (_, i) => i)
+
+function scrollTo(refEl: HTMLDivElement | null, index: number) {
+ if (!refEl) return
+ refEl.scrollTo({ top: index * 40, behavior: 'smooth' })
+}
+
+function updateModel() {
+ const value = `${selectedHour.value.toString().padStart(2, '0')}:${selectedMinute.value.toString().padStart(2, '0')}`
+ emit('update:modelValue', value)
+}
+
+function onScroll(type: 'hour' | 'minute') {
+ const el = type === 'hour' ? hourRef.value : minuteRef.value
+ if (!el) return
+
+ clearTimeout((el as any)._timer)
+ ;(el as any)._timer = setTimeout(() => {
+ const index = Math.round(el.scrollTop / 40)
+ if (type === 'hour') {
+ selectedHour.value = hours[index]
+ scrollTo(hourRef.value, index)
+ } else {
+ selectedMinute.value = minutes[index]
+ scrollTo(minuteRef.value, index)
+ }
+ updateModel()
+ }, 100)
+}
+
+watch(
+ () => props.modelValue,
+ (newVal) => {
+ if (!newVal) return
+ const [h, m] = newVal.split(':').map(Number)
+ selectedHour.value = h
+ selectedMinute.value = m
+ nextTick(() => {
+ scrollTo(hourRef.value, h)
+ scrollTo(minuteRef.value, m)
+ })
+ },
+ { immediate: true }
+)
+</script>
+
+<style scoped>
+.time-picker {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 200px;
+ background: #e6efff;
+ font-family: sans-serif;
+}
+
+.picker-column {
+ width: 60px;
+ height: 200px;
+ overflow-y: scroll;
+ scroll-snap-type: y mandatory;
+ -webkit-overflow-scrolling: touch;
+ text-align: center;
+ position: relative;
+ padding-top: 80px;
+ padding-bottom: 80px;
+}
+
+.picker-item {
+ height: 40px;
+ line-height: 40px;
+ font-size: 14px;
+ color: #666;
+ scroll-snap-align: center;
+ transition: all 0.2s;
+ transform: scale(0.8);
+ opacity: 0.5;
+}
+
+.picker-item.active {
+ font-size: 24px;
+ font-weight: bold;
+ color: #333;
+ transform: scale(1.2);
+ opacity: 1;
+}
+
+.colon {
+ font-size: 24px;
+ margin: 0 10px;
+}
+</style>
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue b/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue
index 2c67b9e..b05d642 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue
@@ -394,9 +394,13 @@
);
});
-watch(() => pageData.value.ktvList, (newVal) => {
+watch(
+ () => pageData.value.ktvList,
+ (newVal) => {
generateKtvListEchart(newVal);
-}, { deep: true });
+ },
+ { deep: true }
+);
watch(
() => pageData.value.monitoringRecord,
@@ -487,9 +491,9 @@
const option = {
grid: [
- { top: "20%", height: "27%", left: 30, right: 20 }, // 伸缩压
- { top: "45%", height: "27%", left: 30, right: 20 }, // 舒张压
- { top: "67%", height: "27%", left: 30, right: 20 }, // 脉搏
+ { top: "10%", height: "25%", left: 30, right: 20 },
+ { top: "38%", height: "25%", left: 30, right: 20 },
+ { top: "66%", height: "25%", left: 30, right: 20 },
],
tooltip: {
trigger: "axis",
@@ -534,9 +538,8 @@
axisTick: { show: false },
axisLabel: { show: false },
splitLine: { show: false },
- min: 80,
- max: 180,
- interval: 20,
+ min: "dataMin", // 自动以数据最小值为最小值
+ max: "dataMax",
gridIndex: 0,
},
{
@@ -546,9 +549,8 @@
axisTick: { show: false },
axisLabel: { show: false },
splitLine: { show: false },
- min: 40,
- max: 120,
- interval: 20,
+ min: "dataMin", // 自动以数据最小值为最小值
+ max: "dataMax",
gridIndex: 1,
},
{
@@ -558,9 +560,8 @@
axisTick: { show: false },
axisLabel: { show: false },
splitLine: { show: false },
- min: 40,
- max: 140,
- interval: 20,
+ min: "dataMin", // 自动以数据最小值为最小值
+ max: "dataMax",
gridIndex: 2,
},
],
--
Gitblit v1.8.0