DynamicTbForm.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. <template>
  2. <div class="unit-create-and-edit" v-loading="formLoading">
  3. <el-tabs v-model="activeTab" @tab-click="handleTabClick" tab-position="left" class="unit-content"
  4. :before-leave="handleBeforeTabLeave">
  5. <div class="c-header">
  6. <div class="title">模板详情</div>
  7. <el-button class="close" link @click="handleClose"><el-icon size="22">
  8. <Close />
  9. </el-icon></el-button>
  10. </div>
  11. <el-tab-pane label="模板信息" name="模板信息">
  12. <div class="form-container">
  13. <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
  14. <el-form-item label="模板名字" prop="tbName">
  15. <el-input v-model="formData.tbName" placeholder="请输入模板名字" />
  16. </el-form-item>
  17. <el-form-item label="模板编号" prop="tbCode">
  18. <el-input v-model="formData.tbCode" placeholder="请输入模板编号" />
  19. </el-form-item>
  20. <el-form-item label="模板分类" prop="tbType">
  21. <el-select v-model="formData.tbType" placeholder="请选择模板分类">
  22. <el-option v-for="dict in getIntDictOptions(DICT_TYPE.PRESSURE2_TB_TYPE)" :key="dict.value"
  23. :label="dict.label" :value="dict.value" />
  24. </el-select>
  25. </el-form-item>
  26. <el-form-item label="模板类型" prop="reportType">
  27. <el-select v-model="formData.reportType" placeholder="请选择模板类型">
  28. <el-option v-for="dict in getIntDictOptions(DICT_TYPE.PRESSURE2_DYNAMIC_REPORT_TYPE)" :key="dict.value"
  29. :label="dict.label" :value="dict.value" />
  30. </el-select>
  31. </el-form-item>
  32. <el-form-item label="项目分类" prop="pjType">
  33. <el-select v-model="formData.pjType" placeholder="请选择项目分类">
  34. <el-option v-for="dict in getIntDictOptions(DICT_TYPE.PRESSURE2_DYNAMIC_PROJECT_TYPE)"
  35. :key="dict.value" :label="dict.label" :value="dict.value" />
  36. </el-select>
  37. </el-form-item>
  38. <el-form-item v-if="false" label="模板地址" prop="tbUrl">
  39. <el-input v-model="formData.tbUrl" placeholder="请输入模板地址" />
  40. </el-form-item>
  41. <el-form-item label="版本号" prop="versionNo">
  42. <el-input v-model="formData.versionNo" placeholder="请输入版本号" />
  43. </el-form-item>
  44. <el-form-item label="模板说明" prop="tbNote">
  45. <el-input v-model="formData.tbNote" type="textarea" placeholder="请输入模板说明" />
  46. </el-form-item>
  47. <el-form-item label="创建人名" prop="creatorName">
  48. <el-input v-model="formData.creatorName" placeholder="请输入创建人名" />
  49. </el-form-item>
  50. <el-form-item label="报告原件" prop="filePaths">
  51. <CustomUploadFile
  52. v-model:fileList="formData.filePaths"
  53. apiUrl="infra/file/upload"
  54. accept=".pdf,.jpg,.png,.doc,.wps,.docx,.DOC"
  55. list-type="text"
  56. />
  57. </el-form-item>
  58. </el-form>
  59. </div>
  60. </el-tab-pane>
  61. <el-tab-pane label="模板文件" name="模板文件">
  62. <!--<SpreadView v-if="isSpredaShow" :dtParams="dtParams" :formData="formData" @success="getData" />-->
  63. <SpreadEditor v-if="isSpredaShow" :dtParams="dtParams" :formData="formData" @success="getData" />
  64. </el-tab-pane>
  65. <el-tab-pane label="模板pdf" name="模板pdf">
  66. <div class="default-toolbar">
  67. <el-button type="primary" @click="handleOpenFileUploadModal">上传模板</el-button>
  68. <el-button type="primary" @click="saveDocument">保存模板</el-button>
  69. </div>
  70. <docEditor :config="officeConfig" @docReady="onDocumentReady" @docCreate="onCreateDoc" ref="officeEvents"/>
  71. <!--<DocumentEditor
  72. id="docEditor"
  73. v-if="officeVisible"
  74. :documentServerUrl="documentServerUrl"
  75. :config="officeConfig"
  76. :events_onDocumentReady="onDocumentReady"
  77. :onLoadComponentError="onLoadComponentError"
  78. />-->
  79. </el-tab-pane>
  80. <el-tab-pane :label="showInfos.title" :name="showInfos.title" v-if="formType !== 'create' && connectInfos?.length">
  81. <el-tabs v-model="activeSpreadTab" type="border-card" class="spread-tabs">
  82. <el-tab-pane
  83. v-for="(item, index) in spreadDataList"
  84. :key="index"
  85. :label="getTemplateName(item)"
  86. :name="index"
  87. class="spread-tab-pane"
  88. >
  89. <div class="spread-scrollbar-wrapper">
  90. <el-scrollbar>
  91. <SpreadViewer :initData="item.initData" ref="spreadRefs" />
  92. </el-scrollbar>
  93. </div>
  94. </el-tab-pane>
  95. </el-tabs>
  96. </el-tab-pane>
  97. </el-tabs>
  98. <div class="unit-footer-btns">
  99. <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
  100. <el-button @click="handleClose">取 消</el-button>
  101. </div>
  102. <FileUploadModal ref="fileUploadModalRef" @success="handleFileUploadSuccess" />
  103. </div>
  104. </template>
  105. <script setup lang="ts">
  106. import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
  107. import { DynamicTbApi, DynamicTbVO } from '@/api/pressure2/dynamictb'
  108. import { Close } from "@element-plus/icons-vue";
  109. //import SpreadView from "@/components/DynamicReport/index1.vue";
  110. import {SpreadEditor, SpreadViewer} from '@/components/DynamicReport/index';
  111. //import { DocumentEditor } from "@onlyoffice/document-editor-vue";
  112. import { DocEditor,DocEditorEvents } from '@/components/BwDocEditor'
  113. import FileUploadModal from './ImportFile.vue'
  114. import {ref } from "vue";
  115. import GC from "@grapecity-software/spread-sheets";
  116. import undo = GC.Spread.Sheets.Commands.undo;
  117. import {useUserStore} from "@/store/modules/user";
  118. import {InitParams} from "@/components/DynamicReport/SpreadInterface";
  119. import {DynamicTbInsApi} from '@/api/pressure2/dynamictbins'
  120. import {BoilerConnectRecordReportApi} from "@/api/pressure2/boilerconnectrecordreport";
  121. /** 承压动态报表表单 表单 */
  122. defineOptions({ name: 'DynamicTbForm' })
  123. const { t } = useI18n() // 国际化
  124. const message = useMessage() // 消息弹窗
  125. const {getUser} = useUserStore()
  126. const dialogVisible = ref(false) // 弹窗的是否展示
  127. const dialogTitle = ref('') // 弹窗的标题
  128. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  129. const formType = ref('') // 表单的类型:create - 新增;update - 修改
  130. const formData = ref({
  131. id: undefined,
  132. tbName: undefined,
  133. tbCode: undefined,
  134. tbType: undefined,
  135. reportType: undefined,
  136. pjType: undefined,
  137. tbUrl: undefined,
  138. versionNo: undefined,
  139. tbNote: undefined,
  140. creatorName: getUser.nickname,
  141. inPath: undefined,
  142. formUrl: undefined,
  143. formPath: undefined,
  144. filePaths: [],
  145. })
  146. const formRules = reactive({
  147. tbName: [{ required: true, message: '模板名字不能为空', trigger: 'blur' }],
  148. tbCode: [{ required: true, message: '模板编号不能为空', trigger: 'blur' }],
  149. tbType: [{ required: true, message: '模板分类不能为空', trigger: 'change' }],
  150. reportType: [{ required: true, message: '模板类型不能为空', trigger: 'change' }],
  151. pjType: [{ required: true, message: '项目分类不能为空', trigger: 'change' }]
  152. })
  153. //const documentServerUrl = import.meta.env.VITE_ONLY_OFFICE_SERVER_URL;
  154. const fileUploadModalRef = ref<InstanceType<typeof FileUploadModal>>();
  155. const currentUploadMap = reactive({
  156. field: '',
  157. fieldAttr: '',
  158. })
  159. // 预览
  160. const router = useRouter();
  161. const connectInfos = ref<[]>(null);
  162. const showInfos = ref({
  163. title : undefined,
  164. type : undefined
  165. })
  166. // 根据 reportType 获取对应的模板 ID
  167. const getTemplateId = (item: any) => {
  168. return formData.value.reportType === 100 ? item.reportTemplateId : item.recordTemplateId
  169. }
  170. // SpreadViewer 相关数据
  171. const activeSpreadTab = ref<number | string>(0)
  172. const spreadRefs = ref()
  173. const spreadDataList = ref<Array<any>>([])
  174. // 根据 reportType 获取对应的模板名称
  175. const getTemplateName = (item: any) => {
  176. return formData.value.reportType === 100 ? item.reportTemplateName : item.recordTemplateName
  177. }
  178. const initConnectInfos = async () => {
  179. if (!tbId.value || !formData.value.reportType) return
  180. const isRecord = formData.value.reportType === 100
  181. const isReport = formData.value.reportType === 200
  182. if (isRecord || isReport) {
  183. showInfos.value = {
  184. title: isRecord ? '报告模板' : '记录模板',
  185. type: isRecord ? 'record' : 'report'
  186. }
  187. connectInfos.value = await BoilerConnectRecordReportApi.getByTemplateId({
  188. templateId: tbId.value,
  189. type: showInfos.value.type
  190. })
  191. // 为每个 connectInfo 创建对应的 SpreadViewer 数据
  192. spreadDataList.value = []
  193. const currentIndex = spreadDataList.value.length
  194. for (const [index, item] of connectInfos.value.entries()) {
  195. const templateId = getTemplateId(item)
  196. try {
  197. const res = await DynamicTbInsApi.getOrCreatePreviewData(templateId)
  198. spreadDataList.value.push({
  199. ...item,
  200. initData: {
  201. templateId: templateId,
  202. refId: res.refId,
  203. refName: '',
  204. insId: '',
  205. opType: 1, // 0:excel,1: pdf
  206. } as InitParams
  207. })
  208. // 等待 DOM 更新后刷新对应的 SpreadViewer
  209. setTimeout(() => {
  210. if (spreadRefs.value && Array.isArray(spreadRefs.value)) {
  211. spreadRefs.value[index]?.reloadView()
  212. }
  213. }, 400)
  214. } catch (error) {
  215. console.error(`加载模板 ${getTemplateName(item)} 失败:`, error)
  216. }
  217. }
  218. }
  219. }
  220. const handleOpenFileUploadModal = () => {
  221. //type: string, attach: string
  222. //currentUploadMap.field = type
  223. //currentUploadMap.fieldAttr = attach
  224. if(formData.value.id){
  225. fileUploadModalRef.value?.open();
  226. } else {
  227. message.alert("先保存才能导入模板!");
  228. }
  229. }
  230. const handleFileUploadSuccess = (fileInfo:{fileName: string, fileUrl: string,fileInfo:any}) => {
  231. //formData.value.tbUrl = fileInfo.fileUrl;
  232. //存filePath
  233. formData.value.inPath = fileInfo.fileUrl;
  234. getDocToDPFToken(formData.value.inPath,true);
  235. console.log('handleFileUploadSuccess:',fileInfo);
  236. //exceptionInfo.value[currentUploadMap.field] = fileInfo.fileName
  237. //exceptionInfo.value[currentUploadMap.fieldAttr] = fileInfo.fileUrl
  238. //console.log('handleFileUploadSuccess:', exceptionInfo.value)
  239. }
  240. //const officeVisible = ref(false)
  241. const officeEditor = ref<any>(null);
  242. const officeKey=ref<string>(null);
  243. const officeEvents=ref<DocEditorEvents>(null);
  244. const officeVisible=ref<boolean>(false);
  245. const officeConfig = ref({
  246. document: {
  247. fileType: 'pdf',
  248. key: null,
  249. permissions: {
  250. edit: true,
  251. },
  252. title: 'Form Template QC12005-202400',
  253. url: 'http://192.168.0.53/temp/QC12005-202400.pdf'
  254. },
  255. documentType: "pdf",
  256. token: ''
  257. });
  258. const officeParam=ref({
  259. documentType: 'PDF',
  260. fileType:'pdf',
  261. key: 'QC12005-202402_pdf',
  262. title: 'QC12005-202402',
  263. url: 'http://192.168.0.53/temp/QC12005-202402.pdf',
  264. pm_edit: true,
  265. pm_fillForms: false,
  266. refId: '',
  267. });
  268. const setToken=async ()=>{
  269. let oConfig= await DynamicTbApi.getToken(officeParam.value);
  270. //oConfig.token='';
  271. if(officeEditor.value){
  272. officeEditor.value.refreshFile(oConfig);
  273. } else {
  274. officeConfig.value =oConfig;
  275. }
  276. //officeVisible.value=true;
  277. }
  278. //setToken();
  279. const getDocToDPFToken=async (filePath:string,isNew:boolean)=>{
  280. officeVisible.value=false;
  281. let oConfig= await DynamicTbApi.getDocToDPFToken(filePath,formData.value.id,isNew);
  282. officeConfig.value =oConfig;
  283. formData.value.formUrl=oConfig.document.url;
  284. formData.value.formPath=oConfig.document.key;
  285. officeKey.value=oConfig.document.key;
  286. /*
  287. if(officeEditor.value){
  288. officeEditor.value.refreshFile(oConfig);
  289. }*/
  290. officeVisible.value=true;
  291. //officeVisible.value=true;
  292. }
  293. /*
  294. const loadPdfInit=()=>{
  295. getDocToDPFToken
  296. }*/
  297. const loadDPFToekn = async()=>{
  298. //officeVisible.value=false;
  299. //officeEditor.value?.destroyEditor();
  300. //officeParam.value.url='http://192.168.0.53:6180/cache/files/data/conv_b41bf875f729618600e4cc4ab04ae2296e239d9f80da814cdd8c26a710fa86fd.docx_513/output.pdf/QC12005-202400.pdf?md5=0CU3XwzCCGbb59DmozCQVA&expires=1763603489&shardkey=b41bf875f729618600e4cc4ab04ae2296e239d9f80da814cdd8c26a710fa86fd.docx&filename=QC12005-202400.pdf';
  301. officeParam.value.key="QC12005-202402_pdf";
  302. officeEditor.value?.destroyEditor();
  303. let oConfig= await DynamicTbApi.getToken(officeParam.value);
  304. officeConfig.value =oConfig;
  305. /*
  306. if(officeEditor.value){
  307. officeEditor.value.refreshFile(oConfig);
  308. } */
  309. //officeVisible.value=true;
  310. }
  311. const loadFilePathToekn = async ()=>{
  312. //officeVisible.value=false;
  313. officeEditor.value?.destroyEditor();
  314. let filePath='b41bf875f729618600e4cc4ab04ae2296e239d9f80da814cdd8c26a710fa86fd.docx';
  315. getDocToDPFToken(filePath,false);
  316. }
  317. const onDocumentReady = (event)=>{
  318. //const documentEditor = window.DocEditor.instances["docEditor"];
  319. //var a=window.DocEditor;
  320. //officeEditor.value = documentEditor;
  321. //const documentEditor =
  322. //officeEditor.value= event.target; //event.target.DocEditor();
  323. officeEditor.value?.showMessage("Welcome to ONLYOFFICE Editor!");
  324. console.log("Document is loaded");
  325. };
  326. const onCreateDoc=(e)=>{
  327. officeEditor.value= e.target; // event.target.DocEditor();
  328. officeEditor.value?.showMessage("Welcome to ONLYOFFICE Editor!");
  329. console.log("Document is create");
  330. }
  331. const clearDocument=()=>{
  332. //const documentEditor = window.DocEditor?.instances["docEditor"];
  333. //documentEditor?.destroyEditor();
  334. officeEvents.value.closeEditor();
  335. }
  336. const saveDocument=async ()=>{
  337. //const documentEditor = window.DocEditor.instances["docEditor"];
  338. //documentEditor.destroyEditor();
  339. //const docAPI = await import(documentServerUrl+'web-apps/apps/api/documents/api.js');
  340. //let docEditor =new window.DocsAPI.DocEditor("docEditor", officeConfig.value);
  341. let connector=officeEditor.value.createConnector();
  342. connector.executeMethod("GetAllContentControls", [],(data)=>{
  343. var a=data;
  344. console.log("Document is GetAllContentControls:"+JSON.stringify(data));
  345. });
  346. //let a=officeEditor.value?.serviceCommand('init',officeConfig.value);
  347. console.log("Document is save click");
  348. }
  349. const onLoadComponentError= (errorCode, errorDescription)=>{
  350. switch(errorCode) {
  351. case -1: // Unknown error loading component
  352. console.log(errorDescription);
  353. break;
  354. case -2: // Error load DocsAPI from http://documentserver/
  355. console.log(errorDescription);
  356. break;
  357. case -3: // DocsAPI is not defined
  358. console.log(errorDescription);
  359. break;
  360. }
  361. };
  362. const dtParams = ref({
  363. tbCode: '',
  364. tbVersion: null
  365. });
  366. const isSpredaShow = ref(false);
  367. const formRef = ref() // 表单 Ref
  368. // el-tab 点击事件
  369. const activeTab = ref('模板信息');
  370. const handleTabClick = async (pane: {
  371. paneName: string
  372. }) => {
  373. let name = pane.paneName;
  374. if (name == '模板文件') {
  375. if (!tbId.value){
  376. message.alert("先保存才能导入模板!");
  377. return
  378. }
  379. if (formData.value.tbCode) {
  380. dtParams.value.tbCode = formData.value.tbCode;
  381. isSpredaShow.value = true;
  382. } else {
  383. isSpredaShow.value = false;
  384. }
  385. }
  386. /*
  387. const spreadRefMap = {
  388. '模板': recordDesignerRef.value,
  389. }
  390. const spreadMap = {
  391. '报告记录': recordDesigner,
  392. '报告模板': reportDesigner,
  393. '检验结果': resultDesigner,
  394. '金额计算': moneyDesigner
  395. }
  396. try {
  397. if(!spreadMap[name]) return;
  398. spreadMap[name].refresh();
  399. spreadMap[name].setData("treeNodeFromJson", basicForm.value.bindingPathSchema);
  400. // 设置工作表数据源字段释义
  401. spreadRefMap[name]?.handleUpdateDesignerState.set('bindingPathDataJSON', basicForm.value.bindingPathNameJson)
  402. } catch (error) {
  403. console.error('handleTabClick报错了', error)
  404. } */
  405. }
  406. const handleBeforeTabLeave = (active, oldActive) => {
  407. }
  408. const props = defineProps({
  409. visible: {
  410. type: Boolean,
  411. default: false
  412. },
  413. id: {
  414. type: Number,
  415. default: 0
  416. },
  417. type: {
  418. type: String,
  419. default: ''
  420. }
  421. })
  422. const tbId = ref()
  423. /** 打开弹窗 */
  424. const open = async () => {
  425. /** dialogVisible.value = true
  426. // dialogTitle.value = t('action.' + type) */
  427. formType.value = props.type
  428. tbId.value = props.id
  429. // 修改时,设置数据
  430. if (tbId.value) {
  431. formLoading.value = true
  432. try {
  433. formData.value = await DynamicTbApi.getDynamicTb(tbId.value)
  434. if(formData.value.id && formData.value.formPath){
  435. getDocToDPFToken(formData.value.formPath,false);
  436. }
  437. await initConnectInfos()
  438. } finally {
  439. formLoading.value = false
  440. }
  441. } else {
  442. resetForm();
  443. }
  444. }
  445. open();
  446. //defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  447. /** 提交表单 */
  448. const emit = defineEmits(['success', 'update:visible']) // 定义 success 事件,用于操作成功后的回调
  449. const submitForm = async () => {
  450. // 校验表单
  451. await formRef.value.validate()
  452. // 提交请求
  453. formLoading.value = true
  454. try {
  455. const data = formData.value as unknown as DynamicTbVO
  456. if (formType.value === 'create') {
  457. tbId.value = await DynamicTbApi.createDynamicTb(data)
  458. formData.value.id = tbId.value
  459. formType.value = 'update'
  460. message.success(t('common.createSuccess'))
  461. } else {
  462. await DynamicTbApi.updateDynamicTb(data)
  463. message.success(t('common.updateSuccess'))
  464. }
  465. dialogVisible.value = false
  466. // 发送操作成功的事件
  467. emit('success')
  468. } finally {
  469. formLoading.value = false
  470. }
  471. }
  472. /** 关闭表单 */
  473. const handleClose = () => {
  474. clearDocument();
  475. emit('update:visible', false);
  476. }
  477. const getData = async () => {
  478. }
  479. /** 重置表单 */
  480. const resetForm = () => {
  481. formData.value = {
  482. id: undefined,
  483. tbName: undefined,
  484. tbCode: undefined,
  485. tbType: undefined,
  486. reportType: undefined,
  487. pjType: undefined,
  488. tbUrl: undefined,
  489. versionNo: undefined,
  490. tbNote: undefined,
  491. creatorName: getUser.nickname,
  492. inPath: undefined,
  493. formUrl: undefined,
  494. formPath: undefined,
  495. filePaths: [],
  496. }
  497. formRef.value?.resetFields()
  498. }
  499. </script>
  500. <style lang="scss" scoped>
  501. .unit-create-and-edit {
  502. position: absolute;
  503. left: 0;
  504. top: 0;
  505. right: 0;
  506. bottom: 0;
  507. z-index: 1000;
  508. box-sizing: border-box;
  509. background-color: #fff;
  510. overflow: hidden;
  511. :deep(.spread-designer-container) {
  512. height: calc(100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 90px);
  513. padding: 0;
  514. .default-toolbar {
  515. padding-top: 0px;
  516. }
  517. }
  518. }
  519. .c-header {
  520. position: sticky;
  521. top: 0;
  522. left: 0;
  523. display: flex;
  524. justify-content: space-between;
  525. align-items: center;
  526. height: 50px;
  527. padding: 0 20px;
  528. margin-bottom: -1px;
  529. font-size: 20px;
  530. line-height: 50px;
  531. border: 1px solid var(--el-border-color-light);
  532. background-color: #fff;
  533. z-index: 1000;
  534. }
  535. .unit-content {
  536. height: 100%;
  537. width: 100%;
  538. padding: 20px 0 56px 20px;
  539. overflow-y: hidden;
  540. :deep(.el-table) {
  541. margin-bottom: 12px;
  542. .el-table__header tr th.el-table__cell {
  543. color: #333;
  544. background-color: var(--el-border-color-light);
  545. }
  546. }
  547. :deep(.add-btn) {
  548. margin-bottom: 12px;
  549. }
  550. :deep(.c-title) {
  551. display: flex;
  552. justify-content: flex-start;
  553. align-items: center;
  554. width: 100%;
  555. height: 36px;
  556. margin-bottom: 18px;
  557. line-height: 36px;
  558. background-color: var(--el-color-primary-light-9);
  559. &::before {
  560. content: '';
  561. height: 100%;
  562. width: 3px;
  563. margin-right: 12px;
  564. background-color: var(--el-color-primary);
  565. }
  566. }
  567. :deep(.el-tabs__content) {
  568. padding-right: 20px;
  569. overflow-y: hidden;
  570. .el-row {
  571. margin: 0 !important;
  572. box-sizing: border-box;
  573. }
  574. .el-tab-pane {
  575. border: 1px solid var(--el-border-color-light);
  576. box-sizing: border-box;
  577. height: calc(100% - 49px);
  578. overflow: hidden;
  579. }
  580. }
  581. :deep(.el-tabs__header-vertical) {
  582. margin-right: -1px;
  583. border: 1px solid var(--el-border-color-light);
  584. .el-tabs__nav-wrap.is-left:after {
  585. display: none;
  586. }
  587. .el-tabs__active-bar {
  588. display: none;
  589. }
  590. .el-tabs__item {
  591. width: 220px;
  592. height: 50px;
  593. font-size: 14px;
  594. text-align: center;
  595. justify-content: center;
  596. &.is-active {
  597. background-color: var(--el-color-primary-light-9);
  598. }
  599. }
  600. }
  601. :deep(.el-table__cell) {
  602. .el-form-item {
  603. margin-bottom: 0;
  604. }
  605. }
  606. }
  607. .unit-footer-btns {
  608. position: absolute;
  609. left: 0;
  610. right: 0;
  611. bottom: 0;
  612. background: #fff;
  613. padding: 12px 0;
  614. display: flex;
  615. justify-content: center;
  616. }
  617. .form-container{
  618. height: 100%;
  619. padding-top: 15px;
  620. overflow-y: auto;
  621. }
  622. .record-template-buttons {
  623. padding: 10px 0;
  624. .el-button {
  625. margin-right: 10px;
  626. margin-bottom: 10px;
  627. }
  628. }
  629. .spread-tab-pane {
  630. height: 100%;
  631. padding: 0 !important;
  632. }
  633. .spread-scrollbar-wrapper {
  634. height: 100%;
  635. padding: 10px;
  636. box-sizing: border-box;
  637. }
  638. </style>