|
|
<template>
|
|
|
<el-dialog :model-value="modelValue" class="hospital-order-form-dialog" :close-on-click-modal="true"
|
|
|
@update:model-value="(v) => $emit('update:modelValue', v)" @closed="onClosed">
|
|
|
<div class="body-wrap">
|
|
|
<div class="body-header">
|
|
|
<div class="body-title">{{ isEdit() ? '编辑工单' : '新建工单' }}</div>
|
|
|
<img src="@/assets/image/close-btn.svg" alt="" class="close-btn" @click="onCancel" />
|
|
|
</div>
|
|
|
|
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
|
|
<!-- 第一行 2 列:服务类型 + 反馈渠道(医院端没有"所属医院") -->
|
|
|
<el-row :gutter="20">
|
|
|
<el-col :span="12">
|
|
|
<el-form-item :label="$t('label.type')" prop="serviceType">
|
|
|
<el-select v-model="form.serviceType" :placeholder="$t('placeholder.type')" clearable style="width: 100%">
|
|
|
<el-option label="故障报修" value="故障报修" />
|
|
|
<el-option label="业务咨询" value="业务咨询" />
|
|
|
<el-option label="需求变更" value="需求变更" />
|
|
|
<el-option label="其他" value="其他" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
<el-col :span="12">
|
|
|
<el-form-item :label="$t('label.feedbackchannel')" prop="feedbackchannel">
|
|
|
<el-select v-model="form.feedbackchannel" :placeholder="$t('placeholder.feedbackchannel')" clearable
|
|
|
style="width: 100%">
|
|
|
<el-option label="微信群" value="微信群" />
|
|
|
<el-option label="微信" value="微信" />
|
|
|
<el-option label="电话" value="电话" />
|
|
|
<el-option label="现场" value="现场" />
|
|
|
<el-option label="钉钉群" value="钉钉群" />
|
|
|
<el-option label="钉钉" value="钉钉" />
|
|
|
<el-option label="其他" value="其他" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
<!-- 第二行 3 列:科室 + 提单人 + 提交时间 -->
|
|
|
<el-row :gutter="20">
|
|
|
<el-col :span="8">
|
|
|
<el-form-item :label="$t('label.dept')" prop="department">
|
|
|
<el-input v-model="form.department" :placeholder="$t('placeholder.dept')" />
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
<el-col :span="8">
|
|
|
<el-form-item :label="$t('label.name')" prop="submitter">
|
|
|
<el-input v-model="form.submitter" :placeholder="$t('placeholder.name')" />
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
<el-col :span="8">
|
|
|
<el-form-item :label="$t('label.createat')" prop="createdat">
|
|
|
<el-date-picker v-model="form.createdat" type="datetime" :placeholder="$t('placeholder.createat')"
|
|
|
value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" style="width: 100%" />
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
<!-- 标题 + 颜色标签 + 优先级 同一行 -->
|
|
|
<el-form-item :label="$t('label.title')" prop="title">
|
|
|
<div class="title-row">
|
|
|
<el-input v-model="form.title" :placeholder="$t('placeholder.title')" maxlength="300" class="title-input">
|
|
|
<template #suffix>
|
|
|
<span class="title-counter"><span :style="{ color: form.colorTag || '#dcdfe6' }">{{ form.title.length
|
|
|
}}</span>/300</span>
|
|
|
<el-popover v-model:visible="colorPickerVisible" :width="180" placement="bottom-end" trigger="click"
|
|
|
:show-arrow="false" popper-class="color-tag-popper">
|
|
|
<template #reference>
|
|
|
<el-badge :color="form.colorTag || '#dcdfe6'" is-dot class="item">
|
|
|
<img src="@/assets/image/admin/orders/sepan.svg" alt="" class="title-sepan" />
|
|
|
</el-badge>
|
|
|
</template>
|
|
|
<div class="color-tag-title">{{ $t('label.colorTag') }}</div>
|
|
|
<div class="color-tag-options">
|
|
|
<div v-for="c in colorOptions" :key="c.value" class="color-tag-option"
|
|
|
:class="{ active: form.colorTag === c.value }" :style="{ background: c.value }" :title="c.label"
|
|
|
@click="selectColor(c.value)"></div>
|
|
|
</div>
|
|
|
</el-popover>
|
|
|
</template>
|
|
|
</el-input>
|
|
|
<div class="priority-wrap">
|
|
|
<div class="priority-label">{{ $t('label.priority') }}</div>
|
|
|
<el-select v-model="form.priority" class="priority-select" :teleported="false">
|
|
|
<template #label="{ label, value }">
|
|
|
<div class="priority-row high" v-if="value === '高'">{{ value }}</div>
|
|
|
<div class="priority-row medium" v-if="value === '中'">{{ value }}</div>
|
|
|
<div class="priority-row low" v-if="value === '低'">{{ value }}</div>
|
|
|
</template>
|
|
|
<el-option v-for="opt in priorityOptions" :key="opt.value" :value="opt.value">
|
|
|
<span class="priority-option">
|
|
|
<span class="priority-dot" :class="opt.cls"></span>
|
|
|
<span class="priority-option-label">{{ opt.label }}</span>
|
|
|
</span>
|
|
|
</el-option>
|
|
|
</el-select>
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
<el-form-item :label="$t('label.description')" prop="description">
|
|
|
<div class="rich-editor">
|
|
|
<Toolbar :editor="editorRef" :default-config="toolbarConfig" mode="default"
|
|
|
style="border-bottom: 1px solid #dcdfe6" />
|
|
|
<Editor v-model="form.description" :default-config="editorConfig" mode="default"
|
|
|
style="height: 200px; overflow-y: auto" @on-created="handleEditorCreated"
|
|
|
@custom-paste="handleEditorPasteImage" />
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
<el-form-item class="fujian" :label="$t('label.attachment')">
|
|
|
<el-upload class="upload-wrap" v-model:file-list="form.files" :auto-upload="false" :limit="1"
|
|
|
:on-exceed="handleAttachmentExceed" :on-remove="handleAttachmentRemove" :on-change="handleAttachmentChange">
|
|
|
<div class="upload-btn">
|
|
|
<div class="left">+ 添加文件</div>
|
|
|
<div class="right">{{ $t('label.attachmentTip') }}</div>
|
|
|
</div>
|
|
|
<template #file="{ file }">
|
|
|
<div class="file-item">
|
|
|
<img class="file-icon" src="@/assets/image/admin/orders/file.svg" alt="">
|
|
|
<div class="file-name"> {{ file.name }}</div>
|
|
|
<div class="file-size"> {{ ((file.size || 0) / 1024 / 1024).toFixed(2) }}MB</div>
|
|
|
<div class="file-delete" @click="handleAttachmentDelete(file)">删除</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-upload>
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
</div>
|
|
|
<div class="body-footer">
|
|
|
<el-button @click="onCancel">{{ $t('common.cancel') }}</el-button>
|
|
|
<el-button type="primary" :loading="submitting" @click="submit">
|
|
|
{{ $t('common.submit') }}
|
|
|
</el-button>
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import dayjs from "dayjs";
|
|
|
import {
|
|
|
nextTick,
|
|
|
onBeforeUnmount,
|
|
|
reactive,
|
|
|
ref,
|
|
|
shallowRef,
|
|
|
watch,
|
|
|
} from "vue";
|
|
|
import { ElMessage } from "element-plus";
|
|
|
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
|
|
|
import "@wangeditor/editor/dist/css/style.css";
|
|
|
import { useI18n } from "vue-i18n";
|
|
|
import {
|
|
|
createHospitalOrder,
|
|
|
getHospitalOrderDetail,
|
|
|
updateHospitalOrder,
|
|
|
getPoints,
|
|
|
} from "@/service/modular/hospital";
|
|
|
import { useRewardResultStore } from "@/stores/rewardResult";
|
|
|
import iconSubmit from "@/assets/image/hospital/ponits/icon-submit-large.svg";
|
|
|
|
|
|
const props = defineProps({
|
|
|
modelValue: { type: Boolean, default: false },
|
|
|
orderId: { type: [String, Number], default: null },
|
|
|
});
|
|
|
const emit = defineEmits(["update:modelValue", "success"]);
|
|
|
|
|
|
const { t: $t } = useI18n();
|
|
|
|
|
|
const isEdit = () => !!props.orderId;
|
|
|
const formRef = ref();
|
|
|
const submitting = ref(false);
|
|
|
|
|
|
// 已加载的原始附件 filePath 集合(用于判断用户是否需要保留原附件)
|
|
|
const originalAttachments = ref([]);
|
|
|
|
|
|
const rewardResultStore = useRewardResultStore();
|
|
|
|
|
|
const getAttachmentFileName = (path) => {
|
|
|
if (!path) return "";
|
|
|
return String(path).replace(/\\/g, "/").split("/").pop() || "";
|
|
|
};
|
|
|
|
|
|
// 根据后端返回填充表单(编辑模式)
|
|
|
const fillFormFromDetail = (detail) => {
|
|
|
if (!detail) return;
|
|
|
form.title = detail.title || "";
|
|
|
form.serviceType = detail.serviceType || "";
|
|
|
form.priority = detail.priority || "中";
|
|
|
form.feedbackchannel = detail.feedbackChannel || detail.feedbackchannel || "";
|
|
|
form.department = detail.department || "";
|
|
|
form.colorTag = detail.colorTag || "#667eea";
|
|
|
form.description = detail.description || "";
|
|
|
form.submitter = detail.submitter || "";
|
|
|
form.createdat = detail.createdAt
|
|
|
? dayjs(detail.createdAt).format("YYYY-MM-DD HH:mm:ss")
|
|
|
: "";
|
|
|
// 附件回显
|
|
|
const atts = detail.attachments || [];
|
|
|
originalAttachments.value = atts.map((a) => a.filePath).filter(Boolean);
|
|
|
if (atts.length) {
|
|
|
const first = atts[0];
|
|
|
const fileName = first.fileName || getAttachmentFileName(first.filePath);
|
|
|
if (fileName) {
|
|
|
form.files = [
|
|
|
{
|
|
|
uid: `attachment-${props.orderId}-0`,
|
|
|
name: fileName,
|
|
|
status: "success",
|
|
|
size: first.fileSize || 0,
|
|
|
},
|
|
|
];
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
form.files = [];
|
|
|
};
|
|
|
|
|
|
const loadDetail = async (id) => {
|
|
|
try {
|
|
|
const res = await getHospitalOrderDetail(id);
|
|
|
fillFormFromDetail(res);
|
|
|
} catch (_) {
|
|
|
ElMessage.error("加载工单详情失败");
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const form = reactive({
|
|
|
title: "",
|
|
|
serviceType: "",
|
|
|
priority: "中",
|
|
|
feedbackchannel: "",
|
|
|
department: "",
|
|
|
colorTag: "#667eea",
|
|
|
description: "",
|
|
|
submitter: "",
|
|
|
createdat: "",
|
|
|
files: [],
|
|
|
});
|
|
|
|
|
|
const rules = {
|
|
|
title: [{ required: true, message: () => $t('msg.pleaseInputTitle'), trigger: "blur" }],
|
|
|
serviceType: [{ required: true, message: () => $t('msg.pleaseSelectType'), trigger: "change" }],
|
|
|
priority: [{ required: true, message: () => $t('msg.pleaseSelectPriority'), trigger: "change" }],
|
|
|
feedbackchannel: [
|
|
|
{ required: true, message: () => $t('msg.pleaseSelectFeedbackChannel'), trigger: "change" },
|
|
|
],
|
|
|
department: [
|
|
|
{ required: true, whitespace: true, message: () => $t('msg.pleaseInputDept'), trigger: "blur" },
|
|
|
],
|
|
|
submitter: [
|
|
|
{ required: true, whitespace: true, message: () => $t('msg.pleaseInputName'), trigger: "blur" },
|
|
|
],
|
|
|
description: [
|
|
|
{
|
|
|
required: true,
|
|
|
validator: (_, value, callback) => {
|
|
|
const hasImage = /<img\s/i.test(value || "");
|
|
|
const text = (value || "")
|
|
|
.replace(/<[^>]*>/g, "")
|
|
|
.replace(/ /gi, "")
|
|
|
.trim();
|
|
|
if (!text && !hasImage) return callback(new Error($t('msg.pleaseInputDescription')));
|
|
|
callback();
|
|
|
},
|
|
|
trigger: "change",
|
|
|
},
|
|
|
],
|
|
|
};
|
|
|
|
|
|
// 颜色标签可选值
|
|
|
const colorOptions = [
|
|
|
{ label: "蓝", value: "#667eea" },
|
|
|
{ label: "绿", value: "#52c41a" },
|
|
|
{ label: "青", value: "#13c2c2" },
|
|
|
{ label: "紫", value: "#722ed1" },
|
|
|
{ label: "橙", value: "#fa8c16" },
|
|
|
{ label: "红", value: "#ff4d4f" },
|
|
|
];
|
|
|
const colorPickerVisible = ref(false);
|
|
|
const selectColor = (val) => {
|
|
|
form.colorTag = val;
|
|
|
colorPickerVisible.value = false;
|
|
|
};
|
|
|
|
|
|
// 优先级可选值(带高/中/低配色 cls)
|
|
|
const priorityOptions = [
|
|
|
{ label: "高", value: "高", cls: "high" },
|
|
|
{ label: "中", value: "中", cls: "medium" },
|
|
|
{ label: "低", value: "低", cls: "low" },
|
|
|
];
|
|
|
|
|
|
const MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
|
const MAX_PASTE_IMAGE_SIZE = 5 * 1024 * 1024;
|
|
|
|
|
|
const handleAttachmentChange = (file) => {
|
|
|
if (file?.size > MAX_FILE_SIZE) {
|
|
|
ElMessage.warning("文件不能超过 50MB");
|
|
|
form.files = form.files.filter(
|
|
|
(f) => f.uid !== file.uid || f.size <= MAX_FILE_SIZE,
|
|
|
);
|
|
|
}
|
|
|
};
|
|
|
const handleAttachmentExceed = () => {
|
|
|
ElMessage.warning("只能上传 1 个文件");
|
|
|
};
|
|
|
const handleAttachmentRemove = () => {
|
|
|
// el-upload 会自动从 v-model:file-list 移除
|
|
|
};
|
|
|
const handleAttachmentDelete = (file) => {
|
|
|
// 自定义"删除"按钮:按 uid 从 form.files 中移除(与 admin 端保持一致)
|
|
|
form.files = (form.files || []).filter((f) => f.uid !== file?.uid);
|
|
|
};
|
|
|
|
|
|
const nowDatetime = () => dayjs().format("YYYY-MM-DD HH:mm:ss");
|
|
|
|
|
|
// 富文本编辑器配置
|
|
|
const editorRef = shallowRef();
|
|
|
const toolbarConfig = {
|
|
|
excludeKeys: [
|
|
|
"uploadImage",
|
|
|
"insertVideo",
|
|
|
"uploadVideo",
|
|
|
"group-video",
|
|
|
"emotion",
|
|
|
"group-emoji",
|
|
|
],
|
|
|
};
|
|
|
|
|
|
const collectPastedImages = (clipboardData) => {
|
|
|
const files = [];
|
|
|
const items = clipboardData?.items;
|
|
|
if (items) {
|
|
|
for (let i = 0; i < items.length; i++) {
|
|
|
const item = items[i];
|
|
|
if (item.kind === "file" && item.type?.startsWith("image/")) {
|
|
|
const file = item.getAsFile();
|
|
|
if (file) files.push(file);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if (files.length === 0 && clipboardData?.files) {
|
|
|
for (let i = 0; i < clipboardData.files.length; i++) {
|
|
|
const file = clipboardData.files[i];
|
|
|
if (file.type?.startsWith("image/")) files.push(file);
|
|
|
}
|
|
|
}
|
|
|
return files;
|
|
|
};
|
|
|
|
|
|
const handleEditorPasteImage = (editor, event) => {
|
|
|
if (event.__wpsImageHandled) return;
|
|
|
const imageFiles = collectPastedImages(event.clipboardData);
|
|
|
if (imageFiles.length === 0) return;
|
|
|
event.__wpsImageHandled = true;
|
|
|
event.preventDefault();
|
|
|
if (typeof event.stopPropagation === "function") event.stopPropagation();
|
|
|
if (typeof event.stopImmediatePropagation === "function")
|
|
|
event.stopImmediatePropagation();
|
|
|
|
|
|
if (typeof editor.focus === "function") editor.focus();
|
|
|
const savedSelection = editor.selection;
|
|
|
|
|
|
imageFiles.forEach((file) => {
|
|
|
if (file.size > MAX_PASTE_IMAGE_SIZE) {
|
|
|
ElMessage.warning("粘贴的图片不能超过 5MB");
|
|
|
return;
|
|
|
}
|
|
|
const reader = new FileReader();
|
|
|
reader.onload = (e) => {
|
|
|
const dataUrl = e.target?.result;
|
|
|
if (!dataUrl) {
|
|
|
ElMessage.error("图片读取失败");
|
|
|
return;
|
|
|
}
|
|
|
try {
|
|
|
if (savedSelection) editor.select(savedSelection);
|
|
|
} catch (_) {
|
|
|
if (typeof editor.focus === "function") editor.focus();
|
|
|
}
|
|
|
if (typeof editor.focus === "function") editor.focus();
|
|
|
editor.dangerouslyInsertHtml(
|
|
|
`<img src="${dataUrl}" style="max-width:100%;height:auto;" />`,
|
|
|
);
|
|
|
if (typeof editor.updateView === "function") editor.updateView();
|
|
|
};
|
|
|
reader.onerror = () => {
|
|
|
ElMessage.error("图片处理失败");
|
|
|
};
|
|
|
reader.readAsDataURL(file);
|
|
|
});
|
|
|
return false;
|
|
|
};
|
|
|
|
|
|
const editorConfig = {
|
|
|
placeholder: $t('placeholder.description'),
|
|
|
};
|
|
|
let pasteHandlerRef = null;
|
|
|
const handleEditorCreated = (editor) => {
|
|
|
editorRef.value = editor;
|
|
|
nextTick(() => {
|
|
|
const root = typeof editor.$el === "function" ? editor.$el() : editor.$el;
|
|
|
if (!root) return;
|
|
|
const editable = root.querySelector?.('[contenteditable="true"]') || root;
|
|
|
if (pasteHandlerRef) {
|
|
|
editable.removeEventListener("paste", pasteHandlerRef, { capture: true });
|
|
|
}
|
|
|
pasteHandlerRef = (event) => handleEditorPasteImage(editor, event);
|
|
|
editable.addEventListener("paste", pasteHandlerRef, { capture: true });
|
|
|
});
|
|
|
};
|
|
|
|
|
|
// ============== 取最新积分 ==============
|
|
|
const fetchLatestPoints = async () => {
|
|
|
try {
|
|
|
const res = await getPoints();
|
|
|
const data = res?.data ?? res ?? {};
|
|
|
return Number(data.totalPoints) || 0;
|
|
|
} catch (_) {
|
|
|
return 0;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const submit = async () => {
|
|
|
form.department = (form.department || "").trim();
|
|
|
form.submitter = (form.submitter || "").trim();
|
|
|
await formRef.value.validate(async (valid) => {
|
|
|
if (!valid) return;
|
|
|
submitting.value = true;
|
|
|
try {
|
|
|
const formData = new FormData();
|
|
|
const { files, ...rest } = form;
|
|
|
for (const [k, v] of Object.entries(rest)) {
|
|
|
if (v !== undefined && v !== null && v !== "") {
|
|
|
formData.append(k, v);
|
|
|
}
|
|
|
}
|
|
|
for (const f of files || []) {
|
|
|
if (f.raw) formData.append("files", f.raw, f.name);
|
|
|
}
|
|
|
if (isEdit()) {
|
|
|
await updateHospitalOrder(props.orderId, formData);
|
|
|
ElMessage.success("编辑成功");
|
|
|
emit("update:modelValue", false);
|
|
|
emit("success", { isEdit: true });
|
|
|
} else {
|
|
|
await createHospitalOrder(formData);
|
|
|
ElMessage.success($t('msg.submitSuccess'));
|
|
|
// 取最新积分,关闭自己,打开全局奖励结果弹窗
|
|
|
const totalPoints = await fetchLatestPoints();
|
|
|
emit("update:modelValue", false);
|
|
|
setTimeout(() => {
|
|
|
rewardResultStore.open({
|
|
|
title: "提交工单",
|
|
|
icon: iconSubmit,
|
|
|
points: 1,
|
|
|
batchGoal: 500,
|
|
|
batchCurrent: totalPoints,
|
|
|
rewardName: "康小虎 AI 吉祥物",
|
|
|
});
|
|
|
}, 100);
|
|
|
emit("success", { isCreate: true });
|
|
|
}
|
|
|
} finally {
|
|
|
submitting.value = false;
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
|
|
|
const onCancel = () => {
|
|
|
emit("update:modelValue", false);
|
|
|
};
|
|
|
|
|
|
const onClosed = () => {
|
|
|
// 关闭时重置表单(编辑模式下重新打开会重新加载详情)
|
|
|
form.title = "";
|
|
|
form.serviceType = "";
|
|
|
form.priority = "中";
|
|
|
form.feedbackchannel = "";
|
|
|
form.department = "";
|
|
|
form.colorTag = "#667eea";
|
|
|
form.description = "";
|
|
|
form.submitter = "";
|
|
|
form.createdat = "";
|
|
|
form.files = [];
|
|
|
originalAttachments.value = [];
|
|
|
};
|
|
|
|
|
|
// 打开时根据 orderId 决定加载模式
|
|
|
watch(
|
|
|
() => [props.modelValue, props.orderId],
|
|
|
([visible, id]) => {
|
|
|
if (!visible) return;
|
|
|
if (id) {
|
|
|
loadDetail(id);
|
|
|
} else {
|
|
|
// 新增模式:默认提交时间为当前时间
|
|
|
form.createdat = nowDatetime();
|
|
|
}
|
|
|
},
|
|
|
);
|
|
|
|
|
|
const removePasteListener = () => {
|
|
|
const editor = editorRef.value;
|
|
|
if (!editor || !pasteHandlerRef) return;
|
|
|
const root = typeof editor.$el === "function" ? editor.$el() : editor.$el;
|
|
|
if (!root) return;
|
|
|
const editable = root.querySelector?.('[contenteditable="true"]') || root;
|
|
|
editable.removeEventListener("paste", pasteHandlerRef, { capture: true });
|
|
|
};
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
removePasteListener();
|
|
|
pasteHandlerRef = null;
|
|
|
const editor = editorRef.value;
|
|
|
if (editor == null) return;
|
|
|
editor.destroy();
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss">
|
|
|
.hospital-order-form-dialog {
|
|
|
.rich-editor {
|
|
|
width: 100%;
|
|
|
background: #fff;
|
|
|
border-radius: 4px;
|
|
|
border: 1px solid #dcdfe6;
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
|
|
|
.rich-editor :deep(.w-e-toolbar) {
|
|
|
background: #fafafa;
|
|
|
border-bottom: 1px solid #dcdfe6;
|
|
|
}
|
|
|
|
|
|
.rich-editor :deep(.w-e-text-container) {
|
|
|
background: #fff;
|
|
|
}
|
|
|
|
|
|
.priority-row {
|
|
|
&.high {
|
|
|
--current-color: #ff383c;
|
|
|
background: #ffebec;
|
|
|
}
|
|
|
|
|
|
&.medium {
|
|
|
--current-color: #ff8d28;
|
|
|
background: #ffefe2;
|
|
|
}
|
|
|
|
|
|
&.low {
|
|
|
--current-color: #3289fb;
|
|
|
background: #eaf3ff;
|
|
|
}
|
|
|
|
|
|
width: 50px;
|
|
|
height: 30px;
|
|
|
border-radius: 8px 8px 8px 8px;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
gap: 4px;
|
|
|
|
|
|
&::before {
|
|
|
content: "";
|
|
|
display: block;
|
|
|
width: 8px;
|
|
|
height: 8px;
|
|
|
border-radius: 50%;
|
|
|
background: var(--current-color);
|
|
|
}
|
|
|
|
|
|
color: var(--current-color);
|
|
|
}
|
|
|
|
|
|
// 标题 + 颜色标签 + 优先级 同一行(与 admin 端一致)
|
|
|
.title-row {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
.title-row .title-input {
|
|
|
flex: 1;
|
|
|
|
|
|
.el-input__wrapper {
|
|
|
border-top-right-radius: 0px;
|
|
|
border-bottom-right-radius: 0px;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.title-row :deep(.el-input__suffix) {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 8px;
|
|
|
}
|
|
|
|
|
|
.title-counter {
|
|
|
font-size: 13px;
|
|
|
color: #909399;
|
|
|
margin-right: 10px;
|
|
|
}
|
|
|
|
|
|
.title-sepan {
|
|
|
width: 16px;
|
|
|
height: 16px;
|
|
|
display: block;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.color-tag-picker {
|
|
|
position: relative;
|
|
|
flex-shrink: 0;
|
|
|
}
|
|
|
|
|
|
// 优先级(与 admin 端一致:左 label + 右 select 拼接)
|
|
|
.priority-wrap {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
flex-shrink: 0;
|
|
|
border-radius: 8px;
|
|
|
height: 40px;
|
|
|
}
|
|
|
|
|
|
.priority-label {
|
|
|
height: 40px;
|
|
|
border-top: 1px solid #ebeef5;
|
|
|
border-bottom: 1px solid #ebeef5;
|
|
|
background: #F9FAFF;
|
|
|
color: #BCBCBC;
|
|
|
font-weight: 400;
|
|
|
font-size: 14px;
|
|
|
white-space: nowrap;
|
|
|
padding: 0 14px;
|
|
|
line-height: 40px;
|
|
|
}
|
|
|
|
|
|
.priority-select {
|
|
|
width: 110px;
|
|
|
}
|
|
|
|
|
|
.priority-select .el-select__wrapper {
|
|
|
background: transparent;
|
|
|
padding: 5px 13px;
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
border-top-left-radius: 0px;
|
|
|
border-bottom-left-radius: 0px;
|
|
|
}
|
|
|
|
|
|
.priority-select :deep(.el-select__placeholder) {
|
|
|
color: #303133;
|
|
|
}
|
|
|
|
|
|
.priority-option {
|
|
|
display: inline-flex;
|
|
|
align-items: center;
|
|
|
gap: 8px;
|
|
|
}
|
|
|
|
|
|
.priority-dot {
|
|
|
display: inline-block;
|
|
|
width: 8px;
|
|
|
height: 8px;
|
|
|
border-radius: 50%;
|
|
|
}
|
|
|
|
|
|
.priority-dot.high {
|
|
|
background: #ff383c;
|
|
|
}
|
|
|
|
|
|
.priority-dot.medium {
|
|
|
background: #ff8d28;
|
|
|
}
|
|
|
|
|
|
.priority-dot.low {
|
|
|
background: #3289fb;
|
|
|
}
|
|
|
|
|
|
.priority-option-label {
|
|
|
font-size: 14px;
|
|
|
color: #303133;
|
|
|
}
|
|
|
|
|
|
:deep(.fujian .el-form-item__content > div) {
|
|
|
width: 100% !important;
|
|
|
}
|
|
|
}
|
|
|
</style>
|
|
|
|
|
|
<style lang="scss">
|
|
|
.hospital-order-form-dialog {
|
|
|
max-width: 90vw;
|
|
|
width: 1168px;
|
|
|
overflow: visible;
|
|
|
|
|
|
.body-footer {
|
|
|
border-radius: 0 0 24px 24px;
|
|
|
}
|
|
|
|
|
|
--el-component-size: 40px;
|
|
|
|
|
|
.el-select__wrapper {
|
|
|
height: 40px;
|
|
|
}
|
|
|
|
|
|
.fujian {
|
|
|
.upload-wrap {
|
|
|
width: 100%;
|
|
|
|
|
|
.el-upload-list__item {
|
|
|
&:hover {
|
|
|
background: transparent;
|
|
|
}
|
|
|
|
|
|
.file-item {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
font-weight: 400;
|
|
|
font-size: 14px;
|
|
|
|
|
|
.file-icon {
|
|
|
width: 18px;
|
|
|
height: 18px;
|
|
|
}
|
|
|
|
|
|
.file-name,
|
|
|
.file-delete {
|
|
|
color: #1D2129;
|
|
|
|
|
|
&:hover {
|
|
|
color: #1890ff;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.file-delete {
|
|
|
margin-left: 14px;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
|
|
|
.file-size {
|
|
|
color: #BCBCBC;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.upload-btn {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
|
|
|
.left {
|
|
|
font-weight: 400;
|
|
|
font-size: 14px;
|
|
|
color: #2B324C;
|
|
|
}
|
|
|
|
|
|
.right {
|
|
|
font-weight: 400;
|
|
|
font-size: 14px;
|
|
|
color: #666666;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 颜色标签 popover 内容(默认 teleport 到 body,需放非 scoped 样式块)
|
|
|
.color-tag-popper {
|
|
|
padding: 12px 14px !important;
|
|
|
border-radius: 10px !important;
|
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12) !important;
|
|
|
min-width: 180px;
|
|
|
}
|
|
|
</style>
|