From 2a476685122d3e177f50a7941aa8f099c34bf6e7 Mon Sep 17 00:00:00 2001 From: tx <2622874537@qq.com> Date: Wed, 28 Aug 2024 16:22:54 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=90=E8=90=A5=E5=8C=BA=E5=9C=B0=E5=9B=BE?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/system/area/areaRange.vue | 947 +++++++++++++++++++++++++++- 1 file changed, 939 insertions(+), 8 deletions(-) diff --git a/src/views/system/area/areaRange.vue b/src/views/system/area/areaRange.vue index 5de3229..d8a75ad 100644 --- a/src/views/system/area/areaRange.vue +++ b/src/views/system/area/areaRange.vue @@ -1,17 +1,948 @@ <template> - <div class="page"> - 11111111 + <div class="container"> + <div id="container"></div> + <div class="input-card-left"> + <div style="color: red">tips:双击区域可重新编辑</div> + <div style="color: red"> + 点击新建--左键开始建立停车区--右键完成建立--点击结束编辑才会最终生效 + </div> + </div> + <div class="input-card"> + <el-button @click="setFitView()">全局查看</el-button> + <el-button @click="changeMapStyle()">切换地图</el-button> + <el-button @click="showMarkers">显示/隐藏文字</el-button> + </div> + <div class="input-card-right"> + <el-button @click="createPolygon()">新建</el-button> + <!-- <el-button @click="polyEditor.open()">开始编辑</el-button> --> + <el-button @click="editClose">结束编辑</el-button> + <el-button @click="changeMapStyle()">切换地图</el-button> + <el-button @click="clearPolygon()">清除多边形</el-button> + </div> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + style="margin-top: 20px" + > + <el-form-item label="停车区" label-width="100" prop="parkingName"> + <el-input + v-model="queryParams.parkingName" + placeholder="请输入停车区" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="类型" prop="type"> + <el-select v-model="queryParams.type" clearable> + <el-option + v-for="dict in dict.type.et_parking_type" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button + type="primary" + icon="el-icon-search" + size="mini" + @click="handleQuery" + >搜索</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery" + >重置</el-button + > + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:parking:add']" + >新增</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleUpdate" + v-hasPermi="['system:parking:edit']" + >修改</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['system:parking:remove']" + >删除</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['system:parking:export']" + >导出</el-button + > + </el-col> + <right-toolbar + :showSearch.sync="showSearch" + @queryTable="getList" + ></right-toolbar> + </el-row> + + <el-table + v-if="showtable" + v-loading="loading" + :data="parkingList" + @selection-change="handleSelectionChange" + + :cell-style="columnbackgroundStyle" + > + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="id" align="center" prop="parkingId" /> + <el-table-column label="名称" align="center" prop="parkingName" /> + <el-table-column + label="误差距离" + align="center" + prop="error" + :formatter="formatDistance" + /> + <el-table-column label="类型" align="center" prop="type"> + <template slot-scope="scope"> + <dict-tag + :options="dict.type.et_parking_type" + :value="scope.row.type" + /> + </template> + </el-table-column> + <el-table-column label="照片" align="center" prop="picture" width="100"> + <template slot-scope="scope"> + <image-preview :src="scope.row.picture" :width="50" :height="50" /> + </template> + </el-table-column> + <el-table-column label="状态" align="center" key="status"> + <template slot-scope="scope"> + <el-switch + v-model="scope.row.status" + active-value="0" + inactive-value="1" + @change="handleStatusChange(scope.row)" + ></el-switch> + </template> + </el-table-column> + <!-- <el-table-column label="区域" align="center" prop="areaId" />--> + <el-table-column + label="创建时间" + align="center" + prop="createTime" + width="180" + > + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime, "{y}-{m}-{d}") }}</span> + </template> + </el-table-column> + <el-table-column label="id" align="center" prop="parkingId"> + <template slot-scope="scope"> + <div :ref="'row_' + scope.row.parkingId">{{ scope.row.parkingId }}</div> + </template> +</el-table-column> + <el-table-column + label="操作" + align="center" + class-name="small-padding fixed-width" + > + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:parking:edit']" + >修改</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:parking:remove']" + >删除</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> </div> </template> <script> -export default { - +import AMapLoader from "@amap/amap-jsapi-loader"; +import globalConfig from "@/utils/config/globalConfig"; +var polyEditor = ""; +function calculateCenter(mapList) { + var total = mapList.length; + var X = 0, + Y = 0, + Z = 0; + mapList.map((item) => { + var lng = (item[0] * Math.PI) / 180; + var lat = (item[1] * Math.PI) / 180; + var x, y, z; + x = Math.cos(lat) * Math.cos(lng); + y = Math.cos(lat) * Math.sin(lng); + z = Math.sin(lat); + X += x; + Y += y; + Z += z; + }); + X = X / total; + Y = Y / total; + Z = Z / total; + var Lng = Math.atan2(Y, X); + var Hyp = Math.sqrt(X * X + Y * Y); + var Lat = Math.atan2(Z, Hyp); + let center = new AMap.LngLat((Lng * 180) / Math.PI, (Lat * 180) / Math.PI); + return center; } + +import { + listParking, + getParking, + delParking, + addParking, + updateParking, + changeParkingStatus, +} from "@/api/system/parking"; +import { + getArea, + optionselect as getAreaOptionselect, +} from "@/api/system/area"; +export default { + name: "AreaMap", + dicts: ["et_parking_type"], + data() { + return { + map: null, + // polyEditor: null, + coordList: "", + timer: "", + status: true, + lon2: null, + lat2: null, + lon: "", + lat: "", + pathList: null, + areaId: null, + parkingList: [], + noParkingList: [], + noridingList: [], + show: false, + labels: [], + markers: [], + areaList: [], + // 遮罩层 + loading: true, + // 选中数组 + ids: [], + // 非单个禁用 + single: true, + // 非多个禁用 + multiple: true, + // 显示搜索条件 + showSearch: true, + // 总条数 + total: 0, + // 停车区表格数据 + parkingList: [], + // 默认区域id + defaultAreaId: "", + // 弹出层标题 + title: "", + // 是否显示弹出层 + open: false, + // 通过key重新渲染area-map组件 + key: 0, + areaLon: null, + areaLat: null, + // 分区列表 + areaOptions: [], + // 类型列表 + typeOptions: [], + // 查询参数 + queryParams: { + pageNum: 1, + pageSize: 20, + parkingName: null, + areaId: null, + type: null, + }, + // 表单参数 + form: {}, + highlightedId: null, // 默认不高亮 + showtable: true, + // 表单校验 + rules: { + parkingName: [ + { required: true, message: "禁停区不能为空", trigger: "blur" }, + ], + type: [{ required: true, message: "类型不能为空", trigger: "blur" }], + boundaryStr: [ + { required: true, message: "边界不能为空", trigger: "blur" }, + ], + error: [ + { + pattern: /^[0-9]*$/, + message: "还车误差必须为正整数", + trigger: "blur", + }, + ], + }, + }; + }, + // props: ["pathList", "areaId","lon","lat","zoom"], + mounted() { + // if (this.areaId) { + // this.start(); + // console.log("修改"); + // } else { + // this.echart(); + // console.log("添加"); + // } + }, + created() { + const areaId = this.$route.params && this.$route.params.areaId; + this.getArea(areaId); + this.getAreaList(); + }, + methods: { + getArea(areaId) { + getArea(areaId).then((response) => { + + this.queryParams.areaId = response.data.areaId; + this.areaId = response.data.areaId; + this.lon = response.data.longitude; + this.lat = response.data.latitude; + this.areaList = response.data.boundaryStr; + this.defaultAreaId = response.data.areaId; + this.getList(); + listParking({ areaId: this.areaId }).then((response) => { + let list = response.rows; + list.forEach((item) => { + if (item.type === "1") { + this.parkingList.push(item); + } else if (item.type === "2") { + this.noParkingList.push(item); + } else if (item.type === "3") { + this.noridingList.push(item); + } + }); + this.initAMap(); + // setTimeout(() => { + // this.showmap = true; + // this.initAMap(); + // }, 300); + }); + + // this.getList(); + }); + }, + + // 取消按钮 + cancel() { + this.open = false; + this.reset(); + }, + // 表单重置 + reset() { + this.form = { + parkingId: null, + parkingName: null, + areaId: null, + boundaryStr: null, + longitude: null, + latitude: null, + createBy: null, + createTime: null, + type: "1", + }; + this.resetForm("form"); + }, + /** 搜索按钮操作 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 重置按钮操作 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 多选框选中数据 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.parkingId); + this.single = selection.length !== 1; + this.multiple = !selection.length; + }, + /** 查询字典类型列表 */ + getAreaList() { + getAreaOptionselect().then((response) => { + this.areaOptions = response.data; + }); + }, + formatDistance(row) { + if (typeof row.error === "number") { + return `${row.error} 米`; + } else { + return "-"; + } + }, + /** 查询停车区列表 */ + getList() { + this.loading = true; + listParking(this.queryParams).then((response) => { + this.parkingList = response.rows; + this.total = response.total; + this.defaultAreaId = this.queryParams.areaId; + getArea(this.defaultAreaId).then((response) => { + this.queryParams.areaId = response.data.areaId; + this.areaLon = response.data.longitude; + this.areaLat = response.data.latitude; + }); + this.loading = false; + }); + }, + setFitView() { + this.map.setFitView(null, false, [150, 60, 100, 60]); + }, + /** 新增按钮操作 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "添加停车区"; + this.key++; + }, + /** 修改按钮操作 */ + handleUpdate(row) { + this.reset(); + const parkingId = row.parkingId || this.ids; + getParking(parkingId).then((response) => { + this.form = response.data; + this.areaLon = response.data.longitude; + this.areaLat = response.data.latitude; + this.open = true; + this.title = "修改停车区"; + this.key++; + }); + }, + /** 删除按钮操作 */ + handleDelete(row) { + const parkingIds = row.parkingId || this.ids; + this.$modal + .confirm('是否确认删除停车区编号为"' + parkingIds + '"的数据项?') + .then(function () { + return delParking(parkingIds); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("删除成功"); + }) + .catch(() => {}); + }, + /** 导出按钮操作 */ + handleExport() { + this.download( + "system/parking/export", + { + ...this.queryParams, + }, + `parking_${new Date().getTime()}.xlsx` + ); + }, + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.parkingId); + this.single = selection.length !== 1; + this.multiple = !selection.length; + }, + showMarkers() { + if (this.show) { + this.labels.forEach((label) => { + label.show(); + }); + } else { + this.labels.forEach((label) => { + label.hide(); + }); + } + this.show = !this.show; + const elements = document.querySelectorAll(".apiary-marker-name"); + elements.forEach((element) => { + element.style.visibility = this.show ? "hidden" : "visible"; + }); + }, + clearPolygon() { + this.status = false; + if (polyEditor) { + polyEditor.close(); // 关闭多边形编辑器 + } + + // 移除地图上的所有多边形对象 + this.map.getAllOverlays("polygon").forEach((polygon) => { + this.map.remove(polygon); + }); + + // 如果需要,也可以清空与多边形相关的其他状态或数据 + this.coordList = ""; + this.$emit("mapList", ""); + + this.$emit("center", ""); + }, + changeMapStyle() { + // 创建一个默认的图层组件 + let defaultLayer = new AMap.TileLayer(); + // 创建一个卫星图图层组件 + let satelliteLayer = new AMap.TileLayer.Satellite(); + let roadNetLayer = new AMap.TileLayer.RoadNet(); + // 将默认图层添加到地图中 + this.map.add(defaultLayer); + // 获取当前地图显示的图层 + let currentLayer = this.map.getLayers()[0]; // 假设默认图层在第一个位置 + // 切换图层 + if (this.type == "default") { + // console.log(1111111) + //获取地图图层数据 + this.map.setLayers([defaultLayer]); // 切换回默认图层 + this.type = "Satellite"; + } else { + console.log(222222); + this.map.setLayers([satelliteLayer, roadNetLayer]); // 切换到卫星图图层 + this.type = "default"; + } + }, + start() { + this.timer = setInterval(this.echart, 1000); // 注意: 第一个参数为方法名的时候不要加括号; + }, + async echart() { + clearInterval(this.timer); + console.log("接收参数", this.pathList); + console.log("接收参数", this.lon); + console.log("接收参数", this.lat); + this.lon2 = this.lon === null ? 120.35218 : this.lon; + this.lat2 = this.lat === null ? 26.944335 : this.lat; + // console.log(typeof JSON.parse(this.pathList)); + await AMapLoader.load({ + key: globalConfig.aMap.key, // 申请好的Web端开发者Key,首次调用 load 时必填 + version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 + plugins: [ + "AMap.ToolBar", + "AMap.Driving", + "AMap.PolygonEditor", + "AMap.PlaceSearch", + ], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 + }) + .then((AMap) => { + this.map = new AMap.Map("container", { + //设置地图容器id + viewMode: "3D", //是否为3D地图模式 + zoom: this.zoom ? this.zoom : 13, //初始化地图级别 + center: [this.lon2, this.lat2], // 初始化地图中心点位置 + }); + + this.parkingList.forEach((parking) => { + this.addParking( + JSON.parse(parking.boundaryStr) || [], + parking.parkingName, + parking.longitude, + parking.latitude + ); + this.addMarker2( + parking, + "https://lxnapi.ccttiot.com/FqcYf6ecsnbC0OT6YYAF5npgu-kh", + parking.parkingName, + "#1890ff" + ); + }); + + this.noParkingList.forEach((noparking) => { + this.addNoParking(JSON.parse(noparking.boundaryStr) || []); + this.addMarker2( + noparking, + "https://lxnapi.ccttiot.com/FjKE5PWbnEnZUq3k-wVIvV4lv8Ab", + noparking.parkingName, + "#ff4444" + ); + }); + + this.noridingList.forEach((noriding) => { + this.addNoriding( + JSON.parse(noriding.boundaryStr) || [], + noriding.parkingName, + noriding.longitude, + noriding.latitude + ); + this.addMarker2( + noriding, + "https://lxnapi.ccttiot.com/FmX1diEPPbFYe1vcUfKp6qbKzzh2", + noriding.parkingName, + "#ffcc00" + ); + }); + }) + .catch((e) => { + console.log(e); + }); + this.initEditor(); + }, + initAMap() { + AMapLoader.load({ + key: globalConfig.aMap.key, + version: "2.0", + plugins: [ + "AMap.ToolBar", + "AMap.Driving", + "AMap.PolygonEditor", + "AMap.PlaceSearch", + ], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 + }) + .then((AMap) => { + this.map = new AMap.Map("container", { + viewMode: "3D", + zoom: 13, + center: [this.lon, this.lat], + }); + + this.infoWindow = new AMap.InfoWindow({ + offset: new AMap.Pixel(0, -30), + }); + + // this.deviceMarker(this.areaId); + + // this.areaList.forEach(area => { + + // }); + this.addArea(JSON.parse(this.areaList) || []); + this.parkingList.forEach((parking) => { + this.addParking( + JSON.parse(parking.boundaryStr) || [], + parking.parkingName, + parking.longitude, + parking.latitude, + parking.parkingId + ); + this.addMarker2( + parking, + "https://lxnapi.ccttiot.com/FqcYf6ecsnbC0OT6YYAF5npgu-kh", + parking.parkingName, + "#1890ff" + ); + }); + + this.noParkingList.forEach((noparking) => { + this.addNoParking(JSON.parse(noparking.boundaryStr) || [], noparking.parkingId); + this.addMarker2( + noparking, + "https://lxnapi.ccttiot.com/FjKE5PWbnEnZUq3k-wVIvV4lv8Ab", + noparking.parkingName, + "#ff4444" + ); + }); + + this.noridingList.forEach((noriding) => { + this.addNoriding( + JSON.parse(noriding.boundaryStr) || [], + noriding.parkingName, + noriding.longitude, + noriding.latitude, + noriding.parkingId + ); + this.addMarker2( + noriding, + "https://lxnapi.ccttiot.com/FmX1diEPPbFYe1vcUfKp6qbKzzh2", + noriding.parkingName, + "#ffcc00" + ); + }); + }) + .catch((e) => { + console.log(e); + }); + }, + addArea(data) { + let polygon = new AMap.Polygon({ + path: data, + fillColor: "#ccebc5", + strokeOpacity: 1, + fillOpacity: 0.5, + strokeColor: "#2b8cbe", + strokeWeight: 1, + strokeStyle: "dashed", + strokeDasharray: [5, 5], + }); + this.map.add(polygon); + }, + addParking(data, title, lon, lat, parkingId) { + let polygon = new AMap.Polygon({ + path: data, + fillColor: "#ccebc5", + strokeOpacity: 1, + fillOpacity: 0.5, + strokeColor: "#3b7ed9", + strokeWeight: 2, + strokeStyle: "solid", + strokeDasharray: [5, 5], + }); + polygon.on("mouseover", () => { + polygon.setOptions({ + fillOpacity: 0.7, + fillColor: "#71b7cc", + }); + }); + polygon.on("mouseout", () => { + polygon.setOptions({ + fillOpacity: 0.5, + fillColor: "#a7c1d0", + }); + }); + polygon.on("click", () => { + // 高亮显示对应的列表项 + this.highlightRow(parkingId); + }); + this.map.add(polygon); + }, + highlightRow(parkingId) { + this.$set(this, "highlightedId", parkingId); + this.showtable = false; + + this.$nextTick(() => { + this.showtable = true; + + // 确保高亮行的 DOM 已经渲染完成 + this.$nextTick(() => { + const rowElement = this.$refs['row_' + parkingId]; + if (rowElement && rowElement[0]) { + rowElement[0].scrollIntoView({ behavior: "smooth", block: "center" }); + } + }); + }); + }, + + columnbackgroundStyle({ row }) { + if (row.parkingId == this.highlightedId) { + //让下标为1的列数背景颜色显示为红色(颜色自定义根据大家需求来) + return "background:#f0f9eb;"; + } + }, + + addNoParking(data,parkingId) { + let polygon = new AMap.Polygon({ + path: data, + fillColor: "#ccebc5", + strokeOpacity: 1, + fillOpacity: 0.5, + strokeColor: "#ff0000", + strokeWeight: 2, + strokeStyle: "solid", + strokeDasharray: [5, 5], + }); + polygon.on("mouseover", () => { + polygon.setOptions({ + fillOpacity: 0.7, + fillColor: "#ff0000", + }); + }); + polygon.on("mouseout", () => { + polygon.setOptions({ + fillOpacity: 0.5, + fillColor: "#cc7b7b", + }); + }); + polygon.on("click", () => { + // 高亮显示对应的列表项 + this.highlightRow(parkingId); + }); + this.map.add(polygon); + }, + addMarker2(parking, icon, title, color) { + let marker = new AMap.Marker({ + map: this.map, + icon: new AMap.Icon({ + image: icon, + size: new AMap.Size(25, 36), + imageSize: new AMap.Size(25, 36), + }), + position: [parking.longitude, parking.latitude], + offset: new AMap.Pixel(-12.5, -36), + }); + + this.markers.push(marker); + + let text = new AMap.Text({ + text: title, + anchor: "center", + position: [parking.longitude, parking.latitude], + offset: new AMap.Pixel(0, -50), + style: { + "background-color": color, + border: "none", + "border-radius": "5px", + color: "white", + "font-size": "12px", + }, + }); + + this.map.add(text); + this.labels.push(text); + }, + addNoriding(data, title, lon, lat,parkingId) { + let polygon = new AMap.Polygon({ + path: data, + fillColor: "#ccebc5", + strokeOpacity: 1, + fillOpacity: 0.5, + strokeColor: "#ffcc00", + strokeWeight: 2, + strokeStyle: "solid", + strokeDasharray: [5, 5], + }); + polygon.on("mouseover", () => { + polygon.setOptions({ + fillOpacity: 0.7, + fillColor: "#FFEBA4FF", + }); + }); + polygon.on("mouseout", () => { + polygon.setOptions({ + fillOpacity: 0.5, + fillColor: "#ffeba4", + }); + }); + polygon.on("click", () => { + // 高亮显示对应的列表项 + this.highlightRow(parkingId); + }); + this.map.add(polygon); + }, + initEditor() { + var path1 = []; + if (this.areaId) { + path1 = JSON.parse(this.pathList) || []; + } + + var polygon1 = new AMap.Polygon({ + path: path1, + }); + this.map.add([polygon1]); + polyEditor = new AMap.PolygonEditor(this.map); + // console.log(polyEditor); + // console.dir(polyEditor); + polyEditor.on("add", (data) => { + // console.log(data); + this.coordList = data.lnglat; + var polygon = data.target; + polygon.on("dblclick", () => { + polyEditor.setTarget(polygon); + polyEditor.open(); + }); + }); + polygon1.on("dblclick", () => { + polyEditor.setTarget(polygon1); + polyEditor.open(); + }); + + return polyEditor; + }, + createPolygon() { + this.status = true; + polyEditor.close(); + polyEditor.setTarget(); + polyEditor.open(); + }, + editClose: function () { + // console.log("this", this); + + let that = this; + polyEditor.on("end", function (event) { + // event.target 即为编辑后的多边形对象 + //多边形的坐标 + this.coordList = event.target.getPath(); + // console.log("coordList", this.coordList); + let mapList = []; + this.coordList.forEach((v) => { + // console.log("v", v.lng, "--", v.lat); + mapList.push([v.lng, v.lat]); + }); + let center = calculateCenter(mapList); + console.log(mapList, "mapListmapList"); + that.$emit("mapList", mapList); + + that.$emit("center", center); + }); + polyEditor.close(); + }, + }, + beforeDestroy() { + clearInterval(this.timer); + }, +}; </script> -<style lang='scss'> -.page{ - margin-top: 200rpx; +<style lang="scss" scoped> +#container { + width: 100%; + height: 30rem; } -</style> \ No newline at end of file +.input-card { + position: absolute; + top: 15px; + right: 15px; +} +.highlight-row { + background-color: #f0f9eb; /* 浅绿色背景 */ +} +.container { + position: relative; + border: 1px solid rgb(204, 204, 204); + padding-bottom: 50px; + .input-card-right { + position: absolute; + bottom: 15px; + right: 15px; + } + .input-card-left { + position: absolute; + top: 5px; + left: 20px; + font-size: 13px; + line-height: 20px; + } +} +</style>