750 lines
22 KiB
Vue
750 lines
22 KiB
Vue
<template>
|
||
<div class="function-form-model">
|
||
<el-dialog
|
||
:close-on-click-modal="false"
|
||
:modal="false"
|
||
:title="title"
|
||
:visible="visible"
|
||
class="params-eldialog"
|
||
top="5vh"
|
||
width="800px"
|
||
@close="$emit('update:visible', false)"
|
||
>
|
||
<el-form
|
||
ref="form"
|
||
:model="form"
|
||
:rules="rules"
|
||
label-position="top"
|
||
style="padding: 0 15px"
|
||
>
|
||
<el-row :gutter="20">
|
||
<el-col :span="12">
|
||
<el-form-item label="标识:" prop="id">
|
||
<el-input
|
||
v-model="form.id"
|
||
placeholder="请输入标识"
|
||
@input="inputChange"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<el-form-item label="功能名称:" prop="name">
|
||
<el-input v-model="form.name" placeholder="请输入功能名称" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-form-item label="输入参数:" prop="inputs">
|
||
<el-table :data="form.inputs" height="300px">
|
||
<el-table-column align="left" label="标识" prop="id" />
|
||
<el-table-column align="left" label="参数名称" prop="name" />
|
||
<el-table-column align="center" label="是否必选" prop="required">
|
||
<template slot-scope="scope">
|
||
<span>{{ scope.row.expands.required ? "是" : "否" }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column align="left" label="数据类型" prop="type">
|
||
<template slot-scope="scope">
|
||
<span>{{ dataTypeOption[scope.row.valueType.type] }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
align="center"
|
||
class-name="small-padding fixed-width"
|
||
label="操作"
|
||
width="200px"
|
||
>
|
||
<template slot-scope="scope">
|
||
<el-button
|
||
:disabled="scope.$index === 0"
|
||
icon="el-icon-arrow-up"
|
||
size="mini"
|
||
type="text"
|
||
@click="handleInputUp(scope.$index)"
|
||
>上移</el-button>
|
||
<el-button
|
||
:disabled="scope.$index === form.inputs.length - 1"
|
||
icon="el-icon-arrow-down"
|
||
size="mini"
|
||
type="text"
|
||
@click="handleInputDown(scope.$index)"
|
||
>下移</el-button>
|
||
<el-button
|
||
icon="el-icon-edit"
|
||
size="mini"
|
||
type="text"
|
||
@click="handleInputUpdate(scope.row, scope.$index)"
|
||
>修改</el-button
|
||
>
|
||
<el-button
|
||
icon="el-icon-delete"
|
||
size="mini"
|
||
type="text"
|
||
@click="handleInputDelete(scope.row, scope.$index)"
|
||
>删除</el-button
|
||
>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<el-button
|
||
icon="el-icon-plus"
|
||
plain
|
||
style="width: 100%;margin-top: 10px"
|
||
type="info"
|
||
@click="addInputParam"
|
||
>新增输入参数</el-button
|
||
>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="是否异步:" prop="async">
|
||
<el-switch v-model="form.async" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||
<el-button @click="$emit('update:visible', false)">取 消</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
<!-- 输入参数弹窗 -->
|
||
<el-dialog
|
||
:close-on-click-modal="false"
|
||
:visible.sync="inputParamOpen"
|
||
append-to-body
|
||
class="params-eldialog"
|
||
title="输入参数"
|
||
width="600px"
|
||
@close="handleInputDialogClose"
|
||
>
|
||
<el-form
|
||
ref="inputForm"
|
||
:model="inputFormObj.form"
|
||
:rules="inputFormRules"
|
||
label-position="top"
|
||
label-width="100px"
|
||
>
|
||
<el-form-item label="标识:" prop="id">
|
||
<el-input v-model="inputFormObj.form.id" placeholder="请输入标识" />
|
||
</el-form-item>
|
||
<el-form-item label="参数名称:" prop="name">
|
||
<el-input
|
||
v-model="inputFormObj.form.name"
|
||
placeholder="请输入参数名称"
|
||
/>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="数据类型:" prop="type">
|
||
<el-select
|
||
v-model="inputFormObj.form.valueType.type"
|
||
placeholder="请选择数据类型"
|
||
style="width: 100%"
|
||
@change="inputDataTypeChange"
|
||
>
|
||
<el-option
|
||
v-for="(dice, value) in dataTypeOption"
|
||
:key="value"
|
||
:label="dice"
|
||
:value="value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item
|
||
v-if="inputFormObj.form.valueType.type === 'enum'"
|
||
label="枚举值:"
|
||
>
|
||
<div class="enum-box">
|
||
<div class="enum-header">
|
||
<el-button size="mini" type="primary" @click="addEnumItem"
|
||
>添加枚举项</el-button
|
||
>
|
||
</div>
|
||
<el-table
|
||
:data="inputFormObj.form.valueType.elements"
|
||
border
|
||
style="width: 100%"
|
||
>
|
||
<el-table-column
|
||
align="center"
|
||
label="序号"
|
||
type="index"
|
||
width="60"
|
||
></el-table-column>
|
||
<el-table-column label="值" prop="value" width="180">
|
||
<template slot-scope="scope">
|
||
<el-input
|
||
v-model="scope.row.value"
|
||
:class="{ 'is-error': scope.row.value }"
|
||
placeholder="请输入值"
|
||
></el-input>
|
||
<div
|
||
v-if="scope.row.value === ''"
|
||
class="el-form-item__error"
|
||
>
|
||
值不能为空
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="描述" prop="text">
|
||
<template slot-scope="scope">
|
||
<el-input
|
||
v-model="scope.row.text"
|
||
:class="{ 'is-error': scope.row.text }"
|
||
placeholder="请输入描述"
|
||
></el-input>
|
||
<div v-if="scope.row.text === ''" class="el-form-item__error">
|
||
描述不能为空
|
||
</div>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column align="center" label="操作" width="80">
|
||
<template slot-scope="scope">
|
||
<el-button
|
||
icon="el-icon-delete"
|
||
style="color: red"
|
||
type="text"
|
||
@click="removeEnumItem(scope.$index)"
|
||
></el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="是否必选:" prop="required">
|
||
<el-switch v-model="inputFormObj.form.expands.required" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button type="primary" @click="submitInputForm">确 定</el-button>
|
||
<el-button @click="inputParamOpen = false">取 消</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
<script>
|
||
import { dataTypeOption } from "@/basedata/physicalModel";
|
||
|
||
const defaultenumForm = {
|
||
value: "",
|
||
text: ""
|
||
};
|
||
|
||
const defaultInputForm = {
|
||
id: "",
|
||
name: "",
|
||
expands: {
|
||
required: false
|
||
},
|
||
valueType: {
|
||
expands: {},
|
||
type: "int",
|
||
elements: []
|
||
}
|
||
};
|
||
|
||
export default {
|
||
name: "FunctionFormModel",
|
||
props: {
|
||
visible: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
title: {
|
||
type: String,
|
||
default: "新增"
|
||
},
|
||
row: {
|
||
type: Object,
|
||
default: () => {}
|
||
},
|
||
tempType: {
|
||
type: String,
|
||
default: "add"
|
||
},
|
||
paramIdx: {
|
||
type: Number,
|
||
default: -1
|
||
},
|
||
functionList: {
|
||
type: Array,
|
||
default: []
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
dataTypeOption,
|
||
inputParamOpen: false,
|
||
form: {
|
||
id: "",
|
||
name: "",
|
||
expands: {},
|
||
async: false,
|
||
inputs: [],
|
||
output: {}
|
||
},
|
||
inputFormObj: {
|
||
isEdit: false,
|
||
index: -1,
|
||
form: JSON.parse(JSON.stringify(defaultInputForm))
|
||
},
|
||
inputFormRules: {
|
||
id: [
|
||
{ required: true, message: "标识不能为空", trigger: "blur" },
|
||
{
|
||
pattern: /^[a-zA-Z0-9_\-]+$/,
|
||
message: "标识只能由数字、字母、下划线、中划线组成",
|
||
trigger: "blur"
|
||
},
|
||
{ validator: this.validateInputId, trigger: "blur" }
|
||
],
|
||
name: [{ required: true, message: "参数名称不能为空", trigger: "blur" }]
|
||
},
|
||
// 表单校验
|
||
rules: {
|
||
name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
|
||
cmdKey: [{ required: true, message: "分组不能为空", trigger: "blur" }],
|
||
id: [
|
||
{ required: true, message: "标识不能为空", trigger: "blur" },
|
||
{
|
||
pattern: /^[a-zA-Z0-9_\-]+$/,
|
||
message: "标识只能由数字、字母、下划线、中划线组成",
|
||
trigger: "blur"
|
||
},
|
||
{ validator: this.validateFunctionId, trigger: "blur" }
|
||
],
|
||
type: [{ required: true, message: "数据类型不能为空", trigger: "blur" }]
|
||
}
|
||
};
|
||
},
|
||
created() {
|
||
if (this.tempType === "update" && this.paramIdx >= 0) {
|
||
this.form = JSON.parse(JSON.stringify(this.row));
|
||
} else {
|
||
// 新增时初始化表单
|
||
this.form = {
|
||
id: "",
|
||
name: "",
|
||
expands: {},
|
||
async: true,
|
||
inputs: [],
|
||
output: {}
|
||
};
|
||
}
|
||
},
|
||
watch: {
|
||
visible(val) {
|
||
if (val) {
|
||
// 当弹窗打开时
|
||
if (this.tempType === "update" && this.paramIdx >= 0) {
|
||
// 编辑模式,复制传入的数据
|
||
this.form = JSON.parse(JSON.stringify(this.row));
|
||
} else {
|
||
// 新增模式,重置表单数据
|
||
this.form = {
|
||
id: "",
|
||
name: "",
|
||
expands: {},
|
||
async: true,
|
||
inputs: [],
|
||
output: {}
|
||
};
|
||
}
|
||
|
||
// 确保输入参数表单也被重置
|
||
this.inputFormObj = {
|
||
isEdit: false,
|
||
index: -1,
|
||
form: JSON.parse(JSON.stringify(defaultInputForm))
|
||
};
|
||
} else {
|
||
// 当弹窗关闭时,重置表单校验状态
|
||
this.$nextTick(() => {
|
||
if (this.$refs.form) {
|
||
this.$refs.form.clearValidate();
|
||
}
|
||
if (this.$refs.inputForm) {
|
||
this.$refs.inputForm.clearValidate();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
},
|
||
methods: {
|
||
// 自定义标识符验证规则
|
||
validateFunctionId(rule, value, callback) {
|
||
if (this.tempType === "update" && value === this.row.id) {
|
||
// 如果是编辑模式且ID没有变化,直接通过验证
|
||
callback();
|
||
return;
|
||
}
|
||
|
||
// 检查功能标识符是否重复
|
||
const isDuplicate =
|
||
this.functionList && this.functionList.some(item => item.id === value);
|
||
if (isDuplicate) {
|
||
callback(new Error("标识符已存在,请更换"));
|
||
} else {
|
||
callback();
|
||
}
|
||
},
|
||
// 自定义输入参数标识符验证规则
|
||
validateInputId(rule, value, callback) {
|
||
if (
|
||
this.inputFormObj.isEdit &&
|
||
value === this.form.inputs[this.inputFormObj.index].id
|
||
) {
|
||
// 如果是编辑模式且ID没有变化,直接通过验证
|
||
callback();
|
||
return;
|
||
}
|
||
|
||
// 检查输入参数标识符是否重复
|
||
const isDuplicate = this.form.inputs.some(item => item.id === value);
|
||
if (isDuplicate) {
|
||
callback(new Error("输入参数标识符已存在,请更换"));
|
||
} else {
|
||
callback();
|
||
}
|
||
},
|
||
inputDataTypeChange(val) {
|
||
// 根据选择的数据类型设置valueType的type属性
|
||
if (val === "int") {
|
||
this.inputFormObj.form.valueType.type = "int";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "long") {
|
||
this.inputFormObj.form.valueType.type = "long";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "float") {
|
||
this.inputFormObj.form.valueType.type = "float";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "double") {
|
||
this.inputFormObj.form.valueType.type = "double";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "string") {
|
||
this.inputFormObj.form.valueType.type = "string";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "boolean") {
|
||
this.inputFormObj.form.valueType.type = "boolean";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "date") {
|
||
this.inputFormObj.form.valueType.type = "date";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "enum") {
|
||
this.inputFormObj.form.valueType.type = "enum";
|
||
if (
|
||
!this.inputFormObj.form.valueType.elements ||
|
||
this.inputFormObj.form.valueType.elements.length === 0
|
||
) {
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
// 默认添加一个空的枚举项
|
||
this.addEnumItem();
|
||
}
|
||
} else if (val === "array") {
|
||
this.inputFormObj.form.valueType.type = "array";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "object") {
|
||
this.inputFormObj.form.valueType.type = "object";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "file") {
|
||
this.inputFormObj.form.valueType.type = "file";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "password") {
|
||
this.inputFormObj.form.valueType.type = "password";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
} else if (val === "geoPoint") {
|
||
this.inputFormObj.form.valueType.type = "geoPoint";
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
}
|
||
},
|
||
|
||
addEnumItem() {
|
||
// 确保elements数组已初始化
|
||
if (!this.inputFormObj.form.valueType.elements) {
|
||
this.inputFormObj.form.valueType.elements = [];
|
||
}
|
||
|
||
// 添加一个新的枚举项
|
||
const newEnumItem = JSON.parse(JSON.stringify(defaultenumForm));
|
||
newEnumItem.value = "";
|
||
newEnumItem.text = "";
|
||
this.inputFormObj.form.valueType.elements.push(newEnumItem);
|
||
},
|
||
removeEnumItem(index) {
|
||
this.$confirm("是否确认删除该枚举参数?", "警告", {
|
||
confirmButtonText: "确定",
|
||
cancelButtonText: "取消",
|
||
type: "warning"
|
||
})
|
||
.then(() => {
|
||
this.inputFormObj.form.valueType.elements.splice(index, 1);
|
||
this.$message({
|
||
type: "success",
|
||
message: "删除成功!"
|
||
});
|
||
})
|
||
.catch(() => {
|
||
this.$message({
|
||
type: "info",
|
||
message: "已取消删除"
|
||
});
|
||
});
|
||
},
|
||
|
||
// 修改提交方法,增加枚举项验证
|
||
submitInputForm() {
|
||
// 验证表单
|
||
this.$refs.inputForm.validate(valid => {
|
||
if (valid) {
|
||
// 如果是枚举类型,确保至少有一个枚举项
|
||
if (
|
||
this.inputFormObj.form.valueType.type === "enum" &&
|
||
(!this.inputFormObj.form.valueType.elements ||
|
||
this.inputFormObj.form.valueType.elements.length === 0)
|
||
) {
|
||
this.$message.warning("枚举类型至少需要一个枚举项");
|
||
return;
|
||
}
|
||
|
||
// 验证枚举项的值和描述不能为空
|
||
if (this.inputFormObj.form.valueType.type === "enum") {
|
||
let hasError = false;
|
||
const enumValues = new Set();
|
||
for (
|
||
let i = 0;
|
||
i < this.inputFormObj.form.valueType.elements.length;
|
||
i++
|
||
) {
|
||
const item = this.inputFormObj.form.valueType.elements[i];
|
||
let value = !item.value;
|
||
let text = !item.text;
|
||
if (value || text) {
|
||
hasError = true;
|
||
break;
|
||
}
|
||
if (enumValues.has(item.value)) {
|
||
this.$message.warning(`枚举值 "${item.value}" 重复,请修改`);
|
||
return;
|
||
}
|
||
enumValues.add(item.value);
|
||
}
|
||
if (hasError) {
|
||
this.$message.warning("请完善枚举项的值和描述");
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 如果是编辑模式
|
||
if (this.inputFormObj.isEdit) {
|
||
// 更新现有输入参数
|
||
this.$set(
|
||
this.form.inputs,
|
||
this.inputFormObj.index,
|
||
this.inputFormObj.form
|
||
);
|
||
} else {
|
||
// 添加新的输入参数
|
||
this.form.inputs.push(
|
||
JSON.parse(JSON.stringify(this.inputFormObj.form))
|
||
);
|
||
}
|
||
|
||
// 关闭弹窗
|
||
this.inputParamOpen = false;
|
||
|
||
// 清除校验状态
|
||
this.$nextTick(() => {
|
||
this.$refs.inputForm.clearValidate();
|
||
});
|
||
|
||
// 提示成功
|
||
this.$message.success(
|
||
this.inputFormObj.isEdit ? "修改成功" : "添加成功"
|
||
);
|
||
}
|
||
});
|
||
},
|
||
addInputParam() {
|
||
this.inputFormObj = {
|
||
isEdit: false,
|
||
index: -1,
|
||
form: JSON.parse(JSON.stringify(defaultInputForm))
|
||
};
|
||
this.inputParamOpen = true;
|
||
},
|
||
/**
|
||
* 上移功能
|
||
* @param {Number} index 当前功能索引
|
||
*/
|
||
handleInputUp(index) {
|
||
if (index === 0) return; // 已经是第一个,不能再上移
|
||
|
||
try {
|
||
// 交换当前项与上一项的位置
|
||
const temp = this.form.inputs[index];
|
||
this.$set(this.form.inputs, index, this.form.inputs[index - 1]);
|
||
this.$set(this.form.inputs, index - 1, temp);
|
||
this.$message({
|
||
type: 'success',
|
||
message: '上移成功!'
|
||
});
|
||
} catch (error) {
|
||
this.$message.error("操作失败:" + error);
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 下移功能
|
||
* @param {Number} index 当前功能索引
|
||
*/
|
||
handleInputDown(index) {
|
||
if (index === this.form.inputs.length - 1) return; // 已经是最后一个,不能再下移
|
||
|
||
try {
|
||
// 交换当前项与下一项的位置
|
||
const temp = this.form.inputs[index];
|
||
this.$set(this.form.inputs, index, this.form.inputs[index + 1]);
|
||
this.$set(this.form.inputs, index + 1, temp);
|
||
this.$message({
|
||
type: 'success',
|
||
message: '下移成功!'
|
||
});
|
||
} catch (error) {
|
||
this.$message.error("操作失败:" + error);
|
||
}
|
||
},
|
||
/**
|
||
* 修改输入参数
|
||
* @param {Object} row 行数据
|
||
* @param {Number} index 行索引
|
||
*/
|
||
handleInputUpdate(row, index) {
|
||
this.inputFormObj = {
|
||
isEdit: true,
|
||
index: index,
|
||
form: JSON.parse(JSON.stringify(row))
|
||
};
|
||
this.inputParamOpen = true;
|
||
},
|
||
|
||
/**
|
||
* 删除输入参数
|
||
* @param {Object} row 行数据
|
||
* @param {Number} index 行索引
|
||
*/
|
||
handleInputDelete(row, index) {
|
||
this.$confirm("是否确认删除该输入参数?", "警告", {
|
||
confirmButtonText: "确定",
|
||
cancelButtonText: "取消",
|
||
type: "warning"
|
||
})
|
||
.then(() => {
|
||
this.form.inputs.splice(index, 1);
|
||
this.$message({
|
||
type: "success",
|
||
message: "删除成功!"
|
||
});
|
||
})
|
||
.catch(() => {
|
||
this.$message({
|
||
type: "info",
|
||
message: "已取消删除"
|
||
});
|
||
});
|
||
},
|
||
inputChange() {
|
||
this.$forceUpdate();
|
||
},
|
||
/** 提交验证 */
|
||
submitForm: function() {
|
||
this.$refs["form"].validate(valid => {
|
||
if (valid) {
|
||
// 额外校验输入参数
|
||
if (!this.form.inputs || this.form.inputs.length === 0) {
|
||
this.$message.warning("请至少添加一个输入参数");
|
||
return;
|
||
}
|
||
// 新增和修改操作
|
||
if (this.tempType === "add") {
|
||
this.$store
|
||
.dispatch("AddFunction", this.form)
|
||
.then(() => {
|
||
this.$message.success("添加成功");
|
||
this.$emit("ok");
|
||
})
|
||
.catch(err => {
|
||
this.$message.error("添加失败:" + err);
|
||
});
|
||
} else if (this.tempType === "update") {
|
||
this.$store
|
||
.dispatch("EditFunction", {
|
||
item: this.form,
|
||
idx: this.paramIdx
|
||
})
|
||
.then(() => {
|
||
this.$message.success("修改成功");
|
||
this.$emit("ok");
|
||
})
|
||
.catch(err => {
|
||
this.$message.error("修改失败:" + err);
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
// 添加一个监听输入参数弹窗关闭的方法
|
||
handleInputDialogClose() {
|
||
this.$nextTick(() => {
|
||
if (this.$refs.inputForm) {
|
||
this.$refs.inputForm.clearValidate();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
<style lang="scss">
|
||
.function-form-model {
|
||
.enum-box {
|
||
border: 1px solid #d8d7d7;
|
||
padding: 10px;
|
||
margin-bottom: 10px;
|
||
.enumTypeDiv {
|
||
margin-top: 10px;
|
||
}
|
||
.enum-header {
|
||
margin-bottom: 10px;
|
||
}
|
||
}
|
||
.el-select {
|
||
width: 100%;
|
||
}
|
||
.el-input-number {
|
||
width: 100%;
|
||
}
|
||
.enumTypeDiv {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
max-height: 200px;
|
||
overflow: auto;
|
||
.enum-item {
|
||
width: 90%;
|
||
display: flex;
|
||
justify-content: space-around;
|
||
align-items: center;
|
||
}
|
||
}
|
||
}
|
||
|
||
.is-error input {
|
||
border-color: #f56c6c;
|
||
}
|
||
|
||
.el-form-item__error {
|
||
color: #f56c6c;
|
||
font-size: 12px;
|
||
line-height: 1;
|
||
padding-top: 4px;
|
||
position: absolute;
|
||
top: 100%;
|
||
left: 0;
|
||
}
|
||
</style>
|