接手的一个项目使用的是avue这个傻瓜式的专门给后端人员用的框架,文档不够友好,使用起来各种蛋疼(咱专业前端基本上不使用)。为此,专门记录一下。当前avue版本2.8.12,如果要切换avue的版本,可以去https://cdn.jsdelivr.net/npm/@smallwei/avue@2.8.12/lib/这个地址去选择自己要的版本,然后进行下载,我这里是通过cdn的方式引用的。
avue官网地址:https://www.avuejs.com/
先选择来源系统,根据所选择的来源系统,自动加载来源表,如下图所示:

js代码如下:
{
label: this.$t("sourceDatasource"),
prop: "sourceDatasource",
type: "select",
clearable: false,
dicData: [],
cascaderItem: ["sourceTable"],
// dicUrl: `/emptech-middle/dataSource/list`,
// dicQuery: { current: 1, size: 100 , descs: "create_time",dsType:"ORACLE"},
// props: {
// label: "dsName",
// value: "id"
// },
// dicFormatter: res => {
// return res.data.records; //返回字典的层级结构
// },
span: 24,
rules: [
{
required: true,
message: this.$t("sourceSysMessage"),
trigger: "blur"
}
]
},
{
label: this.$t("sourceTable"),
prop: "sourceTable",
type: "select",
clearable: false,
dicFlag: false,
dicUrl:
"/emptech-middle/dataTable/getTablesByDataBase?dsId={{key}}",
props: {
label: "tableName",
value: "tableName"
},
search: true,
searchslot: true, //使用插槽
span: 24,
rules: [
{
required: true,
message: this.$t("sourceTbMessage"),
trigger: "blur"
}
]
},
级联这里,第一个字段要配置cascaderItem属性,指定要关联的字段,然后被关联的字段,属性要配置dicFlag: false,否则界面第一次加载时,被关联的字典接口就会自动请求一次。
需要主意的是,如果sourceDatasource配置为dicUrl加载字典的方式,每次界面加载的时候,会调用这个字典接口两次,所以可以采用dicData: []的形式,在mounted中获取字典数据,然后给字典数据赋值的方式,如下代码所示:
async mounted() {//添加字典
await this.initDictData();
let sourceSysColumn = this.findObject(
this.option.column,
"sourceDatasource"
);
sourceSysColumn.dicData = this.sourceSysDicData;
},
methods: {
//初始化字典数据
async initDictData() {
let res = await getDataSourceList(1, 100, {
descs: "create_time",
dsType: "ORACLE"
});
if (res.data.code == 200) {
this.sourceSysDicData = res.data.data.records.map(m => {
return {
value: m.id,
label: m.dsName
};
});
}
},
如下图所示,原表是一个下拉框字典,搜索的时候,需要是一个文本框模糊搜索:

js代码如下:
{
label: this.$t("sourceTable"),
prop: "sourceTable",
type: "select",
clearable: false,
dicFlag: false,
dicUrl:
"/emptech-middle/dataTable/getTablesByDataBase?dsId={{key}}",
props: {
label: "tableName",
value: "tableName"
},
search: true,
searchslot: true, //使用插槽
span: 24,
rules: [
{
required: true,
message: this.$t("sourceTbMessage"),
trigger: "blur"
}
]
},
html代码如下:
<avue-crud
:search.sync="query"
:option="option"
:table-loading="loading"
:data="tbData"
ref="crud"
v-model="form"
:permission="permissionList"
:before-open="beforeOpen"
:before-close="beforeClose"
@row-del="rowDel"
@row-update="rowUpdate"
@row-save="rowSave"
@search-change="searchChange"
@search-reset="searchReset"
@selection-change="selectionChange"
@current-change="currentChange"
@size-change="sizeChange"
@refresh-change="refreshChange"
@on-load="onLoad"
:page.sync="page"
>
<template slot-scope="scope" slot="sourceTableSearch">
<el-input
:placeholder="$t('sourceTbSearchPlaceholder')"
:size="size"
col="6"
v-model="query.sourceTable"
></el-input>
</template>
通过插槽,插槽名字为字段名称+Search,此处为sourceTableSearch
如下图所示,当最大可同步范围选择“自然月”时,下面展示是否支持跨周,否则不展示:


js代码:
{
label: this.$t("taskManage.maxSynchronizedRange"),
prop: "maxSyncType",
type: "select",
hide: true,
span: 24,
value: "1", //默认值,自然周
clearable: false,
rules: [
{
required: true,
message: this.$t("taskManage.maxSynchronizedRangeMessage"),
trigger: "blur"
}
],
dicData: [],
// dicUrl:
// "/emptech-system/dict-biz/dictionary?code=data_sync_max_scope_type",
// props: {
// label: "dictValue",
// value: "dictKey"
// },
control: (val, form) => {
console.log("数据", val);
if (val == 2) {
//自然月
return {
isCrossWeek: {
display: true
}
};
} else {
return {
isCrossWeek: {
display: false
}
};
}
}
},
{
label: this.$t("taskManage.isCrossWeek"),
prop: "isCrossWeek",
type: "radio",
value: "1", //默认值,是
viewDisabled: true,
dicUrl:
"/emptech-system/dict-biz/dictionary?code=data_sync_is_cross_week",
props: {
label: "dictValue",
value: "dictKey"
},
hide: true,
span: 24
},
html代码如下所示:
<template slot-scope="{ row, disabled }" slot="maxSyncTypeForm">
<div class="form-row">
<avue-select
v-model="form.maxSyncType"
:clearable="false"
type="select"
:dic="maxSyncTypeDicData"
:disabled="disabled"
></avue-select>
<el-tooltip placement="right-start">
<div slot="content">
自然周内:如2022年8月1日到2022年8月7日为一个自然周,自然周内则表示可选时间范围为在8月1日到8月7日之间;
<br />
自然月内:如2022年8月为一个自然月,自然月内则表示可选时间范围为<=8月自然月天数。
</div>
<i class="el-icon-question icon"></i>
</el-tooltip>
</div>
</template>
在最大可同步范围字段中可以配置control方法来控制其它字段的隐藏或者显示,当然也可以通过watch的方式,后面会说到。
需求如下图所示,这个执行时间范围只是一个搜索条件,并不会在表格中进行展示,日期时间范围组件默认显示当前时间+00:00:00 到当前时间23:59:59,选择其它日期时,起止时间的时分秒的范围也默认是00:00:00到23:59:59。

js代码如下:
{
label: this.$t("executingTimeRange"),
prop: "executingTimeRange",
type: "datetimerange",
format: "yyyy-MM-dd HH:mm:ss",
valueFormat: "yyyy-MM-dd HH:mm:ss",
hide: true,
display: false,
search: true,
searchSpan: 5,
searchslot: true, //使用插槽
searchRange: true,
span: 24,
searchSpan: 8
},
html代码:
<!-- 自定义搜索卡槽 -->
<template slot="executingTimeRangeSearch" slot-scope="scope">
<el-date-picker
style="width:360px"
v-model="executingTimeRange"
type="datetimerange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']"
>
</el-date-picker>
</template>
data代码:
executingTimeRange: [getCurTimeStart(), getCurTimeEnd()], //执行时间范围
查询代码需要改造:
//查询
searchChange(params, done) {
if (this.executingTimeRange&&this.executingTimeRange.length == 2) {
params.startExecuteTime = getStrToDatetime(this.executingTimeRange[0]);
params.endExecuteTime = getStrToDatetime(this.executingTimeRange[1]);
}
this.page.currentPage = 1;
this.query = params;
this.onLoad(this.page, params);
done();
},
需求,需要验证所选的日期范围是自然周,还是在一个月内,或者是一个月内的自然周内。

js代码如下:
//新增
rowSave(row, done, loading) {
console.log("新增", row);
let flag = this.dataValidate(row);
if (!flag) {
loading();
return;
}
// retrun;
let item = this.createItem(row);
add(item).then(
res => {
this.$message({
type: "success",
message: this.$t("successMessage")
});
// 数据回调进行刷新
this.onLoad(this.page);
done();
},
error => {
window.console.log(error);
loading();
}
);
},
//数据校验
dataValidate(row) {
console.log("查询", row, this.query);
let dateRange = row.dateRange;
if (dateRange.length < 2) {
this.$message({
message: "请选择日期范围",
type: "warning"
});
return false;
}
let res = true;
let message = "";
if (this.maxSynchronizedRange == MAXSYNCRANGE.week) {
//周
res = isSameWeek(dateRange);
message = "选择的日期范围必须是在同一周内";
} else {
//月
if (this.isCrossWeek == 0) {
//不跨周
res = isSameMonthNoCrossWeek(dateRange);
message = "选择的日期范围必须是在同一月同一周内";
} else {
//跨周
res = isSameMonth(dateRange);
message = "选择的日期范围必须是在同一月内";
}
}if (res == false) {
this.$message({
message: message,
type: "warning"
});
}
return res;
},
注意这个loading()是关闭按钮的loading的意思。done()方法是关闭弹窗的意思。
column中
hide:不在表格列表中显示。
日期处理使用的是moment.js,网址:http://momentjs.cn/
/*
*判断是否在同一个星期里
*dateArr:时间字符串数组
*return:true/false
*/
export function isSameWeek(dateArr) {
return moment(dateArr[0]).isSame(dateArr[1], 'week');
}
/*
*判断是否在同一个月
*dateArr:时间字符串数组
*return:true/false
*/
export function isSameMonth(dateArr) {
return moment(dateArr[0]).isSame(dateArr[1], 'month');
}
/**
* 判断是否在一个月内,且不跨周
* @param {*} dataArr
*/
export function isSameMonthNoCrossWeek(dateArr) {
let start = moment(dateArr[0]).isoWeekday();
let end = moment(dateArr[1]).isoWeekday();
let startDay = moment(dateArr[0]).dayOfYear();
let endDay = moment(dateArr[1]).dayOfYear();
let sameMonth = isSameMonth(dateArr);
let sameWeek = (endDay - startDay < 7) && (start <= end);
return sameMonth && sameWeek; //同月同周
}
/**
* 获取当天开始时间
* @returns
*/
export function getCurTimeStart() {
return moment(moment().format('YYYY-MM-DD') + ' 00:00:00').toDate();
}
/**
* 获取当天结束时间
* @returns
*/
export function getCurTimeEnd() {
return moment(moment().format('YYYY-MM-DD') + ' 23:59:59').toDate();
}
/**
* 字符串
* @param str
* @returns
*/
export function getStrToDatetime(str) {
return moment(str).format('YYYY-MM-DD HH:mm:ss')
}
后面后再不断补充.......
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa
本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决
我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).
我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame
我有一个应用需要发送用户事件邀请。当用户邀请friend(用户)参加事件时,如果尚不存在将用户连接到该事件的新记录,则会创建该记录。我的模型由用户、事件和events_user组成。classEventdefinvite(user_id,*args)user_id.eachdo|u|e=EventsUser.find_or_create_by_event_id_and_user_id(self.id,u)e.save!endendend用法Event.first.invite([1,2,3])我不认为以上是完成我的任务的最有效方法。我设想了一种方法,例如Model.find_or_cr
在许多ruby类之间共享记录器实例的最佳(正确)方法是什么?现在我只是将记录器创建为全局$logger=Logger.new变量,但我觉得有更好的方法可以在不使用全局变量的情况下执行此操作。如果我有以下内容:moduleFooclassAclassBclassC...classZend在所有类之间共享记录器实例的最佳方式是什么?我是以某种方式在Foo模块中声明/创建记录器还是只是使用全局$logger没问题? 最佳答案 在模块中添加常量:moduleFooLogger=Logger.newclassAclassBclassC..
如何在出现异常时指定全局救援,如果您将Sinatra用于API或应用程序,您将如何处理日志记录? 最佳答案 404可以在not_found方法的帮助下处理,例如:not_founddo'Sitedoesnotexist.'end500s可以通过调用带有block的错误方法来处理,例如:errordo"Applicationerror.Plstrylater."end错误的详细信息可以通过request.env中的sinatra.error访问,如下所示:errordo'Anerroroccured:'+request.env['si
例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果