<template>
|
|
<div>
|
|
<LineLabel v-if="label" :label="label" />
|
|
<div v-for="(item, index) in formConfig" :key="index">
|
|
<template v-if="item.type === 'cardItem'">
|
|
<div class="grid-container">
|
|
<div v-for="(sItem, key) in item.config" class="form-item"
|
|
:class="sItem.span == 1 ? 'full-row' : ''" :key="key">
|
|
<template v-if="sItem.type === 'input'">
|
|
<div class="form-title">{{ sItem.label }}</div>
|
|
<HandleFormItem @blur="onBlur(key, $event)" :item="sItem" v-model="formFields[key]"
|
|
@copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
|
|
:orange-bg="orangeBgFields[key]" />
|
|
</template>
|
|
<template v-else-if="sItem.type === 'inputNumber'">
|
|
<div class="form-title">{{ sItem.label }}</div>
|
|
<HandleFormItem type="inputNumber" @blur="onBlur(key, $event)" :item="sItem"
|
|
@input="onInputNumberChange(key, $event)" v-model="formFields[key]"
|
|
@copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
|
|
:orange-bg="orangeBgFields[key]" />
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<template v-else-if="item.type === 'conditionItem'">
|
|
<div class="form-item ">
|
|
<div class="form-title fs-16" v-if="item.label">{{ item.label }}</div>
|
|
<div v-for="(sItem, key) in item.config" class="c-Item grid-container">
|
|
<div class="p-r-20">
|
|
<div class="form-title">{{ sItem.label }}</div>
|
|
<div class="flex flex1">
|
|
<HandleFormItem type="select" :item="sItem" v-model="formFields[key]"
|
|
@copy="onCopy(sItem, key)" @change="onSelectChange(key, $event)"
|
|
:error="errors[key]" @update:error="errors[key] = false"
|
|
:orange-bg="orangeBgFields[key]" />
|
|
|
|
</div>
|
|
</div>
|
|
<div class="p-l-20">
|
|
<div v-show="isShowOther(formFields[key])">
|
|
<div class="form-title">其他</div>
|
|
<div class="flex flex1">
|
|
<HandleFormItem @blur="onBlur(key, $event)" :item="getOtherItem(sItem)"
|
|
v-model="formFields[sItem.otherCode]" @copy="onCopy(sItem, key)"
|
|
:error="errors[sItem.otherCode]"
|
|
@update:error="errors[sItem.otherCode] = false" />
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<template v-else-if="item.type === 'cellItem'">
|
|
<div class="form-item ">
|
|
<div class="form-title fs-16" v-if="item.label">{{ item.label }}</div>
|
|
<div class="grid-container gap2">
|
|
<div v-for="(sItem, key) in item.config" class="c-Item" :class="getSpanClass(sItem)" :key="key">
|
|
<div class="form-title" v-if="sItem.label">{{ sItem.label }}</div>
|
|
<div v-if="sItem.type === 'dateTime'" class="flex1">
|
|
<HandleFormItem type="dateTime" :item="sItem" v-model="formFields[key]"
|
|
@copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
|
|
:orange-bg="orangeBgFields[key]" />
|
|
</div>
|
|
<div v-else-if="sItem.type === 'select'">
|
|
<HandleFormItem type="select" :item="sItem" v-model="formFields[key]"
|
|
@copy="onCopy(sItem, key)" @change="onSelectChange(key, $event)"
|
|
:error="errors[key]" @update:error="errors[key] = false"
|
|
:orange-bg="orangeBgFields[key]" />
|
|
</div>
|
|
<div v-else-if="sItem.type === 'input'">
|
|
<HandleFormItem @blur="onBlur(key, $event)" :item="sItem" v-model="formFields[key]"
|
|
@copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
|
|
:orange-bg="orangeBgFields[key]" />
|
|
</div>
|
|
<div v-else-if="sItem.type === 'textarea'">
|
|
<HandleFormItem @blur="onBlur(key, $event)" type="textarea" :item="sItem"
|
|
v-model="formFields[key]" @copy="onCopy(sItem, key)" :error="errors[key]"
|
|
@update:error="errors[key] = false" :orange-bg="orangeBgFields[key]" />
|
|
</div>
|
|
<div v-else-if="sItem.type === 'clickable'" class="flex1">
|
|
<HandleFormItem type="clickable" @clickable="handleClickable(sItem, $event)"
|
|
:item="sItem" :value="formFields[key]" />
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</template>
|
|
<template v-else-if="item.type === 'step'">
|
|
<div class="grid-container gap2">
|
|
<div v-for="(sItem, key) in item.config" class="c-Item flex item-center"
|
|
:class="getSpanClass(sItem)" :key="key">
|
|
<div class="step-form-title" v-if="sItem.label">{{ sItem.label }}</div>
|
|
<div v-if="sItem.type === 'dateTime'" class="flex1">
|
|
<HandleFormItem type="dateTime" :item="sItem" v-model="formFields[key]"
|
|
@copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
|
|
:orange-bg="orangeBgFields[key]" />
|
|
</div>
|
|
<div v-else-if="sItem.type === 'select'" class="flex flex1">
|
|
<HandleFormItem type="select" :item="sItem" style="width: auto;flex:1"
|
|
v-model="formFields[key]" @copy="onCopy(sItem, key)"
|
|
@change="onSelectChange(key, $event)" :error="errors[key]"
|
|
@update:error="errors[key] = false" :orange-bg="orangeBgFields[key]" />
|
|
<div v-show="isShowOther(formFields[key])" class="flex flex1">
|
|
<div class="other-title">其他</div>
|
|
<div class="flex">
|
|
<HandleFormItem @blur="onBlur(key, $event)" :item="getOtherItem(sItem)"
|
|
v-model="formFields[sItem.otherCode]" @copy="onCopy(sItem, key)"
|
|
:error="errors[sItem.otherCode]" @update:error="errors[sItem.otherCode] = false"
|
|
:orange-bg="orangeBgFields[sItem.otherCode]" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else-if="sItem.type === 'input'" class="flex flex1">
|
|
<HandleFormItem @blur="onBlur(key, $event)" class="flex1" :item="sItem"
|
|
v-model="formFields[key]" @copy="onCopy(sItem, key)" :error="errors[key]"
|
|
@update:error="errors[key] = false" :orange-bg="orangeBgFields[key]" />
|
|
<HandleFormItem class="ml-10" v-if="sItem.subType === 'select'" type="select"
|
|
:item="getSubItem(sItem)" v-model="formFields[sItem.subKey]" @copy="onCopy(sItem, key)"
|
|
@change="onSelectChange(sItem.subKey, $event)" :error="errors[sItem.subKey]"
|
|
@update:error="errors[sItem.subKey] = false"
|
|
:orange-bg="orangeBgFields[sItem.subKey]" />
|
|
<div class="ml-10" v-else-if="sItem.subType === 'span'">{{ formFields[sItem.subKey] }}</div>
|
|
<HandleFormItem class="ml-10" v-else-if="sItem.subType === 'clickable'" type="clickable"
|
|
@clickable="handleClickable(sItem, $event)" :item="getClickableItem(sItem)"
|
|
:value="formFields[sItem.subKey]" />
|
|
<div v-show="isShowOther(formFields[sItem.subKey])" class="flex flex1">
|
|
<div class="other-title">其他</div>
|
|
<div class="flex">
|
|
<HandleFormItem @blur="onBlur(key, $event)" :item="getOtherItem(sItem)"
|
|
v-model="formFields[sItem.otherCode]" @copy="onCopy(sItem, key)"
|
|
:error="errors[sItem.otherCode]" @update:error="errors[sItem.otherCode] = false"
|
|
:orange-bg="orangeBgFields[sItem.otherCode]" />
|
|
</div>
|
|
</div>
|
|
<!-- <div class="clickable" :class="getFillType(sItem.subFillType)" v-else-if = "sItem.subType ==='clickable'" @click="handleClickable(sItem,$event)">
|
|
<span v-if="formFields[sItem.subKey]">{{ formFields[sItem.subKey] }}</span>
|
|
<span v-else class="default-placeholder-text">请选择</span>
|
|
</div> -->
|
|
</div>
|
|
<div v-else-if="sItem.type === 'inputNumber'" class="flex flex1">
|
|
<HandleFormItem type="inputNumber" @blur="onBlur(key, $event)" class="flex1" :item="sItem"
|
|
@input="onInputNumberChange(key, $event)" :value="formFields[key]"
|
|
@copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false"
|
|
:orange-bg="orangeBgFields[key]" />
|
|
<HandleFormItem class="ml-10" v-if="sItem.subType === 'select'" type="select"
|
|
:item="getSubItem(sItem)" v-model="formFields[sItem.subKey]" @copy="onCopy(sItem, key)"
|
|
@change="onSelectChange(sItem.subKey, $event)" :error="errors[sItem.subKey]"
|
|
@update:error="errors[sItem.subKey] = false"
|
|
:orange-bg="orangeBgFields[sItem.subKey]" />
|
|
<div class="ml-10" v-else-if="sItem.subType === 'span'">{{ formFields[sItem.subKey] }}</div>
|
|
<HandleFormItem class="ml-10" v-else-if="sItem.subType === 'clickable'"
|
|
@clickable="handleClickable(sItem, $event)" type="clickable"
|
|
:item="getClickableItem(sItem)" :value="formFields[sItem.subKey]" />
|
|
<!-- <div class="clickable" :class="getFillType(sItem.subFillType)" v-else-if = "sItem.subType ==='clickable'" @click="handleClickable(sItem,$event)">
|
|
<span v-if="formFields[sItem.subKey]">{{ formFields[sItem.subKey] }}</span>
|
|
<span v-else class="default-placeholder-text">请选择</span>
|
|
</div> -->
|
|
</div>
|
|
<div v-else-if="sItem.type === 'clickable'" class="flex flex1">
|
|
<HandleFormItem type="clickable" @clickable="handleClickable(sItem, $event)"
|
|
:error="errors[key]" :item="sItem" :value="formFields[key]" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import HandleFormItem from "./HandleFormItem.vue";
|
|
import LineLabel from "./LineLabel.vue";
|
|
export default {
|
|
components: {
|
|
HandleFormItem,
|
|
LineLabel
|
|
},
|
|
props: {
|
|
label: {//当前表单的标题
|
|
type: String,
|
|
default: "",
|
|
},
|
|
formConfig: {
|
|
type: Array,
|
|
value: () => [],
|
|
},
|
|
formData: {
|
|
type: Object,
|
|
value: () => ({})
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
formFields: {},//表单绑定字段
|
|
allFieldsConfig: {},//包含config的所有字段,主要用于校验表单是否填写
|
|
errors: {},//存储表单错误信息,用于标红提示
|
|
orangeBgFields: {},// 存储需要橙色背景的字段
|
|
};
|
|
},
|
|
watch: {
|
|
formData: {
|
|
immediate: true,
|
|
deep: true, // 深度监听,以便检测嵌套对象变化
|
|
handler(v) {
|
|
if (v) {
|
|
this.handleFormField(true);
|
|
}
|
|
}
|
|
},
|
|
formConfig: {
|
|
immediate: true,
|
|
deep: true, // 深度监听,以便检测嵌套对象变化
|
|
handler(v) {
|
|
this.handleFormField();
|
|
}
|
|
}
|
|
},
|
|
mounted() {
|
|
this.handleFormField();
|
|
},
|
|
unmounted() {
|
|
console.log("unmounted")
|
|
this.formFields = {};//清空当前填写的数据
|
|
},
|
|
|
|
methods: {
|
|
getFillType(type) {
|
|
const typeObj = {
|
|
actFill: "orange-border",//实际填写的边框颜色
|
|
green: "green-border",
|
|
preFill: "blue-border",//预填写的边框颜色
|
|
}
|
|
return typeObj[type] || ""
|
|
},
|
|
onInputNumberChange(key, val) {
|
|
this.formFields[key] = val;
|
|
// 清除该表单项的错误状态
|
|
if (this.errors[key]) {
|
|
this.$set(this.errors, key, false);
|
|
}
|
|
},
|
|
updateFormData(key, value) {
|
|
this.formFields[key] = value;
|
|
// 清除该表单项的错误状态
|
|
if (this.errors[key]) {
|
|
this.$set(this.errors, key, false);
|
|
}
|
|
},
|
|
batchUpdateFormData(data) {
|
|
Object.keys(data).forEach(key => {
|
|
this.formFields[key] = data[key];
|
|
// 清除该表单项的错误状态
|
|
if (this.errors[key]) {
|
|
this.$set(this.errors, key, false);
|
|
}
|
|
})
|
|
},
|
|
handleClickable(sItem, event) {
|
|
console.log("clickable", sItem)
|
|
if (this.$store.state.template.templateStatus !== 'actFill') {
|
|
return
|
|
}
|
|
this.$emit("clickable", sItem)
|
|
},
|
|
//根据span判断一行显示几列
|
|
getSpanClass(sItem) {
|
|
const spanArr = ["full-row", "", "three-row"]
|
|
if (sItem.span) {
|
|
return spanArr[sItem.span - 1]
|
|
}
|
|
return ""
|
|
},
|
|
//获取其他下拉框的配置
|
|
getOtherItem(sItem) {
|
|
return {
|
|
label: "其他",
|
|
fillType: sItem.fillType,
|
|
maxlength: sItem.otherMaxlength || 50,
|
|
}
|
|
},
|
|
getClickableItem(sItem) {
|
|
return {
|
|
label: "",
|
|
type: "clickable",
|
|
fillType: sItem.subFillType || sItem.fillType,
|
|
}
|
|
},
|
|
getSubItem(sItem) {
|
|
return {
|
|
label: "",
|
|
options: sItem.subOptions || [],
|
|
fillType: sItem.subFillType || sItem.fillType,
|
|
}
|
|
},
|
|
isShowOther(v = []) {
|
|
// 确保v是数组类型,以避免类型错误
|
|
const arr = Array.isArray(v) ? v : [v];
|
|
//和凡哥商量,只要value为负数都显示其他
|
|
return arr.some(item => item < 0);
|
|
},
|
|
// 根据formConfig回填form表单数据
|
|
handleFormField(update = false) {
|
|
const result = {};
|
|
let config = {};
|
|
const { formConfig, formData, formFields } = this;
|
|
// 遍历配置
|
|
formConfig.forEach((item) => {
|
|
if (item.config) {
|
|
// 合并配置项
|
|
config = { ...config, ...item.config }
|
|
|
|
// 处理每个配置项
|
|
Object.keys(item.config).forEach(key => {
|
|
const currentConfig = item.config[key];
|
|
let value = formData[key];
|
|
|
|
// 如果formFields中已经有值,保持原值(用户输入或之前设置的值)
|
|
if (formFields[key] !== null &&
|
|
formFields[key] !== undefined &&
|
|
formFields[key] !== ''
|
|
// typeof formFields[key] !== 'object'
|
|
) {
|
|
|
|
// 保留原值,不使用formData中的值
|
|
result[key] = formFields[key];
|
|
|
|
} else {
|
|
// 使用formData中的值
|
|
result[key] = value;
|
|
}
|
|
|
|
// 处理特殊字段 - "其他"字段
|
|
if (currentConfig.otherCode) {
|
|
const { otherCode } = currentConfig;
|
|
//如果是更新的话,优先使用formFields中的值
|
|
if (update) {
|
|
result[otherCode] = formFields[otherCode] || formData[otherCode] || '';
|
|
} else {
|
|
result[otherCode] = formData[otherCode] || formFields[otherCode] || '';
|
|
}
|
|
config[otherCode] = { label: "其他", parentKey: key, type: "input", fillType: currentConfig.fillType }
|
|
}
|
|
if (currentConfig.subKey) {
|
|
const { subKey } = currentConfig;
|
|
if (update) {
|
|
result[subKey] = formFields[subKey] || formData[subKey] || '';
|
|
} else {
|
|
result[subKey] = formData[subKey] || formFields[subKey] || '';
|
|
}
|
|
config[subKey] = { label: currentConfig.label, subKey, type: currentConfig.subType, fillType: currentConfig.subFillType || currentConfig.fillType }
|
|
}
|
|
});
|
|
|
|
// 处理可能存在的直接otherCode字段
|
|
if (item.config?.otherCode) {
|
|
config[item.config?.otherCode] = item.config?.otherCode;
|
|
}
|
|
}
|
|
});
|
|
// 更新表单字段
|
|
this.formFields = result;
|
|
this.allFieldsConfig = config;
|
|
},
|
|
//判断是否禁用
|
|
getDisabled() {
|
|
const { item } = this;
|
|
const { fillType } = item;
|
|
if (item.hasOwnProperty("disabled")) {
|
|
return item.disabled
|
|
} else {
|
|
const { templateStatus } = this.$store.state.template;
|
|
if (fillType === "actFill") {//当模板状态是实际填写时,只有当fillType是actFill时才能填写
|
|
return templateStatus !== "actFill"
|
|
} else if (fillType === "preFill") {//当模板状态是预填写时,只有当fillType是preFill才能填写
|
|
return templateStatus !== "preFill"
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
},
|
|
// 表单数据校验
|
|
validateFormData() {
|
|
const { formFields, allFieldsConfig } = this;
|
|
const { templateStatus } = this.$store.state.template;
|
|
const errors = [];
|
|
|
|
// 清空之前的错误状态
|
|
this.errors = {};
|
|
|
|
for (const key in allFieldsConfig) {
|
|
const o = allFieldsConfig[key];
|
|
if (o.otherCode) {//
|
|
if (o.type === "select") {
|
|
const isSelectedOther = this.isShowOther(formFields[key]);
|
|
if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
|
|
formFields[o.otherCode] = "";
|
|
}
|
|
} else if (o.subType === "select") {
|
|
const isSelectedOther = this.isShowOther(formFields[o.subKey]);
|
|
if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
|
|
formFields[o.otherCode] = "";
|
|
}
|
|
}
|
|
|
|
}
|
|
if (this.isValueEmpty(formFields[key])) {
|
|
// 其他字段需要判断是否显示再校验
|
|
if (o.label === "其他" && !this.isShowOther(formFields[o.parentKey])) {
|
|
continue
|
|
}
|
|
//span的字段不校验
|
|
if (o.type === "span") {
|
|
continue
|
|
}
|
|
if (o.fillType == templateStatus && !o.disabled) {
|
|
let prefix = "";
|
|
if (o.type === "input" || o.type === "inputNumber" || o.type === "textarea") {
|
|
prefix = "填写";
|
|
} else {
|
|
prefix = "选择";
|
|
}
|
|
|
|
const errorItem = {
|
|
field: key,
|
|
label: o.label,
|
|
error: `请${prefix}${o.label}`
|
|
};
|
|
|
|
errors.push(errorItem);
|
|
this.$set(this.errors, key, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
valid: errors.length === 0,
|
|
errors: errors
|
|
};
|
|
},
|
|
// 判断值是否为空
|
|
isValueEmpty(value) {
|
|
if (value === null || value === undefined || value === '') {
|
|
return true;
|
|
}
|
|
if (typeof value === 'string' && value.trim() === '') {
|
|
return true;
|
|
}
|
|
if (Array.isArray(value) && value.length === 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
getFormData() {
|
|
// 数据校验
|
|
const validateResult = this.validateFormData();
|
|
return new Promise((resolve, reject) => {
|
|
if (validateResult.valid) {
|
|
resolve(this.formFields);
|
|
} else {
|
|
// this.$message.error("表单内容未填完,请填写后再提交");
|
|
reject(validateResult.errors[0].error);
|
|
}
|
|
});
|
|
},
|
|
//直接获取表单数据,不做校验
|
|
getDirectFormData() {
|
|
return this.formFields;
|
|
},
|
|
getFormDataByKey(key) {
|
|
return this.formFields[key];
|
|
},
|
|
onBlur(key, val) {
|
|
// compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色
|
|
const currentFieldConfig = this.allFieldsConfig[key];
|
|
if (currentFieldConfig && currentFieldConfig.fillType === "actFill" && currentFieldConfig.compareTo) {
|
|
const compareToKey = currentFieldConfig.compareTo;
|
|
const compareToValue = this.formFields[compareToKey];
|
|
|
|
// 比较当前值和compareTo值,如果不相等则设置橙色背景
|
|
if (val !== compareToValue) {
|
|
this.$set(this.orangeBgFields, key, true);
|
|
} else {
|
|
// 相等则移除橙色背景
|
|
this.$set(this.orangeBgFields, key, false);
|
|
}
|
|
}
|
|
|
|
this.$emit("blur", { key, value: val, ...this.formFields });
|
|
},
|
|
onSelectChange(key, val) {
|
|
// 获取对应的配置
|
|
const currentConfig = this.allFieldsConfig[key];
|
|
|
|
// // 确保多选下拉框的值是数组类型
|
|
// if (currentConfig && currentConfig.multiple) {
|
|
// // 多选情况,确保值为数组类型
|
|
// this.formFields[key] = Array.isArray(val) ? val : (val ? [val] : []);
|
|
// } else {
|
|
// 单选情况
|
|
this.formFields[key] = val;
|
|
// }
|
|
this.$emit("select", { key, value: val });
|
|
// 清除该表单项的错误状态
|
|
if (this.errors[key]) {
|
|
this.$set(this.errors, key, false);
|
|
}
|
|
},
|
|
//复制
|
|
onCopy(config, key) {
|
|
const { formFields } = this;
|
|
if (config.copyFrom) {
|
|
formFields[key] = formFields[config.copyFrom];
|
|
this.onBlur(key, formFields[key]);
|
|
}
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.grid-container {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
/* 默认2列 */
|
|
gap: 0 20px;
|
|
}
|
|
|
|
.gap2 {
|
|
gap: 0 64px;
|
|
}
|
|
|
|
.w-100 {
|
|
width: 100%;
|
|
}
|
|
|
|
.form-item {
|
|
background: #fff;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
|
|
margin-top: 20px;
|
|
padding: 20px;
|
|
border-radius: 5px 5px;
|
|
|
|
}
|
|
|
|
/* 或者使用 span 语法 */
|
|
.full-row {
|
|
grid-column: span 2;
|
|
}
|
|
|
|
.three-row {
|
|
grid-column: span 3;
|
|
}
|
|
|
|
|
|
.c-Item {
|
|
&:not(:last-child) {
|
|
margin-bottom: 16px;
|
|
}
|
|
}
|
|
|
|
.eo {
|
|
&:nth-child(even) {
|
|
padding-left: 20px;
|
|
}
|
|
|
|
&:nth-child(odd) {
|
|
padding-right: 20px;
|
|
}
|
|
}
|
|
|
|
.default-placeholder-text {
|
|
color: #C0C4CC;
|
|
}
|
|
|
|
.form-title {
|
|
margin-bottom: 12px;
|
|
font-size: 14px;
|
|
font-weight: normal;
|
|
color: #606266;
|
|
}
|
|
|
|
.step-form-title {
|
|
font-size: 14px;
|
|
font-weight: normal;
|
|
color: #606266;
|
|
width: 150px;
|
|
text-align: right;
|
|
padding-right: 10px;
|
|
}
|
|
|
|
.p-r-20 {
|
|
padding-right: 20px;
|
|
}
|
|
|
|
.p-l-20 {
|
|
padding-left: 20px;
|
|
}
|
|
|
|
.fs-16 {
|
|
font-size: 0.96rem;
|
|
font-weight: bold;
|
|
color: #464647
|
|
}
|
|
|
|
.flex1 {
|
|
flex: 1;
|
|
}
|
|
|
|
.flex {
|
|
display: flex;
|
|
}
|
|
|
|
.other-title {
|
|
width: 50px;
|
|
text-align: right;
|
|
margin: 0 10px;
|
|
font-size: 14px;
|
|
font-weight: normal;
|
|
color: #606266;
|
|
}
|
|
|
|
.mr-24 {
|
|
margin-right: 24px;
|
|
}
|
|
|
|
.sub-select {
|
|
width: 100px;
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.orange-border {
|
|
border-color: #f9c588;
|
|
}
|
|
|
|
.green-border {
|
|
border-color: green;
|
|
}
|
|
|
|
.blue-border {
|
|
border-color: #4ea2ff;
|
|
}
|
|
|
|
.ml-10 {
|
|
margin-left: 10px;
|
|
}
|
|
</style>
|