ACE模板知识积累-CSS部分-1-.space

本文介绍了ACE框架中的一系列CSS样式,如.space和.vspace,用于在垂直方向上创建不同大小的间隔。这些样式通过设置max-height、min-height、overflow和margin实现,提供了从2px到32px的间距选择。然而,存在一个疑问:为何每个样式先设定margin:12px 0,再用另一个margin覆盖?同时,每个.space样式都有对应的.vspace,其作用是什么?

ace中有一类样式用来做垂直div之间的间隙

之前我在bootstrap框架中都会添加一个.mt10(margin-top:10px)

但ace显然比我的做法要高级得多,它定义了一套间隙样式:(取自ace.min.css美化后第686到922行)

.space {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0
}
.vspace-xs,.vspace-sm,.vspace-md,.vspace-lg {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    display:none;
    margin:12px 0
}
.space-32 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:32px 0 31px
}
.vspace-32,.vspace-xs-32,.vspace-sm-32,.vspace-md-32,.vspace-lg-32 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:32px 0 31px 0
}
.space-30 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:30px 0 29px
}
.vspace-30,.vspace-xs-30,.vspace-sm-30,.vspace-md-30,.vspace-lg-30 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:30px 0 29px 0
}
.space-28 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:28px 0 27px
}
.vspace-28,.vspace-xs-28,.vspace-sm-28,.vspace-md-28,.vspace-lg-28 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:28px 0 27px 0
}
.space-26 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:26px 0 25px
}
.vspace-26,.vspace-xs-26,.vspace-sm-26,.vspace-md-26,.vspace-lg-26 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:26px 0 25px 0
}
.space-24 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:24px 0 23px
}
.vspace-24,.vspace-xs-24,.vspace-sm-24,.vspace-md-24,.vspace-lg-24 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:24px 0 23px 0
}
.space-22 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:22px 0 21px
}
.vspace-22,.vspace-xs-22,.vspace-sm-22,.vspace-md-22,.vspace-lg-22 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:22px 0 21px 0
}
.space-20 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:20px 0 19px
}
.vspace-20,.vspace-xs-20,.vspace-sm-20,.vspace-md-20,.vspace-lg-20 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:20px 0 19px 0
}
.space-18 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:18px 0 17px
}
.vspace-18,.vspace-xs-18,.vspace-sm-18,.vspace-md-18,.vspace-lg-18 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:18px 0 17px 0
}
.space-16 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:16px 0 15px
}
.vspace-16,.vspace-xs-16,.vspace-sm-16,.vspace-md-16,.vspace-lg-16 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:16px 0 15px 0
}
.space-14 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:14px 0 13px
}
.vspace-14,.vspace-xs-14,.vspace-sm-14,.vspace-md-14,.vspace-lg-14 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:14px 0 13px 0
}
.space-12 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:12px 0 11px
}
.vspace-12,.vspace-xs-12,.vspace-sm-12,.vspace-md-12,.vspace-lg-12 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:12px 0 11px 0
}
.space-10 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:10px 0 9px
}
.vspace-10,.vspace-xs-10,.vspace-sm-10,.vspace-md-10,.vspace-lg-10 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:10px 0 9px 0
}
.space-8 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:8px 0 7px
}
.vspace-8,.vspace-xs-8,.vspace-sm-8,.vspace-md-8,.vspace-lg-8 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:8px 0 7px 0
}
.space-6 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:6px 0 5px
}
.vspace-6,.vspace-xs-6,.vspace-sm-6,.vspace-md-6,.vspace-lg-6 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:6px 0 5px 0
}
.space-4 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:4px 0 3px
}
.vspace-4,.vspace-xs-4,.vspace-sm-4,.vspace-md-4,.vspace-lg-4 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:4px 0 3px 0
}
.space-2 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:2px 0 1px
}
.vspace-2,.vspace-xs-2,.vspace-sm-2,.vspace-md-2,.vspace-lg-2 {
    max-height:1px;
    min-height:1px;
    overflow:hidden;
    margin:12px 0;
    margin:2px 0 1px 0
}

从2到32都有,可以说绝对满足人们的需要。

但不明白的是为什么都要先写个margin:12px 0,然后用另一个margin去覆盖?这样写的用意是什么?望有路过的大神给提点一下。

还有就是每个.space都有一套.vspace伴随,这又是为何?

分析代码; <!DOCTYPE html> <html lang="zh-cn"> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <title>京东TMS系统</title> <meta content="width=device-width, initial-scale=1.0" name="viewport" /> <link type="image/x-icon" href="/static/images/favicon.ico" rel="shortcut icon"> <!-- basic styles begin --> <link href="/static/assets/css/bootstrap.min.css" rel="stylesheet" type="text/css"/> <!-- basic styles end--> <!-- basic script begin --> <script src="/static/js/plugins/jquery-3.3.0.js" type="text/javascript"></script> <script src="/static/assets/js/bootstrap.min.js" type="text/javascript"></script> <script src="/static/assets/js/bootstrap-table.js" type="text/javascript"></script> <link href="/static/assets/css/bootstrap-table.css" rel="stylesheet" type="text/css"/> <!-- basic script end --> </head> <body lang="zh-CN"> <link href="/static/assets/css/font-awesome.min.css" rel="stylesheet" type="text/css"/> <!--[if IE 7]> <link href="/static/assets/css/font-awesome-ie7.min.css" rel="stylesheet"/> <![endif]--> <link href="/static/assets/css/ace.min.css" rel="stylesheet" type="text/css"/> <!--[if lte IE 8]> <link href="/static/assets/css/ace-ie.min.css" rel="stylesheet"/> <![endif]--> <link href="/static/assets/css/ace-rtl.min.css" rel="stylesheet" type="text/css"/> <link href="/static/assets/css/ace-skins.min.css" rel="stylesheet" type="text/css"/> <link href="/static/assets/css/bootstrap-datetimepicker.min.css" rel="stylesheet" media="screen"> <link href="/static/js/plugins/sweetalert/sweet-alert.css" rel="stylesheet" media="screen"> <link href="/static/js/plugins/dateRange/daterangepicker.css" rel="stylesheet" type="text/css" /> <link href="/static/css/boss.css" rel="stylesheet" type="text/css"/> <link href="/static/css/bootstrap-table-fixed-columns.min.css" type="text/css" rel="stylesheet" /> <style type="text/css"> .page-content {padding-left:24px;padding-right:24px;} .fixed-table-border { height: 0px !important; } .no-records-found{ display: none; } </style> <input type="hidden" id="contextPath" value=""/> <input type="hidden" id="userDefaultSiteCode" value=""/> <link href="/static/css/bootstrap-select.css" type="text/css" rel="stylesheet" /> <style> @media (max-width: 10000px) { .table-responsive { width: 100%; margin-bottom: 15px; overflow-x: scroll; overflow-y: hidden; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; border: 1px solid #ddd; } .table-responsive > .table > thead > tr > th, .table-responsive > .table > tbody > tr > td { white-space: nowrap; } tr{ white-space: nowrap; } th{ white-space: nowrap; } } #queryForm label{font-size:11px;} </style> <div class="main-content"> <div id="breadcrumbs" class="breadcrumbs"> <ul class="breadcrumb"> <li> <i class="icon-home home-icon"></i> <a href="#">首页</a> </li> <li> <a href="#">运输管理</a> </li> <li class="active">揽收运输单管理</li> </ul> </div> <div class="page-content"> <div class="search-area well" style="padding-left: 20px"> <form id="queryForm" class="form-horizontal" method="post"> <input type="hidden" name="excludeFlag" id="excludeFlag" /> <input type="hidden" name="strict" id="strict" /> <div class="row"> <div class="control-group search-group"> <label class="control-label search-lable100" for="scheduleCenterName">调度中心:</label> <input type="text" id="scheduleCenterName" class="search-input200" /> <input type="hidden" id="scheduleCenterCode" name="scheduleCenterCode" value="020D324" /> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="transbillCode">运单号:</label> <input type="text" id="transbillCode" name="transbillCode" class="search-input200" /> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="shipperCode">发货商家:</label> <select class="selectpicker search-input150" name="shipperCode" id="shipperCode" multiple data-actions-box="true" data-live-search="true" title="请选择发货商家" data-live-search-placeholder="请输入发货商家" data-none-results-text="暂无发货商家 {0}" data-select-all-text="全选" data-deselect-all-text="全不选"></select> <label for="excludeCheck" class="exclude-check-label">排除:</label> <input type="checkbox" class="exclude-check-box" id="excludeCheck" /> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="shipperCode">温层:</label> <select id="temperatureLayer" name="temperatureLayer" class="search-input200"> </select> </div> </div> <div class="row"> <div class="control-group search-group"> <label class="control-label search-lable100" for="beginProvinceId">揽收省份:</label> <select id="beginProvinceId" name="beginProvinceId" class="search-input200"> </select> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="beginCityId">揽收城市:</label> <select id="beginCityId" name="beginCityId" class="search-input200"> </select> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="beginCountyId">揽收县区:</label> <select id="beginCountyId" name="beginCountyId" class="search-input200"> </select> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="beginTownId">揽收乡区:</label> <select id="beginTownId" name="beginTownId" class="search-input200"> </select> </div> </div> <div class="row"> <div class="control-group search-group"> <label class="control-label search-lable100" for="industryType">行业类型:</label> <select id="industryType" name="industryType" class="search-input200"> </select> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="receiveJobCode">揽收任务单号:</label> <input type="text" id="receiveJobCode" name="receiveJobCode" class="search-input200" /> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="scheduleStatus">调度状态:</label> <select id="scheduleStatus" name="scheduleStatus" class="search-input200"> <option value="" selected="selected"></option> <option value="10">初始</option> <option value="20">待调度</option> <option value="30">已调度</option> <option value="100">已完成</option> <option value="200">取消</option> </select> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="selfFlag">揽收方式:</label> <select id="selfFlag" name="selfFlag" class="search-input200"> <option value="">全部</option> <option value="1">上门揽收</option> <option value="2">自送揽收</option> </select> </div> </div> <div class="row"> <div class="control-group search-group"> <label class="control-label search-lable100" for="operateTerminal">操作终端:</label> <select id="operateTerminal" name="operateTerminal" class="search-input200"> <option value="">全部</option> <option value="1">一体机</option> <option value="2">APP</option> </select> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="tcFlag">业务类型:</label> <select id="tcFlag" name="tcFlag" class="search-input200"> <option value=""></option> <option value="1">TC上门揽收</option> <option value="0">B网揽收</option> </select> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="receiveBeginTime">预约揽收开始时间:</label> <span class="input-icon input-icon-right"> <input id="receiveBeginTime" type="text" readonly="readonly" class="search-input200" style="background-color:#ffffff !important;" /> <input type="hidden" id="receiveBeginTimeBegin" name="receiveBeginTimeBegin" /> <input type="hidden" id="receiveBeginTimeEnd" name="receiveBeginTimeEnd" /> <i class="icon-calendar add-on"></i> </span> </div> <button class="btn btn-sm btn-purple" type="button" id="clearTime"> <i class="icon-undo icon-on-right bigger-110"></i>清空时间 </button> </div> <div class="row"> <div class="control-group search-group"> <label class="control-label search-lable100" for="createTime">创建时间:</label> <span class="input-icon input-icon-right"> <input id="createTime" type="text" readonly="readonly" class="search-input200" style="background-color: rgb(255, 255, 255) !important;"> <input type="hidden" id="createBeginTime" name="createBeginTime"> <input type="hidden" id="createEndTime" name="createEndTime"> <i class="icon-calendar add-on"></i> </span> </div> <div class="control-group search-group"> <label class="control-label search-lable100" for="transbillCode">发货地址:</label> <input type="text" id="beginAddress" name="beginAddress" class="search-input200" value=""> </div> </div> <div class="row"> <div class="col-xs-12"> <div class="control-group search-group" style="width: 100%; text-align: center;"> <button class="btn btn-sm btn-primary" type="button" id="queryBtn"> <i class="icon-search icon-on-right bigger-110"></i>查询 </button> <button class="btn btn-sm btn-info" type="button" id="batchReassignBtn"> <i class="icon-wrench icon-on-right bigger-110"></i>批量修改调度中心 </button> <button class="btn btn-sm btn-pink" type="button" id="exportBtn"> <i class="icon-share-alt icon-on-right bigger-110"></i>导出 </button> <input type="hidden" id="currentPage" name="currentPage" value="1"/> </div> </div> </div> </form> </div> <div class="row"> <div class="col-xs-12"> <div class="table-responsive" style="overflow: hidden"> <table class="table table-striped table-bordered table-hover" id="sample-table-1" data-toggle="table" data-height="500"> <thead> <tr> <th class="center" width="50"> <label> <input type="checkbox" id="checkboxAll" name="checkboxAll" title="全选/反选" /> <span class="lbl"></span> </label> </th> <th>操作</th> <th>揽收任务号|询价单号</th> <th>运单号</th> <th>发货商家</th> <th>订单来源</th> <th>业务类型</th> <th>承运商类型</th> <th>承运商车队</th> <th>承运商</th> <th>调度状态</th> <th>调度中心</th> <th>温层</th> <th>是否包装</th> <th>行业类型</th> <th>预计体积</th> <th>预计重量</th> <th>预计件数</th> <th>揽收省份</th> <th>揽收城市</th> <th>揽收县区</th> <th>揽收乡镇</th> <th>目的快运中心</th> <th>揽收方式</th> <th>预约揽收开始时间</th> <th>预约揽收结束时间</th> <th>取消揽收原因</th> <th>操作终端</th> <th>实测温度</th> </tr> </thead> <tbody id="dataTbody"> </tbody> </table> </div><!-- /.table-responsive --> <div id="pageBarDiv" class="row"></div> </div><!-- /span --> </div> </div><!-- /.page-content --> </div><!-- /.main-content --> <!-- Modal --> <div class="modal fade" id="inputDialog" tabindex="-1" role="dialog" aria-labelledby="inputDialogLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"> <span aria-hidden="true">×</span><span class="sr-only">Close</span> </button> <h4 class="modal-title" id="inputDialogLabel">修改调度中心</h4> </div> <div class="modal-body"> <table class="table table-striped table-bordered table-hover"> <tbody> <tr id="transbillCodeTR"> <td class="td-label">运单号:</td> <td> <input type="text" id="input_transbillCode" class="col-md-5" value="" disabled="disabled"><!-- 只能输入字母数字--> <span class="red">*</span> </td> </tr> <tr> <td class="td-label">所属调度中心:</td> <td> <input type="text" id="input_scheduleCenterName" name="input_scheduleCenterName" class="search-input300" value=""> <input type="hidden" id="input_scheduleCenterCode" name="input_scheduleCenterCode" value=""/> </td> </tr> </tbody> </table> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="inputSubmitBtn" data-loading-text="正在处理..." >保存</button> </div> </div> </div> </div> <!-- page specific plugin scripts --> <script src="/static/assets/js/jquery.dataTables.min.js" type="text/javascript"></script> <script src="/static/assets/js/jquery.dataTables.bootstrap.js" type="text/javascript"></script> <script src="/static/js/plugins/json2.js" type="text/javascript"></script> <script src="/static/js/common/pcct.selector.js" type="text/javascript"></script> <script src="/static/js/common/basic-data-client.js" type="text/javascript"></script> <script src="/static/js/plugins/bootstrap-select.js" type="text/javascript"></script> <script src="/static/assets/js/bootstrap-table-fixed-columns.min.js" type="text/javascript"></script> <script src="/static/js/boss/receive-transbill/index.js?v=20240819" type="text/javascript"></script> <script src="/static/assets/js/ace-extra.min.js" type="text/javascript"></script> <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src="/static/assets/js/html5shiv.js" type="text/javascript"></script> <script src="/static/assets/js/respond.min.js" type="text/javascript"></script> <![endif]--> <!-- ace scripts --> <script src="/static/assets/js/jquery-ui.1.12.1.js" type="text/javascript"></script> <script src="/static/assets/js/typeahead-bs2.min.js" type="text/javascript"></script> <script src="/static/assets/js/ace-elements.min.js" type="text/javascript"></script> <script src="/static/assets/js/ace.min.js" type="text/javascript"></script> <script src="/static/assets/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script> <script src="/static/assets/js/bootbox.min.js" type="text/javascript"></script> <script src="/static/js/plugins/jquery.blockUI.js" type="text/javascript"></script> <script src="/static/js/plugins/sweetalert/sweet-alert.js" type="text/javascript"></script> <script src="/static/js/common/common-client.js" type="text/javascript"></script> <script src="/static/js/common/common-ui.js?v=20160909" type="text/javascript"></script> <script src="/static/js/common/utils.js?t=20150128" type="text/javascript"></script> <script src="/static/js/plugins/dateRange/moment.min.js" type="text/javascript"></script> <script src="/static/js/plugins/dateRange/daterangepicker.js" type="text/javascript"></script><script type="text/javascript"> /************将以下脚本部署至每一个页面底部</body> 之前且紧挨</body> 。每个页面只可引用一次,不可重复引用。*************/ var jaq = jaq || []; jaq.push(['account', 'JA2018_1121107']); jaq.push(['domain', 'jd.com']); //jaq.push(['erp_account', 'test']); //ERP帐号,erp_account为字段名固定不变,test填入用户erp帐号(调用方自己传,若不传,会记录用户的京东pin) (function () { var ja = document.createElement('script'); ja.type = 'text/javascript'; ja.async = true; ja.src = '//wl.jd.com/joya.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ja, s); })() </script> </body> </html>
09-05
如下述代码1,是一个弹窗的代码页面(如图1所示),调整一下左侧的"SQL查询",当分辨率高变形的有点厉害了,请参照代码2中的样式所示,请优化"SQL查询"的样式,并完整的写出修改后的代码(不改变代码1中的功能,即"sql查询"框中能够输入sql语句不变) ### 代码1:src\views\handle\dataset\add\AddView.vue ```vue <template> <div class="sql-dataset-container"> <el-container class="layout-container"> <!-- 右侧SQL配置表单 --> <el-aside width="40%" class="config-aside"> <div class="config-section"> <div class="section-header"> <h2><el-icon><setting /></el-icon> SQL数据集配置</h2> </div> <el-form :model="form" :rules="rules" label-position="top" class="config-form" ref="formRef" > <!-- 数据集名称 - 修改为行内布局 --> <el-form-item v-if="props.id===''" label="数据集名称" prop="name" class="form-item-card inline-form-item"> <el-input v-model="form.name" placeholder="例如: 用户行为分析数据集" size="large" :prefix-icon="Document" /> </el-form-item> <!-- SQL编辑器 --> <el-form-item label="SQL查询" prop="sql" class="form-item-card sql-editor-item"> <div class="sql-editor-container"> <VAceEditor v-model:value="form.sql" lang="sql" theme="github" style="height: 300px; width: 100%" :options="{ enableBasicAutocompletion: true, enableLiveAutocompletion: true, highlightActiveLine: true, showLineNumbers: true, tabSize: 2, }" /> <div class="sql-tips"> <el-tag type="info" size="small"> <el-icon><info-filled /></el-icon> 提示: 请确保SQL语法正确且符合数据源规范 </el-tag> </div> </div> </el-form-item> </el-form> </div> </el-aside> <!-- 左侧数据预览 --> <el-main class="preview-main"> <div class="preview-section"> <div class="section-header"> <div class="header-left"> <h2><el-icon><data-line /></el-icon> 数据预览</h2> </div> <div class="header-right"> <el-button type="warning" plain size="small" @click="emit('cancel')" :icon="Close">取消</el-button> <el-button type="success" plain size="small" :disabled="!form.sql" @click="fetchPreviewData" :icon="Refresh">执行SQL预览</el-button> <el-button type="primary" plain size="small" @click="handleSave" :icon="Check">保存</el-button> </div> </div> <div class="preview-content"> <zr-table :tableModule="tableModule" /> </div> </div> </el-main> </el-container> </div> </template> <script setup> import {ref, reactive, onMounted, getCurrentInstance} from 'vue' import { VAceEditor } from 'vue3-ace-editor' import '@/components/CodeEdit/ace-config.js' import { Setting, DataLine, Document, Refresh, Check, Close, InfoFilled, Edit, Download } from '@element-plus/icons-vue' import ZrTable from "@/components/ZrTable/index.vue"; import {buildFilterSos} from "@/components/ZrTable/table.js"; import { handleDataSetCreate, handleDataSetGet, handleDataSetPreviewData, handleDataSetReconstruct } from "@/api/handle/dataset.js"; const { proxy } = getCurrentInstance() const props = defineProps({ sceneId:{ type: String, default: '', }, id:{ type: String, default: '', } }) const emit = defineEmits(['saved', 'cancel']) const form = ref({ id:props.id, name: '', sceneId:props.sceneId, type:'view', sql: '', info:'', }) //数据预览 const columnsData= ref([]) const queryData = ref([]) const state = reactive({ columns: columnsData, // 表格配置 query: queryData, // 查询条件配置 queryForm: {}, // 查询form表单 loading: false, // 加载状态 dataList: [], // 列表数据 pages:false, }) const { loading, dataList, columns, pages, query, queryForm } = toRefs(state) const formRef = ref(null) // 预览数据 // 传给子组件的 const tableModule = ref({ callback: fetchPreviewData, // 回调,子组件中可以看到很多调用callback的,这里对应的是获取列表数据的方法 // 以下不说了,上面都给解释了 queryForm, columns, dataList, loading, pages, query, }) const rules = reactive({ name: [ { required: true, message: '请输入数据集名称', trigger: 'blur' }, { max: 50, message: '名称长度不能超过50个字符', trigger: 'blur' } ], sql: [ { required: true, message: '请输入SQL查询语句', trigger: 'blur' }, { validator: (rule, value, callback) => { if (!value || !value.trim()) { callback(new Error('SQL不能为空')) } else if (!value.toLowerCase().includes('select')) { callback(new Error('SQL必须是SELECT查询语句')) } else { callback() } }, trigger: 'blur' } ] }) async function fetchPreviewData() { state.loading = true const valid = await formRef.value.validate() if (!valid) { proxy.$modal.msgError("校验错误,请修改好再次执行") return } // 掉自己的接口,切勿复制粘贴 handleDataSetPreviewData({ sql:form.value.sql }).then((res) => { if (res.success) { if(res.data.pageData.length>0){ for (let key in res.data.pageData[0]) { columnsData.value.push({prop: key, label:key, align: 'center',show:1}) } } state.dataList = res.data.pageData proxy.$modal.msgSuccess('SQL执行成功') } else { proxy.$modal.msgError(res.message) } }) state.loading = false } const handleSave = async () => { const valid = await formRef.value.validate() if (!valid) return form.value.info=JSON.stringify({ sql:form.value.sql }) const method=form.value.id===""?handleDataSetCreate:handleDataSetReconstruct method(form.value).then((res) => { if (res.success) { emit('saved',{id: res.data }) } else { proxy.$modal.msgError(res.message) } }) } watch(() => props.id, (newid, oldid) => { if (newid !== oldid && newid!=="") { // 引用变化时触发 handleDataSetGet(newid).then((res) => { if(res.success){ form.value.sql=JSON.parse(res.data.info)?.sql; } }) } }, { immediate: true } // 注意:不要用 deep: true ); </script> <style scoped lang="scss"> .sql-dataset-container { height: calc(90vh - 60px); padding: 20px; background-color: #f5f7fa; } .layout-container { height: 100%; background: #fff; border-radius: 12px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05); overflow: hidden; display: flex; } .config-aside { background: #f9fafc; border-right: 1px solid var(--el-border-color-light); padding: 24px; display: flex; flex-direction: column; } .preview-main { padding: 24px; background: #fff; display: flex; flex-direction: column; } .section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; h2 { margin: 0; color: var(--el-text-color-primary); font-weight: 600; font-size: 18px; display: flex; align-items: center; gap: 8px; } .header-left, .header-right { display: flex; align-items: center; } } .preview-content { flex: 1; border: 1px solid var(--el-border-color-light); border-radius: 8px; overflow: hidden; display: flex; flex-direction: column; } .config-form { flex: 1; display: flex; flex-direction: column; :deep(.el-form-item) { margin-bottom: 20px; &.inline-form-item { :deep(.el-form-item__label) { display: inline-flex; align-items: center; width: auto; margin-right: 12px; padding-bottom: 0; } :deep(.el-form-item__content) { display: inline-flex; flex: 1; } } .el-form-item__label { font-weight: 500; padding-bottom: 8px; color: var(--el-text-color-regular); font-size: 14px; } } } .form-item-card { background: #fff; padding: 16px; border-radius: 8px; border-left: 3px solid var(--el-color-primary); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05); } .sql-editor-item { flex: 1; display: flex; flex-direction: column; :deep(.el-form-item__content) { flex: 1; display: flex; flex-direction: column; } } .sql-editor-container { flex: 1; display: flex; flex-direction: column; border: 1px solid var(--el-border-color-light); border-radius: 4px; overflow: hidden; } .sql-tips { padding: 8px 12px; background: var(--el-color-info-light-9); border-top: 1px solid var(--el-border-color-light); .el-tag { width: 100%; justify-content: flex-start; .el-icon { margin-right: 6px; } } } .form-actions { margin-top: 24px; padding-top: 16px; display: flex; justify-content: flex-end; gap: 16px; border-top: 1px dashed var(--el-border-color); } .refresh-btn { :deep(.el-icon) { margin-right: 6px; } } @media (max-width: 992px) { .layout-container { flex-direction: column; } .config-aside { width: 100% !important; border-right: none; border-bottom: 1px solid var(--el-border-color-light); } } </style> ``` ### 代码2:src\views\handle\dataset\add\AddView.vue ```vue <template> <div class="sql-dataset-container"> <el-container class="layout-container"> <!-- 左侧:数据集名称和SQL查询 --> <el-aside class="config-aside"> <div class="config-section"> <div class="section-header"> <h2><el-icon><setting /></el-icon> SQL数据集配置</h2> </div> <el-form :model="form" :rules="rules" label-position="top" class="config-form" ref="formRef" > <!-- 数据集名称 --> <el-form-item v-if="props.id === ''" label="数据集名称" prop="name" class="form-item-card inline-form-item"> <el-input v-model="form.name" placeholder="例如: 用户行为分析数据集" size="large" :prefix-icon="Document" /> </el-form-item> <!-- SQL编辑器 --> <el-form-item label="SQL查询" prop="sql" class="form-item-card sql-editor-item"> <div class="sql-editor-container"> <VAceEditor v-model:value="form.sql" lang="sql" theme="github" style="height: 100%; width: 100%" :options="{ enableBasicAutocompletion: true, enableLiveAutocompletion: true, highlightActiveLine: true, showLineNumbers: true, tabSize: 2, }" /> <div class="sql-tips"> <el-tag type="info" size="small"> <el-icon><info-filled /></el-icon> 提示: 请确保SQL语法正确且符合数据源规范 </el-tag> </div> </div> </el-form-item> </el-form> </div> </el-aside> <!-- 右侧:数据预览 --> <el-main class="preview-main"> <div class="preview-section"> <div class="section-header"> <div class="header-left"> <h2><el-icon><data-line /></el-icon> 数据预览</h2> </div> <div class="header-right"> <el-button type="warning" plain size="small" @click="emit('cancel')" :icon="Close">取消</el-button> <el-button type="success" plain size="small" :disabled="!form.sql" @click="fetchPreviewData" :icon="Refresh">执行SQL预览</el-button> <el-button type="primary" plain size="small" @click="handleSave" :icon="Check">保存</el-button> </div> </div> <div class="preview-content"> <zr-table :tableModule="tableModule" /> </div> </div> </el-main> </el-container> </div> </template> <script setup> import {ref, reactive, onMounted, getCurrentInstance, watch} from 'vue' import { VAceEditor } from 'vue3-ace-editor' import '@/components/CodeEdit/ace-config.js' import { Setting, DataLine, Document, Refresh, Check, Close, InfoFilled, Edit, Download } from '@element-plus/icons-vue' import ZrTable from "@/components/ZrTable/index.vue"; import {buildFilterSos} from "@/components/ZrTable/table.js"; import { handleDataSetCreate, handleDataSetGet, handleDataSetPreviewData, handleDataSetReconstruct } from "@/api/handle/dataset.js"; const { proxy } = getCurrentInstance() const props = defineProps({ sceneId:{ type: String, default: '', }, id:{ type: String, default: '', } }) const emit = defineEmits(['saved', 'cancel']) const form = ref({ id:props.id, name: '', sceneId:props.sceneId, type:'view', sql: '', info:'', }) //数据预览 const columnsData= ref([]) const queryData = ref([]) const state = reactive({ columns: columnsData, // 表格配置 query: queryData, // 查询条件配置 queryForm: {}, // 查询form表单 loading: false, // 加载状态 dataList: [], // 列表数据 pages:false, }) const { loading, dataList, columns, pages, query, queryForm } = toRefs(state) const formRef = ref(null) // 预览数据 // 传给子组件的 const tableModule = ref({ callback: fetchPreviewData, // 回调,子组件中可以看到很多调用callback的,这里对应的是获取列表数据的方法 // 以下不说了,上面都给解释了 queryForm, columns, dataList, loading, pages, query, }) const rules = reactive({ name: [ { required: true, message: '请输入数据集名称', trigger: 'blur' }, { max: 50, message: '名称长度不能超过50个字符', trigger: 'blur' } ], sql: [ { required: true, message: '请输入SQL查询语句', trigger: 'blur' }, { validator: (rule, value, callback) => { if (!value || !value.trim()) { callback(new Error('SQL不能为空')) } else if (!value.toLowerCase().includes('select')) { callback(new Error('SQL必须是SELECT查询语句')) } else { callback() } }, trigger: 'blur' } ] }) async function fetchPreviewData() { state.loading = true const valid = await formRef.value.validate() if (!valid) { proxy.$modal.msgError("校验错误,请修改好再次执行") return } // 掉自己的接口,切勿复制粘贴 handleDataSetPreviewData({ sql:form.value.sql }).then((res) => { if (res.success) { columnsData.value = []; // 重置列数据 if(res.data.pageData.length>0){ for (let key in res.data.pageData[0]) { columnsData.value.push({prop: key, label:key, align: 'center',show:1}) } } state.dataList = res.data.pageData proxy.$modal.msgSuccess('SQL执行成功') } else { proxy.$modal.msgError(res.message) } }) state.loading = false } const handleSave = async () => { const valid = await formRef.value.validate() if (!valid) return form.value.info=JSON.stringify({ sql:form.value.sql }) const method=form.value.id===""?handleDataSetCreate:handleDataSetReconstruct method(form.value).then((res) => { if (res.success) { emit('saved',{id: res.data }) } else { proxy.$modal.msgError(res.message) } }) } watch(() => props.id, (newid, oldid) => { if (newid !== oldid && newid!=="") { // 引用变化时触发 handleDataSetGet(newid).then((res) => { if(res.success){ form.value.sql=JSON.parse(res.data.info)?.sql; } }) } }, { immediate: true } // 注意:不要用 deep: true ); </script> <style scoped lang="scss"> .sql-dataset-container { height: calc(90vh - 60px); padding: 16px; background-color: #f5f7fa; } .layout-container { height: 100%; background: #fff; border-radius: 8px; box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05); overflow: hidden; display: flex; /* 使用flex横向布局 */ flex-direction: row; /* 横向排列 */ } .config-aside { background: #f9fafc; border-right: 1px solid var(--el-border-color-light); /* 右侧边框分隔 */ padding: 18px; display: flex; flex-direction: column; width: 50%; /* 左侧占50%宽度 */ min-width: 300px; /* 最小宽度限制 */ } .preview-main { padding: 18px; background: #fff; display: flex; flex-direction: column; flex: 1; /* 右侧占剩余宽度 */ min-width: 300px; /* 最小宽度限制 */ } .section-header { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; margin-bottom: 16px; gap: 12px; h2 { margin: 0; color: var(--el-text-color-primary); font-weight: 600; font-size: 16px; display: flex; align-items: center; gap: 6px; white-space: nowrap; } } .preview-content { flex: 1; border: 1px solid var(--el-border-color-light); border-radius: 6px; overflow: hidden; display: flex; flex-direction: column; min-height: 250px; } .config-form { flex: 1; display: flex; flex-direction: column; :deep(.el-form-item) { margin-bottom: 16px; } } .form-item-card { background: #fff; padding: 12px; border-radius: 6px; border-left: 2px solid var(--el-color-primary); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03); } .sql-editor-container { flex: 1; display: flex; flex-direction: column; border: 1px solid var(--el-border-color-light); border-radius: 4px; overflow: hidden; min-height: 220px; max-height: 400px; } .sql-tips { padding: 6px 10px; background: var(--el-color-info-light-9); border-top: 1px solid var(--el-border-color-light); .el-tag { width: 100%; justify-content: flex-start; font-size: 11px; padding: 4px 8px; } } /* 响应式调整 */ @media (max-width: 992px) { .layout-container { flex-direction: column; /* 小屏幕下改为纵向布局 */ } .config-aside, .preview-main { width: 100%; /* 占满宽度 */ min-width: auto; /* 取消最小宽度限制 */ } .config-aside { border-right: none; border-bottom: 1px solid var(--el-border-color-light); /* 底部边框分隔 */ max-height: 50%; /* 限制最大高度 */ } .sql-dataset-container { padding: 12px; height: auto; min-height: 100vh; } .section-header { flex-direction: column; align-items: stretch; .header-left, .header-right { width: 100%; } .header-right { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 8px; } } .sql-editor-container { max-height: 250px; min-height: 180px; } } @media (max-width: 768px) { .preview-content { min-height: 200px; } .section-header { gap: 8px; h2 { font-size: 15px; } } .header-right { grid-template-columns: repeat(2, 1fr) !important; .el-button { width: 100%; margin: 0 !important; } .el-button:last-child { grid-column: span 2; } } } @media (max-width: 480px) { .sql-dataset-container { padding: 8px; } .config-aside, .preview-main { padding: 12px; } .sql-editor-container { min-height: 150px; max-height: 200px; } .form-item-card { padding: 8px; } .el-input, .el-button { font-size: 13px !important; } } </style> ```
07-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值