index.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. <template>
  2. <div class="p-2">
  3. <!-- 处方模板类型选择菜单 -->
  4. <el-card shadow="hover" class="mb-4">
  5. <div class="template-header">
  6. <div class="template-title">
  7. <el-icon class="title-icon">
  8. <User />
  9. </el-icon>
  10. <span class="title-text">个人模板</span>
  11. </div>
  12. <el-radio-group v-model="queryParams.type" @change="handleTypeChange"
  13. class="prescription-type-selector">
  14. <el-radio-button :label="2">预包装处方模板</el-radio-button>
  15. <el-radio-button :label="3">配置处方模板</el-radio-button>
  16. <el-radio-button :label="4">长嘱处方模板</el-radio-button>
  17. </el-radio-group>
  18. </div>
  19. </el-card>
  20. <transition :enter-active-class="proxy?.animate.searchAnimate.enter"
  21. :leave-active-class="proxy?.animate.searchAnimate.leave">
  22. <div v-show="showSearch" class="mb-[10px]">
  23. <el-card shadow="hover">
  24. <el-form ref="queryFormRef" :model="queryParams" :inline="true">
  25. <el-form-item label="模板名称" prop="templateName">
  26. <el-input v-model="queryParams.templateName" placeholder="请输入模板名称" clearable
  27. @keyup.enter="handleQuery" />
  28. </el-form-item>
  29. <el-form-item label="模板描述" prop="templateDescription">
  30. <el-input v-model="queryParams.templateDescription" placeholder="请输入模板描述" clearable
  31. @keyup.enter="handleQuery" />
  32. </el-form-item>
  33. <el-form-item label="处方科室" prop="prescriptionDepartmentName">
  34. <el-input v-model="queryParams.prescriptionDepartmentName" placeholder="请输入处方科室" clearable
  35. @keyup.enter="handleQuery" />
  36. </el-form-item>
  37. <el-form-item>
  38. <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
  39. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  40. </el-form-item>
  41. </el-form>
  42. </el-card>
  43. </div>
  44. </transition>
  45. <el-card shadow="never">
  46. <template #header>
  47. <el-row :gutter="10" class="mb8">
  48. <el-col :span="1.5">
  49. <el-button type="primary" plain icon="Plus" @click="handleAdd"
  50. v-hasPermi="['system:personalEnteralNutritionTemplate:add']">新增模板</el-button>
  51. </el-col>
  52. <el-col :span="1.5">
  53. <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"
  54. v-hasPermi="['system:personalEnteralNutritionTemplate:edit']">修改</el-button>
  55. </el-col>
  56. <el-col :span="1.5">
  57. <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"
  58. v-hasPermi="['system:personalEnteralNutritionTemplate:remove']">删除</el-button>
  59. </el-col>
  60. <el-col :span="1.5">
  61. <el-button type="warning" plain icon="Download" @click="handleExport"
  62. v-hasPermi="['system:personalEnteralNutritionTemplate:export']">导出</el-button>
  63. </el-col>
  64. <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
  65. </el-row>
  66. </template>
  67. <el-table v-loading="loading" border :data="personalEnteralNutritionTemplateList"
  68. @selection-change="handleSelectionChange" class="personal-template-table">
  69. <el-table-column type="selection" width="55" align="center" />
  70. <el-table-column label="模板名称" align="center" prop="templateName" min-width="150">
  71. <template #default="scope">
  72. <div class="template-name-cell">
  73. <el-icon class="personal-icon">
  74. <UserFilled />
  75. </el-icon>
  76. <span class="template-name">{{ scope.row.templateName }}</span>
  77. </div>
  78. </template>
  79. </el-table-column>
  80. <el-table-column label="模板描述" align="center" prop="templateDescription" min-width="200"
  81. show-overflow-tooltip />
  82. <el-table-column label="处方类型" align="center" prop="prescriptionType" width="120">
  83. <template #default="scope">
  84. <el-tag :type="getPrescriptionTypeTagType(scope.row.prescriptionType)" effect="light">
  85. {{ getPrescriptionTypeText(scope.row.prescriptionType) }}
  86. </el-tag>
  87. </template>
  88. </el-table-column>
  89. <el-table-column label="处方科室" align="center" prop="prescriptionDepartmentName" min-width="120"
  90. show-overflow-tooltip />
  91. <el-table-column label="状态" align="center" prop="status" width="80">
  92. <template #default="scope">
  93. <el-tag :type="scope.row.status === '0' ? 'success' : 'danger'" effect="light">
  94. {{ scope.row.status === '0' ? '正常' : '停用' }}
  95. </el-tag>
  96. </template>
  97. </el-table-column>
  98. <el-table-column label="创建时间" align="center" prop="createTime" width="150">
  99. <template #default="scope">
  100. <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
  101. </template>
  102. </el-table-column>
  103. <el-table-column label="创建者" align="center" prop="createBy" width="120" show-overflow-tooltip />
  104. <el-table-column label="更新者" align="center" prop="updateBy" width="120" show-overflow-tooltip />
  105. <el-table-column label="最后编辑时间" align="center" prop="updateTime" width="150">
  106. <template #default="scope">
  107. <span>{{ parseTime(scope.row.updateTime, '{y}-{m}-{d}') }}</span>
  108. </template>
  109. </el-table-column>
  110. <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160"
  111. fixed="right">
  112. <template #default="scope">
  113. <el-tooltip content="查看详情" placement="top">
  114. <el-button link type="primary" icon="View" @click="handleView(scope.row)"></el-button>
  115. </el-tooltip>
  116. <el-tooltip content="修改" placement="top">
  117. <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
  118. v-hasPermi="['system:personalEnteralNutritionTemplate:edit']"></el-button>
  119. </el-tooltip>
  120. <el-tooltip content="复制" placement="top">
  121. <el-button link type="warning" icon="CopyDocument"
  122. @click="handleCopy(scope.row)"></el-button>
  123. </el-tooltip>
  124. <el-tooltip content="删除" placement="top">
  125. <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)"
  126. v-hasPermi="['system:personalEnteralNutritionTemplate:remove']"></el-button>
  127. </el-tooltip>
  128. </template>
  129. </el-table-column>
  130. </el-table>
  131. <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
  132. v-model:limit="queryParams.pageSize" @pagination="getList" />
  133. </el-card>
  134. <!-- 模板详情查看对话框 -->
  135. <el-dialog :title="viewDialog.title" v-model="viewDialog.visible" width="80%" append-to-body
  136. class="template-detail-dialog">
  137. <div class="template-detail-content" v-if="viewTemplateData">
  138. <el-descriptions :column="2" border>
  139. <el-descriptions-item label="模板名称">
  140. <div class="template-name-cell">
  141. <el-icon class="personal-icon">
  142. <UserFilled />
  143. </el-icon>
  144. <span class="template-name">{{ viewTemplateData.templateName }}</span>
  145. </div>
  146. </el-descriptions-item>
  147. <el-descriptions-item label="处方类型">
  148. <el-tag :type="getPrescriptionTypeTagType(viewTemplateData.prescriptionType)" effect="light">
  149. {{ getPrescriptionTypeText(viewTemplateData.prescriptionType) }}
  150. </el-tag>
  151. </el-descriptions-item>
  152. <el-descriptions-item label="模板描述" :span="2">{{ viewTemplateData.templateDescription
  153. }}</el-descriptions-item>
  154. <el-descriptions-item label="处方科室">{{ viewTemplateData.prescriptionDepartmentName
  155. }}</el-descriptions-item>
  156. <el-descriptions-item label="状态">
  157. <el-tag :type="viewTemplateData.status === '0' ? 'success' : 'danger'" effect="light">
  158. {{ viewTemplateData.status === '0' ? '正常' : '停用' }}
  159. </el-tag>
  160. </el-descriptions-item>
  161. <el-descriptions-item label="创建时间">
  162. {{ parseTime(viewTemplateData.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}
  163. </el-descriptions-item>
  164. <el-descriptions-item label="创建者">{{ viewTemplateData.createBy || '未知' }}</el-descriptions-item>
  165. <el-descriptions-item label="更新者">{{ viewTemplateData.updateBy || '未知' }}</el-descriptions-item>
  166. <el-descriptions-item label="最后编辑时间">
  167. {{ parseTime(viewTemplateData.updateTime, '{y}-{m}-{d} {h}:{i}:{s}') }}
  168. </el-descriptions-item>
  169. </el-descriptions>
  170. <div class="template-content-section">
  171. <h4>模板内容:</h4>
  172. <div class="content-preview">
  173. <pre>{{ formatTemplateContent(viewTemplateData.content) }}</pre>
  174. </div>
  175. </div>
  176. </div>
  177. <template #footer>
  178. <div class="dialog-footer">
  179. <el-button @click="viewDialog.visible = false">关闭</el-button>
  180. </div>
  181. </template>
  182. </el-dialog>
  183. <!-- 添加或修改个人肠内处方模板对话框 -->
  184. <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
  185. <el-form ref="personalEnteralNutritionTemplateFormRef" :model="form" :rules="rules" label-width="100px">
  186. <el-form-item label="模板名称" prop="templateName">
  187. <el-input v-model="form.templateName" placeholder="请输入模板名称" />
  188. </el-form-item>
  189. <el-form-item label="模板描述" prop="templateDescription">
  190. <el-input v-model="form.templateDescription" type="textarea" :rows="3" placeholder="请输入模板描述" />
  191. </el-form-item>
  192. <el-form-item label="处方类型" prop="prescriptionType">
  193. <el-select v-model="form.prescriptionType" placeholder="请选择处方类型" style="width: 100%">
  194. <el-option label="预包装处方模板" value="2" />
  195. <el-option label="配置处方模板" value="3" />
  196. <el-option label="长嘱处方模板" value="4" />
  197. </el-select>
  198. </el-form-item>
  199. <el-form-item label="处方科室ID" prop="prescriptionId">
  200. <el-input v-model="form.prescriptionId" placeholder="请输入处方科室ID" />
  201. </el-form-item>
  202. <el-form-item label="营养产品信息">
  203. <editor v-model="form.content" :min-height="192" />
  204. </el-form-item>
  205. <el-form-item label="状态" prop="status">
  206. <el-radio-group v-model="form.status">
  207. <el-radio label="0">正常</el-radio>
  208. <el-radio label="1">停用</el-radio>
  209. </el-radio-group>
  210. </el-form-item>
  211. </el-form>
  212. <template #footer>
  213. <div class="dialog-footer">
  214. <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
  215. <el-button @click="cancel">取 消</el-button>
  216. </div>
  217. </template>
  218. </el-dialog>
  219. </div>
  220. </template>
  221. <script setup name="PersonalEnteralNutritionTemplate" lang="ts">
  222. import { listPersonalEnteralNutritionTemplate, getPersonalEnteralNutritionTemplate, delPersonalEnteralNutritionTemplate, addPersonalEnteralNutritionTemplate, updatePersonalEnteralNutritionTemplate } from '@/api/parameter/personalTemplate/enteralNutritionTemplate';
  223. import { PersonalEnteralNutritionTemplateVO, PersonalEnteralNutritionTemplateQuery, PersonalEnteralNutritionTemplateForm } from '@/api/parameter/personalTemplate/enteralNutritionTemplate/types';
  224. import { useRouter, useRoute } from 'vue-router';
  225. import { User, UserFilled } from '@element-plus/icons-vue';
  226. const router = useRouter();
  227. const route = useRoute();
  228. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  229. const personalEnteralNutritionTemplateList = ref<PersonalEnteralNutritionTemplateVO[]>([]);
  230. const buttonLoading = ref(false);
  231. const loading = ref(true);
  232. const showSearch = ref(true);
  233. const ids = ref<Array<string | number>>([]);
  234. const single = ref(true);
  235. const multiple = ref(true);
  236. const total = ref(0);
  237. const queryFormRef = ref<ElFormInstance>();
  238. const personalEnteralNutritionTemplateFormRef = ref<ElFormInstance>();
  239. const dialog = reactive<DialogOption>({
  240. visible: false,
  241. title: ''
  242. });
  243. const viewDialog = reactive<DialogOption>({
  244. visible: false,
  245. title: ''
  246. });
  247. const viewTemplateData = ref<PersonalEnteralNutritionTemplateVO | null>(null);
  248. const initFormData: PersonalEnteralNutritionTemplateForm = {
  249. id: undefined,
  250. templateName: undefined,
  251. templateDescription: undefined,
  252. prescriptionType: undefined,
  253. prescriptionId: undefined,
  254. content: undefined,
  255. status: '0',
  256. delFlag: undefined,
  257. templateType: 0 // 0表示个人模板
  258. }
  259. const data = reactive<PageData<PersonalEnteralNutritionTemplateForm, PersonalEnteralNutritionTemplateQuery>>({
  260. form: { ...initFormData },
  261. queryParams: {
  262. pageNum: 1,
  263. pageSize: 10,
  264. templateName: undefined,
  265. templateDescription: undefined,
  266. type: 2,
  267. prescriptionType: undefined,
  268. prescriptionId: undefined,
  269. prescriptionDepartmentName: undefined,
  270. content: undefined,
  271. status: undefined,
  272. templateType: 0, // 设置为个人模板类型
  273. params: {}
  274. },
  275. rules: {
  276. templateName: [
  277. { required: true, message: "模板名称不能为空", trigger: "blur" }
  278. ],
  279. prescriptionType: [
  280. { required: true, message: "处方类型不能为空", trigger: "change" }
  281. ]
  282. }
  283. });
  284. const { queryParams, form, rules } = toRefs(data);
  285. // 获取处方类型显示文本
  286. const getPrescriptionTypeText = (type: string) => {
  287. switch (type) {
  288. case '2':
  289. return '预包装处方';
  290. case '3':
  291. return '配置处方';
  292. case '4':
  293. return '长嘱处方';
  294. default:
  295. return '未知类型';
  296. }
  297. };
  298. // 获取处方类型标签样式
  299. const getPrescriptionTypeTagType = (type: string) => {
  300. switch (type) {
  301. case '2':
  302. return 'primary';
  303. case '3':
  304. return 'success';
  305. case '4':
  306. return 'warning';
  307. default:
  308. return 'info';
  309. }
  310. };
  311. // 格式化模板内容用于显示
  312. const formatTemplateContent = (content: string) => {
  313. try {
  314. const parsed = JSON.parse(content);
  315. return JSON.stringify(parsed, null, 2);
  316. } catch {
  317. return content;
  318. }
  319. };
  320. /** 查询个人肠内处方模板列表 */
  321. const getList = async () => {
  322. loading.value = true;
  323. try {
  324. const res = await listPersonalEnteralNutritionTemplate(queryParams.value);
  325. personalEnteralNutritionTemplateList.value = res.rows;
  326. total.value = res.total;
  327. } catch (error) {
  328. console.error('获取个人模板列表失败:', error);
  329. personalEnteralNutritionTemplateList.value = [];
  330. total.value = 0;
  331. } finally {
  332. loading.value = false;
  333. }
  334. }
  335. /** 取消按钮 */
  336. const cancel = () => {
  337. reset();
  338. dialog.visible = false;
  339. }
  340. /** 表单重置 */
  341. const reset = () => {
  342. form.value = { ...initFormData };
  343. personalEnteralNutritionTemplateFormRef.value?.resetFields();
  344. }
  345. /** 搜索按钮操作 */
  346. const handleQuery = () => {
  347. queryParams.value.pageNum = 1;
  348. getList();
  349. }
  350. /** 重置按钮操作 */
  351. const resetQuery = () => {
  352. queryFormRef.value?.resetFields();
  353. handleQuery();
  354. }
  355. /** 处方模板类型变更处理 */
  356. const handleTypeChange = (type: number) => {
  357. queryParams.value.type = type;
  358. queryParams.value.pageNum = 1;
  359. getList();
  360. }
  361. /** 多选框选中数据 */
  362. const handleSelectionChange = (selection: PersonalEnteralNutritionTemplateVO[]) => {
  363. ids.value = selection.map(item => item.id);
  364. single.value = selection.length != 1;
  365. multiple.value = !selection.length;
  366. }
  367. /** 新增按钮操作 */
  368. const handleAdd = () => {
  369. router.push({
  370. path: '/argManage/enteralNutritionTemplateAdd',
  371. query: {
  372. type: queryParams.value.type,
  373. action: 'add',
  374. templateType: 0 // 标识为个人模板
  375. }
  376. });
  377. }
  378. /** 查看模板详情 */
  379. const handleView = async (row: PersonalEnteralNutritionTemplateVO) => {
  380. try {
  381. const res = await getPersonalEnteralNutritionTemplate(row.id);
  382. viewTemplateData.value = res.data;
  383. viewDialog.visible = true;
  384. viewDialog.title = `查看模板详情 - ${row.templateName}`;
  385. } catch (error) {
  386. console.error('获取模板详情失败:', error);
  387. proxy?.$modal.msgError("获取模板详情失败");
  388. }
  389. }
  390. /** 复制模板 */
  391. const handleCopy = async (row: PersonalEnteralNutritionTemplateVO) => {
  392. router.push({
  393. path: '/argManage/enteralNutritionTemplateAdd',
  394. query: {
  395. copyId: row.id, // 使用copyId标识复制操作
  396. type: queryParams.value.type,
  397. action: 'add',
  398. templateType: 0 // 标识为个人模板
  399. }
  400. });
  401. }
  402. /** 修改按钮操作 */
  403. const handleUpdate = async (row?: PersonalEnteralNutritionTemplateVO) => {
  404. router.push({
  405. path: '/argManage/enteralNutritionTemplateAdd',
  406. query: {
  407. id: row?.id || ids.value[0],
  408. type: queryParams.value.type,
  409. action: 'update',
  410. templateType: 0 // 标识为个人模板
  411. }
  412. });
  413. }
  414. /** 提交按钮 */
  415. const submitForm = () => {
  416. personalEnteralNutritionTemplateFormRef.value?.validate(async (valid: boolean) => {
  417. if (valid) {
  418. buttonLoading.value = true;
  419. try {
  420. // 确保设置为个人模板
  421. form.value.templateType = 0;
  422. if (form.value.id) {
  423. await updatePersonalEnteralNutritionTemplate(form.value);
  424. } else {
  425. await addPersonalEnteralNutritionTemplate(form.value);
  426. }
  427. proxy?.$modal.msgSuccess("操作成功");
  428. dialog.visible = false;
  429. await getList();
  430. } catch (error) {
  431. console.error('提交失败:', error);
  432. proxy?.$modal.msgError("操作失败");
  433. } finally {
  434. buttonLoading.value = false;
  435. }
  436. }
  437. });
  438. }
  439. /** 删除按钮操作 */
  440. const handleDelete = async (row?: PersonalEnteralNutritionTemplateVO) => {
  441. const _ids = row?.id || ids.value;
  442. try {
  443. await proxy?.$modal.confirm('是否确认删除个人模板编号为"' + _ids + '"的数据项?');
  444. await delPersonalEnteralNutritionTemplate(_ids);
  445. proxy?.$modal.msgSuccess("删除成功");
  446. await getList();
  447. } catch (error) {
  448. if (error !== 'cancel') {
  449. console.error('删除失败:', error);
  450. proxy?.$modal.msgError("删除失败");
  451. }
  452. }
  453. }
  454. /** 导出按钮操作 */
  455. const handleExport = () => {
  456. // 使用与基础公共模板相同的导出接口,通过templateType=0过滤个人模板
  457. const exportParams = { ...queryParams.value, templateType: 0 };
  458. proxy?.download('parameter/basicPublicTemplate/enteralNutritionTemplate/export', exportParams, `personal_enteral_nutrition_template_${new Date().getTime()}.xlsx`)
  459. }
  460. // 初始化状态锁,防止重复初始化
  461. const isInitializing = ref(false)
  462. /** 页面初始化函数 */
  463. const initializePage = async () => {
  464. // 防止重复初始化
  465. if (isInitializing.value) {
  466. console.log('个人模板页面正在初始化中,跳过重复初始化')
  467. return
  468. }
  469. try {
  470. isInitializing.value = true
  471. console.log('个人肠内处方模板列表页面初始化')
  472. // 重置选择状态
  473. ids.value = []
  474. single.value = true
  475. multiple.value = true
  476. // 重置分页到第一页(保持搜索条件和处方类型)
  477. queryParams.value.pageNum = 1
  478. // 显示加载状态
  479. loading.value = true
  480. // 重新获取数据
  481. await getList()
  482. console.log('个人模板页面初始化完成')
  483. } catch (error) {
  484. console.error('个人模板页面初始化失败:', error)
  485. // 确保加载状态被重置
  486. loading.value = false
  487. } finally {
  488. // 延迟重置锁,避免快速连续的路由变化
  489. setTimeout(() => {
  490. isInitializing.value = false
  491. }, 300)
  492. }
  493. }
  494. // 监听路由变化 - 检测从其他页面跳转回来
  495. watch(() => route.fullPath, async (newFullPath, oldFullPath) => {
  496. // 当前页面的路径模式
  497. const isCurrentListPage = newFullPath.includes('personalTemplate/enteralNutritionTemplate') &&
  498. !newFullPath.includes('Add') &&
  499. !newFullPath.includes('Edit')
  500. // 上一个页面是否为非列表页
  501. const wasNotListPage = !oldFullPath ||
  502. !oldFullPath.includes('personalTemplate/enteralNutritionTemplate') ||
  503. oldFullPath.includes('Add') ||
  504. oldFullPath.includes('Edit')
  505. // 如果从非列表页跳转到列表页,则重新初始化
  506. if (newFullPath !== oldFullPath && isCurrentListPage && wasNotListPage) {
  507. console.log('检测到从其他页面跳转回个人模板列表页,重新初始化')
  508. console.log('旧路径:', oldFullPath)
  509. console.log('新路径:', newFullPath)
  510. await initializePage()
  511. }
  512. }, { flush: 'post' })
  513. onMounted(() => {
  514. getList();
  515. });
  516. </script>
  517. <style scoped>
  518. .template-header {
  519. display: flex;
  520. justify-content: space-between;
  521. align-items: center;
  522. padding: 8px 0;
  523. }
  524. .template-title {
  525. display: flex;
  526. align-items: center;
  527. gap: 8px;
  528. font-size: 16px;
  529. font-weight: 600;
  530. color: #409eff;
  531. }
  532. .title-icon {
  533. font-size: 18px;
  534. }
  535. .prescription-type-selector {
  536. display: flex;
  537. justify-content: center;
  538. align-items: center;
  539. }
  540. .prescription-type-selector .el-radio-button {
  541. margin: 0 4px;
  542. }
  543. .prescription-type-selector .el-radio-button__inner {
  544. padding: 8px 20px;
  545. font-weight: 500;
  546. border-radius: 6px;
  547. transition: all 0.3s ease;
  548. }
  549. .prescription-type-selector .el-radio-button__inner:hover {
  550. color: var(--el-color-primary);
  551. border-color: var(--el-color-primary);
  552. }
  553. .prescription-type-selector .el-radio-button.is-active .el-radio-button__inner {
  554. background-color: var(--el-color-primary);
  555. border-color: var(--el-color-primary);
  556. color: #fff;
  557. box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
  558. }
  559. .personal-template-table {
  560. --el-table-header-bg-color: #f8fafc;
  561. }
  562. .template-name-cell {
  563. display: flex;
  564. align-items: center;
  565. gap: 8px;
  566. }
  567. .personal-icon {
  568. color: #409eff;
  569. font-size: 16px;
  570. }
  571. .template-name {
  572. font-weight: 500;
  573. }
  574. .template-detail-dialog .template-detail-content {
  575. padding: 20px 0;
  576. }
  577. .template-content-section {
  578. margin-top: 24px;
  579. }
  580. .template-content-section h4 {
  581. margin-bottom: 12px;
  582. color: #303133;
  583. font-weight: 600;
  584. }
  585. .content-preview {
  586. background-color: #f5f7fa;
  587. border: 1px solid #dcdfe6;
  588. border-radius: 4px;
  589. padding: 16px;
  590. max-height: 300px;
  591. overflow-y: auto;
  592. }
  593. .content-preview pre {
  594. margin: 0;
  595. font-family: 'Courier New', monospace;
  596. font-size: 12px;
  597. line-height: 1.5;
  598. color: #606266;
  599. white-space: pre-wrap;
  600. word-wrap: break-word;
  601. }
  602. .mb-4 {
  603. margin-bottom: 16px;
  604. }
  605. /* 响应式设计 */
  606. @media (max-width: 768px) {
  607. .template-header {
  608. flex-direction: column;
  609. gap: 16px;
  610. align-items: flex-start;
  611. }
  612. .prescription-type-selector {
  613. width: 100%;
  614. justify-content: flex-start;
  615. flex-wrap: wrap;
  616. }
  617. .prescription-type-selector .el-radio-button {
  618. margin: 4px;
  619. }
  620. }
  621. </style>