华西海圻ELN前端工程
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

680 lines
29 KiB

3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <template>
  2. <div>
  3. <LineLabel v-if="label" :label="label" />
  4. <div v-for="(item, index) in formConfig" :key="index">
  5. <template v-if="item.type === 'cardItem'">
  6. <div class="grid-container">
  7. <div v-for="(sItem, key) in item.config" class="form-item"
  8. :class="sItem.span == 1 ? 'full-row' : ''" :key="key">
  9. <template v-if="sItem.type === 'input'">
  10. <div class="form-title">{{ $t( sItem.label) }}</div>
  11. <HandleFormItem :field-item-label="fieldItemLabel" @blur="onBlur(key, $event)" :item="sItem" v-model="formFields[key]"
  12. :field-key="prefixKey+'_'+key"
  13. @copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
  14. :orange-bg="orangeBgFields[key]" />
  15. </template>
  16. <template v-else-if="sItem.type === 'inputNumber'">
  17. <div class="form-title">{{ $t( sItem.label) }}</div>
  18. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" type="inputNumber" @blur="onBlur(key, $event)" :item="sItem"
  19. @input="onInputNumberChange(key, $event)" v-model="formFields[key]"
  20. @copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
  21. :orange-bg="orangeBgFields[key]" />
  22. </template>
  23. </div>
  24. </div>
  25. </template>
  26. <template v-else-if="item.type === 'conditionItem'">
  27. <div class="form-item ">
  28. <div class="form-title fs-16" v-if="item.label">{{ $t( item.label) }}</div>
  29. <div v-for="(sItem, key) in item.config" class="c-Item grid-container">
  30. <div class="p-r-20">
  31. <div class="form-title">{{ $t( sItem.label) }}</div>
  32. <div class="flex flex1">
  33. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" type="select" :item="sItem" v-model="formFields[key]"
  34. @copy="onCopy(sItem, key)" @change="onSelectChange(key, $event)"
  35. :error="errors[key]" @update:error="errors[key] = false"
  36. :orange-bg="orangeBgFields[key]" />
  37. </div>
  38. </div>
  39. <div class="p-l-20">
  40. <div v-show="isShowOther(formFields[key])">
  41. <div class="form-title">其他</div>
  42. <div class="flex flex1">
  43. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+sItem.otherCode" @blur="onBlur(key, $event)" :item="getOtherItem(sItem)"
  44. v-model="formFields[sItem.otherCode]" @copy="onCopy(sItem, key)"
  45. :error="errors[sItem.otherCode]"
  46. @update:error="errors[sItem.otherCode] = false" />
  47. </div>
  48. </div>
  49. </div>
  50. </div>
  51. </div>
  52. </template>
  53. <template v-else-if="item.type === 'cellItem'">
  54. <div class="form-item ">
  55. <div class="form-title fs-16" v-if="item.label">{{ $t( item.label) }}</div>
  56. <div class="grid-container gap2">
  57. <div v-for="(sItem, key) in item.config" class="c-Item" :class="getSpanClass(sItem)" :key="key">
  58. <div class="form-title" v-if="sItem.label">{{ $t( sItem.label) }}</div>
  59. <div v-if="sItem.type === 'dateTime'" class="flex1">
  60. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" type="dateTime" :item="sItem" v-model="formFields[key]"
  61. @copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
  62. :orange-bg="orangeBgFields[key]" />
  63. </div>
  64. <div v-else-if="sItem.type === 'select'">
  65. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" type="select" :item="sItem" v-model="formFields[key]"
  66. @copy="onCopy(sItem, key)" @change="onSelectChange(key, $event)"
  67. :error="errors[key]" @update:error="errors[key] = false"
  68. :orange-bg="orangeBgFields[key]" />
  69. </div>
  70. <div v-else-if="sItem.type === 'input'">
  71. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" @blur="onBlur(key, $event)" :item="sItem" v-model="formFields[key]"
  72. @copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
  73. :orange-bg="orangeBgFields[key]" />
  74. </div>
  75. <div v-else-if="sItem.type === 'textarea'">
  76. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" @blur="onBlur(key, $event)" type="textarea" :item="sItem"
  77. v-model="formFields[key]" @copy="onCopy(sItem, key)" :error="errors[key]"
  78. @update:error="errors[key] = false" :orange-bg="orangeBgFields[key]" />
  79. </div>
  80. <div v-else-if="sItem.type === 'clickable'" class="flex1">
  81. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" type="clickable" @clickable="handleClickable(sItem, $event)"
  82. :item="sItem" :value="formFields[key]" />
  83. </div>
  84. </div>
  85. </div>
  86. </div>
  87. </template>
  88. <template v-else-if="item.type === 'step'">
  89. <div class="grid-container gap2">
  90. <div v-for="(sItem, key) in item.config" class="c-Item flex item-center"
  91. :class="getSpanClass(sItem)" :key="key">
  92. <div class="step-form-title" v-if="sItem.label">{{ $t( sItem.label) }}</div>
  93. <div v-if="sItem.type === 'dateTime'" class="flex1">
  94. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" type="dateTime" :item="sItem" v-model="formFields[key]"
  95. @copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
  96. :orange-bg="orangeBgFields[key]" />
  97. </div>
  98. <div v-else-if="sItem.type === 'select'" class="flex flex1">
  99. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" type="select" :item="sItem" style="width: auto;flex:1"
  100. v-model="formFields[key]" @copy="onCopy(sItem, key)"
  101. @change="onSelectChange(key, $event)" :error="errors[key]"
  102. @update:error="errors[key] = false" :orange-bg="orangeBgFields[key]" />
  103. <div v-show="isShowOther(formFields[key])" class="flex flex1">
  104. <div class="other-title">其他</div>
  105. <div class="flex">
  106. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+sItem.otherCode" @blur="onBlur(key, $event)" :item="getOtherItem(sItem)"
  107. v-model="formFields[sItem.otherCode]" @copy="onCopy(sItem, key)"
  108. :error="errors[sItem.otherCode]" @update:error="errors[sItem.otherCode] = false"
  109. :orange-bg="orangeBgFields[sItem.otherCode]" />
  110. </div>
  111. </div>
  112. </div>
  113. <div v-else-if="sItem.type === 'input'" class="flex flex1">
  114. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" @blur="onBlur(key, $event)" class="flex1" :item="sItem"
  115. v-model="formFields[key]" @copy="onCopy(sItem, key)" :error="errors[key]"
  116. @update:error="errors[key] = false" :orange-bg="orangeBgFields[key]" />
  117. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+sItem.subKey" class="ml-10" v-if="sItem.subType === 'select'" type="select"
  118. :item="getSubItem(sItem)" v-model="formFields[sItem.subKey]" @copy="onCopy(sItem, key)"
  119. @change="onSelectChange(sItem.subKey, $event)" :error="errors[sItem.subKey]"
  120. @update:error="errors[sItem.subKey] = false"
  121. :orange-bg="orangeBgFields[sItem.subKey]" />
  122. <div class="ml-10 item-span" v-else-if="sItem.subType === 'span'">{{ formFields[sItem.subKey] }}</div>
  123. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+sItem.subKey" class="ml-10" v-else-if="sItem.subType === 'clickable'" type="clickable"
  124. @clickable="handleClickable(sItem, $event)" :item="getClickableItem(sItem)"
  125. :value="formFields[sItem.subKey]" />
  126. <div v-show="isShowOther(formFields[sItem.subKey])" class="flex flex1">
  127. <div class="other-title">其他</div>
  128. <div class="flex flex1">
  129. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+sItem.otherCode" @blur="onBlur(key, $event)" :item="getOtherItem(sItem)"
  130. v-model="formFields[sItem.otherCode]" @copy="onCopy(sItem, key)"
  131. :error="errors[sItem.otherCode]" @update:error="errors[sItem.otherCode] = false"
  132. :orange-bg="orangeBgFields[sItem.otherCode]" />
  133. </div>
  134. </div>
  135. <!-- <div class="clickable" :class="getFillType(sItem.subFillType)" v-else-if = "sItem.subType ==='clickable'" @click="handleClickable(sItem,$event)">
  136. <span v-if="formFields[sItem.subKey]">{{ formFields[sItem.subKey] }}</span>
  137. <span v-else class="default-placeholder-text">请选择</span>
  138. </div> -->
  139. </div>
  140. <div v-else-if="sItem.type === 'inputNumber'" class="flex flex1">
  141. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" type="inputNumber" @blur="onBlur(key, $event)" class="flex1" :item="sItem"
  142. @input="onInputNumberChange(key, $event)" :value="formFields[key]"
  143. @copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
  144. :orange-bg="orangeBgFields[key]" />
  145. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+sItem.subKey" class="ml-10" v-if="sItem.subType === 'select'" type="select"
  146. :item="getSubItem(sItem)" v-model="formFields[sItem.subKey]" @copy="onCopy(sItem, key)"
  147. @change="onSelectChange(sItem.subKey, $event)" :error="errors[sItem.subKey]"
  148. @update:error="errors[sItem.subKey] = false"
  149. :orange-bg="orangeBgFields[sItem.subKey]" />
  150. <div class="ml-10 item-span" v-else-if="sItem.subType === 'span'">{{ formFields[sItem.subKey] }}</div>
  151. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+sItem.subKey" class="ml-10" v-else-if="sItem.subType === 'clickable'"
  152. @clickable="handleClickable(sItem, $event)" type="clickable"
  153. :item="getClickableItem(sItem)" :value="formFields[sItem.subKey]" />
  154. <!-- <div class="clickable" :class="getFillType(sItem.subFillType)" v-else-if = "sItem.subType ==='clickable'" @click="handleClickable(sItem,$event)">
  155. <span v-if="formFields[sItem.subKey]">{{ formFields[sItem.subKey] }}</span>
  156. <span v-else class="default-placeholder-text">请选择</span>
  157. </div> -->
  158. </div>
  159. <div v-else-if="sItem.type === 'clickable'" class="flex flex1">
  160. <HandleFormItem :field-item-label="fieldItemLabel" :field-key="prefixKey+'_'+key" type="clickable" @clickable="handleClickable(sItem, $event)"
  161. :error="errors[key]" :item="sItem" :value="formFields[key]" />
  162. </div>
  163. </div>
  164. </div>
  165. </template>
  166. </div>
  167. </div>
  168. </template>
  169. <script>
  170. import HandleFormItem from "./HandleFormItem.vue";
  171. import LineLabel from "./LineLabel.vue";
  172. export default {
  173. inject: ['templateFillType'],
  174. components: {
  175. HandleFormItem,
  176. LineLabel
  177. },
  178. props: {
  179. label: {//当前表单的标题
  180. type: String,
  181. default: "",
  182. },
  183. formConfig: {
  184. type: Array,
  185. value: () => [],
  186. },
  187. formData: {
  188. type: Object,
  189. value: () => ({})
  190. },
  191. //主要标识当前表单属于哪个模块,用于传给后端
  192. fieldItemLabel: {
  193. type: String,
  194. default: "",
  195. },
  196. //循环组件的情况下需要用这个来区分字段
  197. prefixKey:{
  198. type: String,
  199. default: "",
  200. }
  201. },
  202. data() {
  203. return {
  204. formFields: {},//表单绑定字段
  205. allFieldsConfig: {},//包含config的所有字段,主要用于校验表单是否填写
  206. errors: {},//存储表单错误信息,用于标红提示
  207. orangeBgFields: {},// 存储需要橙色背景的字段
  208. };
  209. },
  210. watch: {
  211. formData: {
  212. immediate: true,
  213. deep: true, // 深度监听,以便检测嵌套对象变化
  214. handler(v) {
  215. if (v) {
  216. this.handleFormField(true);
  217. }
  218. }
  219. },
  220. fieldItemLabel: {
  221. immediate: true,
  222. deep: true, // 深度监听,以便检测嵌套对象变化
  223. handler(v) {
  224. if (v) {
  225. console.log(v,"fieldItemLabel")
  226. }
  227. }
  228. },
  229. formConfig: {
  230. immediate: true,
  231. deep: true, // 深度监听,以便检测嵌套对象变化
  232. handler(v) {
  233. this.handleFormField();
  234. }
  235. }
  236. },
  237. mounted() {
  238. this.handleFormField();
  239. },
  240. unmounted() {
  241. console.log("unmounted")
  242. this.formFields = {};//清空当前填写的数据
  243. },
  244. methods: {
  245. getFillType(type) {
  246. const typeObj = {
  247. actFill: "orange-border",//实际填写的边框颜色
  248. green: "green-border",
  249. preFill: "blue-border",//预填写的边框颜色
  250. }
  251. return typeObj[type] || ""
  252. },
  253. onInputNumberChange(key, val) {
  254. this.formFields[key] = val;
  255. // 清除该表单项的错误状态
  256. if (this.errors[key]) {
  257. this.$set(this.errors, key, false);
  258. }
  259. },
  260. //更新表单数据
  261. updateFormData(key, value) {
  262. this.formFields[key] = value;
  263. // 清除该表单项的错误状态
  264. if (this.errors[key]) {
  265. this.$set(this.errors, key, false);
  266. }
  267. },
  268. //批量更新表单数据
  269. batchUpdateFormData(data) {
  270. Object.keys(data).forEach(key => {
  271. this.formFields[key] = data[key];
  272. // 清除该表单项的错误状态
  273. if (this.errors[key]) {
  274. this.$set(this.errors, key, false);
  275. }
  276. })
  277. },
  278. handleClickable(sItem, event) {
  279. console.log("clickable", sItem)
  280. if (this.templateFillType !== 'actFill') {
  281. return
  282. }
  283. this.$emit("clickable", sItem)
  284. },
  285. //根据span判断一行显示几列
  286. getSpanClass(sItem) {
  287. const spanArr = ["full-row", "", "three-row"]
  288. if (sItem.span) {
  289. return spanArr[sItem.span - 1]
  290. }
  291. return ""
  292. },
  293. //获取其他下拉框的配置
  294. getOtherItem(sItem) {
  295. return {
  296. label: "其他",
  297. fillType: sItem.fillType,
  298. maxlength: sItem.otherMaxlength || 50,
  299. parentLabel: sItem.label,
  300. }
  301. },
  302. getClickableItem(sItem) {
  303. return {
  304. label: "",
  305. type: "clickable",
  306. fillType: sItem.subFillType || sItem.fillType,
  307. parentLabel: sItem.label,
  308. }
  309. },
  310. getSubItem(sItem) {
  311. return {
  312. label: "",
  313. options: sItem.subOptions || [],
  314. fillType: sItem.subFillType || sItem.fillType,
  315. parentLabel: sItem.label,
  316. }
  317. },
  318. isShowOther(v = []) {
  319. // 确保v是数组类型,以避免类型错误
  320. const arr = Array.isArray(v) ? v : [v];
  321. //和凡哥商量,只要value为负数都显示其他
  322. return arr.some(item => item < 0);
  323. },
  324. // 根据formConfig回填form表单数据
  325. handleFormField(update = false) {
  326. const result = {};
  327. let config = {};
  328. const { formConfig, formData, formFields } = this;
  329. // 遍历配置
  330. formConfig.forEach((item) => {
  331. if (item.config) {
  332. // 合并配置项
  333. config = { ...config, ...item.config }
  334. // 处理每个配置项
  335. Object.keys(item.config).forEach(key => {
  336. const currentConfig = item.config[key];
  337. let value = formData[key];
  338. // 如果formFields中已经有值,保持原值(用户输入或之前设置的值)
  339. if (formFields[key] !== null &&
  340. formFields[key] !== undefined &&
  341. formFields[key] !== ''
  342. // typeof formFields[key] !== 'object'
  343. ) {
  344. // 保留原值,不使用formData中的值
  345. result[key] = formFields[key];
  346. } else {
  347. // 使用formData中的值
  348. result[key] = value;
  349. }
  350. // 处理特殊字段 - "其他"字段
  351. if (currentConfig.otherCode) {
  352. const { otherCode } = currentConfig;
  353. //如果是更新的话,优先使用formFields中的值
  354. if (update) {
  355. result[otherCode] = formFields[otherCode] || formData[otherCode] || '';
  356. } else {
  357. result[otherCode] = formData[otherCode] || formFields[otherCode] || '';
  358. }
  359. config[otherCode] = { label: "其他", parentKey: key, type: "input", fillType: currentConfig.fillType }
  360. }
  361. if (currentConfig.subKey) {
  362. const { subKey } = currentConfig;
  363. if (update) {
  364. result[subKey] = formFields[subKey] || formData[subKey] || '';
  365. } else {
  366. result[subKey] = formData[subKey] || formFields[subKey] || '';
  367. }
  368. config[subKey] = { label: currentConfig.label, subKey, type: currentConfig.subType, fillType: currentConfig.subFillType || currentConfig.fillType }
  369. }
  370. });
  371. // 处理可能存在的直接otherCode字段
  372. if (item.config?.otherCode) {
  373. config[item.config?.otherCode] = item.config?.otherCode;
  374. }
  375. }
  376. });
  377. // 更新表单字段
  378. this.formFields = result;
  379. this.allFieldsConfig = config;
  380. },
  381. //判断是否禁用
  382. getDisabled() {
  383. const { item } = this;
  384. const { fillType } = item;
  385. if (item.hasOwnProperty("disabled")) {
  386. return item.disabled
  387. } else {
  388. if (fillType === "actFill") {//当模板状态是实际填写时,只有当fillType是actFill时才能填写
  389. return this.templateFillType !== "actFill"
  390. } else if (fillType === "preFill") {//当模板状态是预填写时,只有当fillType是preFill才能填写
  391. return this.templateFillType !== "preFill"
  392. } else {
  393. return true
  394. }
  395. }
  396. },
  397. // 表单数据校验
  398. validateFormData() {
  399. const { formFields, allFieldsConfig } = this;
  400. const errors = [];
  401. // 清空之前的错误状态
  402. this.errors = {};
  403. for (const key in allFieldsConfig) {
  404. const o = allFieldsConfig[key];
  405. if (o.otherCode) {//
  406. if (o.type === "select") {
  407. const isSelectedOther = this.isShowOther(formFields[key]);
  408. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  409. formFields[o.otherCode] = "";
  410. }
  411. } else if (o.subType === "select") {
  412. const isSelectedOther = this.isShowOther(formFields[o.subKey]);
  413. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  414. formFields[o.otherCode] = "";
  415. }
  416. }
  417. }
  418. if (this.isValueEmpty(formFields[key])) {
  419. // 其他字段需要判断是否显示再校验
  420. if (o.label === "其他" && !this.isShowOther(formFields[o.parentKey])) {
  421. continue
  422. }
  423. //span的字段不校验
  424. if (o.type === "span") {
  425. continue
  426. }
  427. if (o.fillType === this.templateFillType && !o.disabled) {
  428. let prefix = "";
  429. if (o.type === "input" || o.type === "inputNumber" || o.type === "textarea") {
  430. prefix = "填写";
  431. } else {
  432. prefix = "选择";
  433. }
  434. const errorItem = {
  435. field: key,
  436. label: o.label,
  437. error: `${prefix}${o.label}`
  438. };
  439. errors.push(errorItem);
  440. this.$set(this.errors, key, true);
  441. }
  442. }
  443. }
  444. return {
  445. valid: errors.length === 0,
  446. errors: errors
  447. };
  448. },
  449. // 判断值是否为空
  450. isValueEmpty(value) {
  451. if (value === null || value === undefined || value === '') {
  452. return true;
  453. }
  454. if (typeof value === 'string' && value.trim() === '') {
  455. return true;
  456. }
  457. if (Array.isArray(value) && value.length === 0) {
  458. return true;
  459. }
  460. return false;
  461. },
  462. getFormData() {
  463. // 数据校验
  464. const validateResult = this.validateFormData();
  465. return new Promise((resolve, reject) => {
  466. if (validateResult.valid) {
  467. resolve(this.formFields);
  468. } else {
  469. // this.$message.error("表单内容未填完,请填写后再提交");
  470. reject(validateResult.errors[0].error);
  471. }
  472. });
  473. },
  474. //直接获取表单数据,不做校验
  475. getFilledFormData() {
  476. return this.formFields;
  477. },
  478. getFormDataByKey(key) {
  479. return this.formFields[key];
  480. },
  481. onBlur(key, val) {
  482. // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色
  483. const currentFieldConfig = this.allFieldsConfig[key];
  484. if (currentFieldConfig && currentFieldConfig.fillType === "actFill" && currentFieldConfig.compareTo) {
  485. const compareToKey = currentFieldConfig.compareTo;
  486. const compareToValue = this.formFields[compareToKey];
  487. // 比较当前值和compareTo值,如果不相等则设置橙色背景
  488. if (val !== compareToValue) {
  489. this.$set(this.orangeBgFields, key, true);
  490. } else {
  491. // 相等则移除橙色背景
  492. this.$set(this.orangeBgFields, key, false);
  493. }
  494. }
  495. this.$emit("blur", { key, value: val, ...this.formFields });
  496. },
  497. onSelectChange(key, val) {
  498. // 获取对应的配置
  499. const currentConfig = this.allFieldsConfig[key];
  500. // // 确保多选下拉框的值是数组类型
  501. // if (currentConfig && currentConfig.multiple) {
  502. // // 多选情况,确保值为数组类型
  503. // this.formFields[key] = Array.isArray(val) ? val : (val ? [val] : []);
  504. // } else {
  505. // 单选情况
  506. this.formFields[key] = val;
  507. // }
  508. this.$emit("select", { key, value: val });
  509. // 清除该表单项的错误状态
  510. if (this.errors[key]) {
  511. this.$set(this.errors, key, false);
  512. }
  513. },
  514. //复制
  515. onCopy(config, key) {
  516. const { formFields } = this;
  517. if (config.copyFrom) {
  518. formFields[key] = formFields[config.copyFrom];
  519. this.onBlur(key, formFields[key]);
  520. }
  521. },
  522. },
  523. }
  524. </script>
  525. <style lang="scss">
  526. .grid-container {
  527. display: grid;
  528. grid-template-columns: repeat(2, 1fr);
  529. /* 默认2列 */
  530. gap: 0 20px;
  531. }
  532. .gap2 {
  533. gap: 0 64px;
  534. }
  535. .w-100 {
  536. width: 100%;
  537. }
  538. .form-item {
  539. background: #fff;
  540. padding: 20px;
  541. border-radius: 8px;
  542. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
  543. margin-top: 20px;
  544. padding: 20px;
  545. border-radius: 5px 5px;
  546. }
  547. /* 或者使用 span 语法 */
  548. .full-row {
  549. grid-column: span 2;
  550. }
  551. .three-row {
  552. grid-column: span 3;
  553. }
  554. .c-Item {
  555. &:not(:last-child) {
  556. margin-bottom: 16px;
  557. }
  558. }
  559. .eo {
  560. &:nth-child(even) {
  561. padding-left: 20px;
  562. }
  563. &:nth-child(odd) {
  564. padding-right: 20px;
  565. }
  566. }
  567. .default-placeholder-text {
  568. color: #C0C4CC;
  569. }
  570. .form-title {
  571. margin-bottom: 12px;
  572. font-size: 14px;
  573. font-weight: normal;
  574. color: #606266;
  575. }
  576. .step-form-title {
  577. font-size: 14px;
  578. font-weight: normal;
  579. color: #606266;
  580. width: 150px;
  581. text-align: right;
  582. padding-right: 10px;
  583. }
  584. .p-r-20 {
  585. padding-right: 20px;
  586. }
  587. .p-l-20 {
  588. padding-left: 20px;
  589. }
  590. .fs-16 {
  591. font-size: 0.96rem;
  592. font-weight: bold;
  593. color: #464647
  594. }
  595. .flex1 {
  596. flex: 1;
  597. }
  598. .flex {
  599. display: flex;
  600. }
  601. .other-title {
  602. width: 50px;
  603. text-align: right;
  604. margin: 0 10px;
  605. font-size: 14px;
  606. font-weight: normal;
  607. color: #606266;
  608. }
  609. .mr-24 {
  610. margin-right: 24px;
  611. }
  612. .sub-select {
  613. width: 100px;
  614. margin-left: 10px;
  615. }
  616. .orange-border {
  617. border-color: #f9c588;
  618. }
  619. .green-border {
  620. border-color: green;
  621. }
  622. .blue-border {
  623. border-color: #4ea2ff;
  624. }
  625. .ml-10 {
  626. margin-left: 10px;
  627. }
  628. .item-span{
  629. color: #606266;
  630. font-size: 14px;
  631. }
  632. </style>