feat(testing): 增加质检报告独立编辑与详情页面,不再使用弹窗
这个提交包含在:
@@ -42,6 +42,14 @@
|
||||
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
|
||||
</div>
|
||||
</div>
|
||||
{if $canSetGranarySites}
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">库区数据权限:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
{:build_select('row[granary_sites]', ['all'=>'全部库区', 'center'=>'遵义中心库', 'xishui'=>'习水库', 'none'=>'无库区权限'], 'all', ['class'=>'form-control'])}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="form-group hidden layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
||||
@@ -48,6 +48,14 @@
|
||||
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
|
||||
</div>
|
||||
</div>
|
||||
{if $canSetGranarySites}
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">库区数据权限:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
{:build_select('row[granary_sites]', ['all'=>'全部库区', 'center'=>'遵义中心库', 'xishui'=>'习水库', 'none'=>'无库区权限'], $row['granary_sites'], ['class'=>'form-control'])}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="form-group hidden layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
||||
@@ -51,13 +51,18 @@
|
||||
</style>
|
||||
<div id="vue" data-id="{$id}" v-cloak>
|
||||
<el-form ref="form" :rules="rules" :model="formData" label-width="90px">
|
||||
<el-form-item label="所属库区:" required>
|
||||
<el-select v-model="formSite" @change="formSiteChanged" placeholder="请选择库区" style="width: 330px">
|
||||
<el-option v-for="site in siteOptions" :key="site.id" :value="site.id" :label="site.name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属仓库:" prop="gid">
|
||||
<el-select style="width: 330px;" v-model="formData.gid" filterable clearable
|
||||
placeholder="请您选择所属仓库">
|
||||
<el-option
|
||||
v-for="item in granaryList"
|
||||
v-for="item in siteGranaries"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:label="granaryLabel(item)"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
@@ -42,6 +42,11 @@
|
||||
<div id="vue" v-cloak>
|
||||
<div class="screen-container">
|
||||
<div class="screen-container-show">
|
||||
<div class="screen-container-right display-flex" style="margin-right: 12px">
|
||||
<el-select v-model="search.site" @change="siteChanged" clearable size="small" placeholder="全部库区" aria-label="筛选库区" style="width: 150px">
|
||||
<el-option v-for="site in siteOptions" :key="site.id" :value="site.id" :label="site.name"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="screen-container-left display-flex">
|
||||
<el-button size="small" @click="refreshPage" icon="el-icon-refresh" circle type="primary"></el-button>
|
||||
<div class="datetime">
|
||||
@@ -71,7 +76,7 @@
|
||||
<el-option
|
||||
v-for="item in granaryList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:label="granaryLabel(item)"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<link rel="stylesheet" href="__CDN__/assets/element-ui-2.15.14/css/index.css">
|
||||
<link rel="stylesheet" href="__CDN__/assets/css/vvv.css">
|
||||
<style>
|
||||
.forecast-page { background: #fff; padding: 20px; }
|
||||
.forecast-toolbar { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; margin-bottom: 18px; }
|
||||
.forecast-toolbar h3 { margin: 0 auto 0 0; font-size: 18px; }
|
||||
.forecast-intro { color: #606266; margin: 0 0 20px; line-height: 1.8; }
|
||||
.forecast-env { display: flex; flex-wrap: wrap; gap: 12px 28px; margin: 16px 0; color: #606266; }
|
||||
.forecast-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 0 20px; }
|
||||
.forecast-fields .el-input, .forecast-fields .el-date-editor { width: 100%; }
|
||||
.forecast-page .el-pagination { margin-top: 18px; text-align: right; }
|
||||
.forecast-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }
|
||||
.forecast-error { margin-bottom: 16px; }
|
||||
.forecast-actual-date { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 16px 0; }
|
||||
.forecast-hint { color: #909399; font-size: 13px; line-height: 1.8; }
|
||||
.forecast-page .el-dialog { max-width: calc(100vw - 24px); }
|
||||
@media (max-width: 700px) { .forecast-fields { grid-template-columns: 1fr; } .forecast-page { padding: 12px; } }
|
||||
</style>
|
||||
<div id="forecast-app" class="forecast-page" v-cloak>
|
||||
<div class="forecast-toolbar">
|
||||
<h3>温湿度预测与实测</h3>
|
||||
<el-select v-model="site" clearable placeholder="全部库区" @change="siteChanged" style="width: 150px" aria-label="筛选库区"><el-option v-for="s in siteOptions" :key="s.id" :value="s.id" :label="s.name"></el-option></el-select>
|
||||
<el-select v-model="gid" clearable filterable placeholder="全部仓库" @change="filterChanged" style="width: 280px" aria-label="筛选仓库">
|
||||
<el-option v-for="g in granaries" :key="g.id" :value="g.id" :label="g.label"></el-option>
|
||||
</el-select>
|
||||
<el-button icon="el-icon-refresh" size="small" @click="load" :loading="loading">刷新</el-button>
|
||||
<el-button type="primary" icon="el-icon-plus" size="small" @click="newRecord">录入温湿度并预测</el-button>
|
||||
</div>
|
||||
<p class="forecast-intro">选择仓库,录入采集当天的仓内外温湿度,生成未来品质指标预测;取得检测结果后,在对应周期补录实测值并查看偏差。</p>
|
||||
<forecast-list :rows="rows" :loading="loading" @open="openRecord"></forecast-list>
|
||||
<el-pagination background layout="total, prev, pager, next" :total="total" :page-size="15" :current-page="page" @current-change="changePage"></el-pagination>
|
||||
<el-dialog title="录入温湿度并预测" :visible.sync="creating" width="760px" :close-on-click-modal="false" :before-close="closeCreate" :show-close="!saving">
|
||||
<forecast-create v-if="creating" ref="create" :granaries="granaries" :busy="saving" @submit="createRecord" @cancel="closeCreate"></forecast-create>
|
||||
</el-dialog>
|
||||
<el-dialog title="预测与真实监测值对比" :visible.sync="viewing" width="1180px" :close-on-click-modal="false" :before-close="closeDetail" :show-close="!saving">
|
||||
<forecast-detail v-if="viewing && selected" ref="detail" :record="selected" :busy="saving" @save="saveActual" @retry="retry"></forecast-detail>
|
||||
<div class="forecast-foot"><el-button @click="closeDetail" :disabled="saving">关闭</el-button></div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<script type="text/x-template" id="forecast-list-template">
|
||||
<el-table :data="rows" border stripe v-loading="loading" empty-text="暂无预测记录,请先录入温湿度">
|
||||
<el-table-column prop="id" label="记录编号" width="90"></el-table-column>
|
||||
<el-table-column prop="granary_name" label="仓库" min-width="120"></el-table-column>
|
||||
<el-table-column prop="storage" label="库区" min-width="180" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="observed_date" label="采集日期" width="115"></el-table-column>
|
||||
<el-table-column label="仓内温湿度" min-width="175">
|
||||
<template slot-scope="s">
|
||||
<div style="display:flex;align-items:center;gap:6px;flex-wrap:wrap">
|
||||
<span>{{number(s.row.tm_i)}}℃ / {{number(s.row.hm_i)}}%</span>
|
||||
<el-tag :type="evalTemp(s.row.tm_i, s.row.hm_i).tagType" size="mini" effect="plain">{{evalTemp(s.row.tm_i, s.row.hm_i).label}}</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="仓外温湿度" min-width="145"><template slot-scope="s">{{number(s.row.tm_o)}}℃ / {{number(s.row.hm_o)}}%</template></el-table-column>
|
||||
<el-table-column label="预测状态" width="130"><template slot-scope="s"><el-tag :type="s.row.status === 'ready' ? 'success' : s.row.status === 'failed' ? 'danger' : 'warning'" size="small">{{status(s.row.status)}}</el-tag></template></el-table-column>
|
||||
<el-table-column label="实测完成周期" width="120"><template slot-scope="s">{{s.row.measured}} / {{s.row.point_count}}</template></el-table-column>
|
||||
<el-table-column label="操作" width="150" fixed="right"><template slot-scope="s"><el-button type="text" @click="$emit('open', s.row.id)">查看 / 补录实测</el-button></template></el-table-column>
|
||||
</el-table>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="forecast-create-template">
|
||||
<el-form label-position="top" @submit.native.prevent>
|
||||
<el-form-item label="所属仓库(小麦 / 稻谷)" required>
|
||||
<el-select v-model="form.gid" filterable placeholder="请选择仓库" style="width: 100%" :disabled="busy">
|
||||
<el-option v-for="g in granaries" :key="g.id" :value="g.id" :label="g.label"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 中储粮温控规范快捷工况 -->
|
||||
<div class="forecast-preset-box" style="margin-bottom: 16px; padding: 10px 14px; background: #f4f8fa; border: 1px solid #dbe6ee; border-radius: 6px;">
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;">
|
||||
<span style="font-size: 13px; font-weight: bold; color: #304157;">🎯 快捷规范工况模板:</span>
|
||||
<span style="font-size: 12px; color: #909399;">符合中储粮《粮油储藏技术规范》GB/T 29890</span>
|
||||
</div>
|
||||
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
|
||||
<el-button v-for="(p, k) in presets" :key="k" size="mini" :type="selectedPresetKey === k ? p.type : ''" plain @click="applyPreset(k)">
|
||||
{{p.name}} ({{p.tm_i}}℃ / {{p.hm_i}}%)
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 实时温控规范研判指示卡片 -->
|
||||
<div class="forecast-standard-banner" style="margin-bottom: 16px; padding: 8px 12px; border-radius: 6px; font-size: 13px; display: flex; align-items: center; justify-content: space-between;"
|
||||
:style="{ background: tempStatus.isHigh ? '#fef0f0' : (tempStatus.grade === 'low' ? '#f0f9eb' : '#edf6fc'), border: '1px solid ' + (tempStatus.isHigh ? '#fde2e2' : (tempStatus.grade === 'low' ? '#e1f3d8' : '#d9ecff')) }">
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<el-tag :type="tempStatus.tagType" size="small">{{tempStatus.label}}</el-tag>
|
||||
<span :style="{ color: tempStatus.isHigh ? '#f56c6c' : (tempStatus.grade === 'low' ? '#67c23a' : '#409eff') }">{{tempStatus.hint}}</span>
|
||||
</div>
|
||||
<span v-if="tempStatus.isHigh" style="font-size: 12px; color: #f56c6c; font-weight: bold;">[注意通风降温]</span>
|
||||
</div>
|
||||
|
||||
<div class="forecast-fields">
|
||||
<el-form-item label="温湿度采集日期" required><el-date-picker v-model="form.observed_date" type="date" value-format="yyyy-MM-dd" :picker-options="dateOptions" :disabled="busy" :editable="false" placeholder="选择采集日期"></el-date-picker></el-form-item>
|
||||
<el-form-item label="预测周期" required><el-checkbox-group v-model="form.horizons" :disabled="busy"><el-checkbox v-for="day in [7,15,30,60]" :key="day" :label="day">{{day}}天后</el-checkbox></el-checkbox-group></el-form-item>
|
||||
<el-form-item v-for="field in fields" :key="field.key" :label="field.label" required>
|
||||
<el-input v-model="form[field.key]" :label="field.label" type="number" :min="field.min" :max="field.max" step="0.1" :disabled="busy" placeholder="请输入实测环境值"><template slot="append">{{field.unit}}</template></el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<p class="forecast-hint"><strong>中储粮控温技术规范:</strong>低温储粮 ≤15℃,准低温储粮 ≤20℃,常温储粮 ≤25℃(>25℃需通风或机械降温)。仓内相对湿度建议 ≤70%~75%。预测目标日期按采集日期加周期计算。</p>
|
||||
<div class="forecast-foot"><el-button :disabled="busy" @click="$emit('cancel')">取消</el-button><el-button type="primary" :loading="busy" @click="submit">保存并生成预测</el-button></div>
|
||||
</el-form>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="forecast-detail-template">
|
||||
<div>
|
||||
<strong>{{record.storage}} · {{record.granary_name}} · {{record.grain_type === 'wheat' ? '小麦' : '稻谷'}}</strong>
|
||||
<div class="forecast-env"><span>采集日期:{{record.observed_date}}</span><span>仓内:{{number(record.tm_i)}}℃ / {{number(record.hm_i)}}%</span><span>仓外:{{number(record.tm_o)}}℃ / {{number(record.hm_o)}}%</span></div>
|
||||
<div v-if="record.status !== 'ready'" class="forecast-error">
|
||||
<el-alert :title="record.status === 'processing' ? '预测正在生成,稍后刷新查看结果;若请求中断,两分钟后可重试。' : (record.error || '温湿度已保存,等待生成预测。')" :type="record.status === 'failed' ? 'error' : 'warning'" :closable="false" show-icon></el-alert>
|
||||
<el-button style="margin-top: 10px" size="small" type="primary" :loading="busy" @click="$emit('retry', record.id)">重新生成预测 / 刷新状态</el-button>
|
||||
</div>
|
||||
<el-tabs v-model="active" :before-leave="beforeLeave">
|
||||
<el-tab-pane v-for="p in record.points" :key="p.id" :name="String(p.id)" :label="'+' + p.horizon + '天 · ' + p.target_date"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<div v-if="point">
|
||||
<div class="forecast-actual-date"><strong>预测目标:{{point.target_date}}</strong><label>实际检测日期:</label><el-date-picker v-model="actualDate" type="date" value-format="yyyy-MM-dd" :picker-options="dateOptions" :editable="false" :disabled="busy" placeholder="取得结果后选择实际检测日期"></el-date-picker></div>
|
||||
<el-alert v-if="actualDate && actualDate !== point.target_date" title="实际检测日期与预测目标日期不同,以下偏差仅供参考,请核对是否选对周期。" type="warning" :closable="false" show-icon style="margin-bottom: 12px"></el-alert>
|
||||
<el-table :data="comparison" border>
|
||||
<el-table-column prop="name" label="监测指标" min-width="200"></el-table-column>
|
||||
<el-table-column prop="unit" label="单位" width="100"></el-table-column>
|
||||
<el-table-column label="原始预测值" width="125"><template slot-scope="s">{{number(s.row.predicted)}}</template></el-table-column>
|
||||
<el-table-column label="人工实测值" min-width="155"><template slot-scope="s"><el-input v-model="actual[s.row.key]" :label="s.row.name + '实测值'" type="number" min="0" :max="s.row.max" step="0.0001" :disabled="busy" placeholder="待检测,可留空"></el-input></template></el-table-column>
|
||||
<el-table-column label="偏差(实测−预测)" width="150"><template slot-scope="s">{{signed(s.row.delta)}}</template></el-table-column>
|
||||
<el-table-column label="相对偏差" width="115"><template slot-scope="s">{{s.row.percent === null ? '—' : signed(s.row.percent) + '%'}}</template></el-table-column>
|
||||
</el-table>
|
||||
<p class="forecast-hint">实测值可以分次补录;空白表示未检测,0 表示真实零值。偏差 = 实测值 − 预测值;相对偏差 = 偏差 ÷ |预测值|,预测值为0时不计算相对偏差。</p>
|
||||
<div class="forecast-foot"><el-button type="primary" :loading="busy" @click="save">保存本周期实测值</el-button></div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script src="__CDN__/assets/element-ui-2.15.14/js/vue.js"></script>
|
||||
<script src="__CDN__/assets/element-ui-2.15.14/js/index.js"></script>
|
||||
@@ -87,6 +87,11 @@
|
||||
<div id="vue" v-cloak>
|
||||
<div class="screen-container">
|
||||
<div class="screen-container-show">
|
||||
<div class="screen-container-right display-flex" style="margin-right: 12px">
|
||||
<el-select v-model="search.site" @change="siteChanged" clearable size="small" placeholder="全部库区" aria-label="筛选库区" style="width: 150px">
|
||||
<el-option v-for="site in siteOptions" :key="site.id" :value="site.id" :label="site.name"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="screen-container-left display-flex">
|
||||
<el-button size="small" @click="refreshPage" icon="el-icon-refresh" circle type="primary"></el-button>
|
||||
<div class="datetime">
|
||||
@@ -202,6 +207,7 @@
|
||||
</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="site" label="所属库区" width="120" align="center"><template slot-scope="s"><el-tag :type="s.row.site === 'xishui' ? 'warning' : 'primary'" size="small">{{s.row.site === 'xishui' ? '习水库' : '遵义中心库'}}</el-tag></template></el-table-column>
|
||||
<el-table-column prop="storage" width="270" label="仓库储存点" show-overflow-tooltip
|
||||
align="center"></el-table-column>
|
||||
<el-table-column prop="num" width="130" label="仓号" show-overflow-tooltip
|
||||
@@ -209,7 +215,7 @@
|
||||
<el-table-column prop="granary_type" label="仓型" show-overflow-tooltip
|
||||
align="center">
|
||||
<template scope="scope">
|
||||
<span v-if="scope.row.granary_type == 1">圆型</span>
|
||||
<span v-if="scope.row.granary_type == 1">立式油罐</span>
|
||||
<span v-else-if="scope.row.granary_type == 3">浅圆仓</span>
|
||||
<span v-else>平房仓</span>
|
||||
</template>
|
||||
@@ -257,9 +263,14 @@
|
||||
</a>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属库区:" prop="site">
|
||||
<el-select v-model="formData.site" @change="changeSite" placeholder="请选择所属库区" style="width: 330px">
|
||||
<el-option v-for="site in siteOptions" :key="site.id" :value="site.id" :label="site.name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="仓库储存点:" prop="storage">
|
||||
<el-input placeholder="请您输入仓库储存点" style="width: 330px;" maxlength="100" show-word-limit
|
||||
v-model="formData.storage"></el-input>
|
||||
v-model="formData.storage" readonly></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="仓号:" prop="num">
|
||||
<el-select @change="handleSelectNum" style="width: 330px;" v-model="formData.num" filterable allow-create default-first-option clearable
|
||||
@@ -272,7 +283,7 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="大屏建筑位置:">
|
||||
<el-form-item v-if="formData.site === 'center'" label="大屏建筑位置:">
|
||||
<el-select @change="changeScreenPosition" v-model="formData.screenPosition" style="width: 440px;">
|
||||
<el-option label="保留现有建筑位置" value=""></el-option>
|
||||
<el-option label="中心库 · 左上新增仓库(42号仓左侧)" value="center_upper_left"></el-option>
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
<link rel="stylesheet" href="__CDN__/assets/element-ui-2.15.14/css/index.css">
|
||||
<link href="/assets/css/sweetalert.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="__CDN__/assets/css/vvv.css">
|
||||
<style>
|
||||
.quality-detail-page {
|
||||
padding: 16px;
|
||||
background: #f4f6f9;
|
||||
min-height: calc(100vh - 40px);
|
||||
}
|
||||
.page-header-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: #fff;
|
||||
padding: 14px 20px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.page-header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
.page-header-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
.page-body-card {
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 16px;
|
||||
padding: 14px 18px;
|
||||
background: #fafafa;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.info-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
.info-label {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
.info-value {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
.quality-rule-ranges {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="vue" v-cloak class="quality-detail-page">
|
||||
<div class="page-header-card">
|
||||
<div class="page-header-left">
|
||||
<el-button size="small" icon="el-icon-back" @click="goBack">返回列表</el-button>
|
||||
<span class="page-header-title">质检报告详情</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-button size="small" type="primary" icon="el-icon-edit" @click="toEdit">编辑此报告</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body-card">
|
||||
<div class="info-grid">
|
||||
<div class="info-item">
|
||||
<span class="info-label">所属库区</span>
|
||||
<span class="info-value">{{ granarySiteName }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">所属仓库</span>
|
||||
<span class="info-value">{{ item.granary ? item.granary.name : '-' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">品种类型</span>
|
||||
<span class="info-value">
|
||||
<span v-if="item.type == 'rapeseed'">菜籽油</span>
|
||||
<span v-else-if="item.type == 'bean'">大豆油</span>
|
||||
<span v-else-if="item.type == 'wheat'">小麦</span>
|
||||
<span v-else-if="item.type == 'paddy'">稻谷</span>
|
||||
<span v-else-if="item.type == 'corn'">玉米</span>
|
||||
<span v-else>{{ item.type }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">记录日期</span>
|
||||
<span class="info-value">{{ item.year }}-{{ item.month < 10 ? '0' + parseInt(item.month) : item.month }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">季节</span>
|
||||
<span class="info-value">
|
||||
<el-tag size="small" type="info">{{ item.season == 1 ? '春季' : item.season == 2 ? '秋季' : '满仓' }}</el-tag>
|
||||
</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">排序</span>
|
||||
<span class="info-value">{{ item.sort }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-label">数据来源</span>
|
||||
<span class="info-value">
|
||||
<el-tag :type="Number(item.is_demo) === 1 ? 'warning' : 'success'" size="small">
|
||||
{{ Number(item.is_demo) === 1 ? 'DEMO 演示' : '后台录入' }}
|
||||
</el-tag>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 style="margin: 20px 0 12px 0; color: #303133;">检测参数清单</h4>
|
||||
<el-table :data="item.testing_params" border highlight-current-row style="width: 100%;">
|
||||
<el-table-column prop="num" width="60" label="序号" align="center"></el-table-column>
|
||||
<el-table-column prop="name" min-width="150" label="检测项目" align="center"></el-table-column>
|
||||
<el-table-column prop="unit" width="120" label="单位" align="center"></el-table-column>
|
||||
<el-table-column prop="val" width="150" label="实测值" align="center">
|
||||
<template scope="scope">
|
||||
<strong>{{ scope.row.val }}</strong>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="warning" width="140" label="预警值" align="center"></el-table-column>
|
||||
<el-table-column prop="alert" width="140" label="警告值" align="center"></el-table-column>
|
||||
<el-table-column prop="is_number" width="110" label="大屏显示" align="center">
|
||||
<template scope="scope">
|
||||
<el-tag size="mini" v-if="scope.row.is_number == 1" type="success">显示</el-tag>
|
||||
<el-tag size="mini" v-else type="info">隐藏</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column min-width="260" label="指标偏好与颜色规则" align="left">
|
||||
<template scope="scope">
|
||||
<template v-if="isNumericRule(scope.row)">
|
||||
<div style="font-weight: 500; margin-bottom: 4px;">{{ ruleDirection(scope.row) === 'lower' ? '● 越大越好' : '● 越小越好' }}</div>
|
||||
<div class="quality-rule-ranges">
|
||||
<span style="color: #16844a;">绿 · {{ ruleRanges(scope.row)[0] }}</span>
|
||||
<span style="color: #946200;">黄 · {{ ruleRanges(scope.row)[1] }}</span>
|
||||
<span style="color: #c0392b;">红 · {{ ruleRanges(scope.row)[2] }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<span v-else style="color: #909399;">文字指标,按检测结果判定</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="__CDN__/assets/element-ui-2.15.14/js/vue.js"></script>
|
||||
<script src="__CDN__/assets/element-ui-2.15.14/js/index.js"></script>
|
||||
<script src="__CDN__/assets/js/jquery-2.1.1.min.js"></script>
|
||||
|
||||
<script>
|
||||
var SERVER_DATA = {
|
||||
item: {:json_encode($item, JSON_UNESCAPED_UNICODE)},
|
||||
siteOptions: {:json_encode($siteOptions, JSON_UNESCAPED_UNICODE)}
|
||||
};
|
||||
|
||||
new Vue({
|
||||
el: '#vue',
|
||||
data: function () {
|
||||
return {
|
||||
item: SERVER_DATA.item || {},
|
||||
siteOptions: SERVER_DATA.siteOptions || []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
granarySiteName: function () {
|
||||
var siteId = this.item && this.item.granary ? this.item.granary.site : '';
|
||||
var found = this.siteOptions.find(function (s) { return s.id === siteId; });
|
||||
return found ? found.name : (siteId || '-');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isRuleNumber: function (val) {
|
||||
return (typeof val === 'string' || typeof val === 'number')
|
||||
&& /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/.test(String(val).trim())
|
||||
&& Number.isFinite(Number(val));
|
||||
},
|
||||
isNumericRule: function (item) {
|
||||
return this.isRuleNumber(item.warning) && this.isRuleNumber(item.alert);
|
||||
},
|
||||
ruleDirection: function (item) {
|
||||
if (item.direction === 'upper' || item.direction === 'lower') return item.direction;
|
||||
return (this.isNumericRule(item) && Number(item.warning) > Number(item.alert)) ? 'lower' : 'upper';
|
||||
},
|
||||
ruleRanges: function (item) {
|
||||
var w = item.warning, a = item.alert;
|
||||
return this.ruleDirection(item) === 'upper'
|
||||
? ['当前值 ≤ ' + w, w + ' < 当前值 ≤ ' + a, '当前值 > ' + a]
|
||||
: ['当前值 ≥ ' + w, a + ' ≤ 当前值 < ' + w, '当前值 < ' + a];
|
||||
},
|
||||
goBack: function () {
|
||||
if (typeof top !== 'undefined' && top && top.Backend && top.Backend.api && top.Backend.api.closetabs) {
|
||||
var currentNav = top.$("#nav ul.nav-tabs li.active");
|
||||
if (currentNav.length > 0) {
|
||||
currentNav.find(".close-tab").trigger("click");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (window.history.length > 1) {
|
||||
window.history.back();
|
||||
} else {
|
||||
window.location.href = 'testing/index';
|
||||
}
|
||||
},
|
||||
toEdit: function () {
|
||||
var url = 'testing/edit?ids=' + this.item.id;
|
||||
var title = '编辑检测报告';
|
||||
if (typeof top !== 'undefined' && top && top.Backend && top.Backend.api && typeof top.Backend.api.addtabs === 'function') {
|
||||
top.Backend.api.addtabs(url, title);
|
||||
} else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,457 @@
|
||||
<link rel="stylesheet" href="__CDN__/assets/element-ui-2.15.14/css/index.css">
|
||||
<link href="/assets/css/sweetalert.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="__CDN__/assets/css/vvv.css">
|
||||
<style>
|
||||
.quality-edit-page {
|
||||
padding: 16px;
|
||||
background: #f4f6f9;
|
||||
min-height: calc(100vh - 40px);
|
||||
}
|
||||
.page-header-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: #fff;
|
||||
padding: 14px 20px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.page-header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
.page-header-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
.page-body-card {
|
||||
background: #fff;
|
||||
padding: 24px 24px 80px 24px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 4px rgba(0,21,41,.08);
|
||||
}
|
||||
.quality-editor-card {
|
||||
padding: 14px 16px 10px;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
margin-top: 6px;
|
||||
}
|
||||
.quality-editor-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin-bottom: 12px;
|
||||
padding: 10px 14px;
|
||||
border-radius: 6px;
|
||||
background: #f0f9ff;
|
||||
color: #5f6b7a;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.quality-legend {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.quality-legend span {
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.quality-legend .good { background: #eaf8f0; color: #16844a; }
|
||||
.quality-legend .warn { background: #fef7e7; color: #946200; }
|
||||
.quality-legend .bad { background: #fdeeee; color: #c0392b; }
|
||||
.quality-rule-ranges {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.quality-direction-help {
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
.page-footer-bar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #fff;
|
||||
padding: 12px 30px;
|
||||
border-top: 1px solid #e4e7ed;
|
||||
box-shadow: 0 -3px 10px rgba(0, 0, 0, .05);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
z-index: 100;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="vue" v-cloak class="quality-edit-page">
|
||||
<div class="page-header-card">
|
||||
<div class="page-header-left">
|
||||
<el-button size="small" icon="el-icon-back" @click="goBack">返回列表</el-button>
|
||||
<span class="page-header-title">{{ formData.id ? '编辑检测报告' : '添加检测报告' }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-button size="small" type="primary" :loading="submitting" icon="el-icon-check" @click="submit">保存提交</el-button>
|
||||
<el-button size="small" @click="goBack">取消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-body-card">
|
||||
<el-form ref="form" :rules="rules" :model="formData" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="所属库区:" required>
|
||||
<el-select v-model="formSite" @change="formSiteChanged" placeholder="请选择库区" style="width: 100%;">
|
||||
<el-option v-for="site in siteOptions" :key="site.id" :value="site.id" :label="site.name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="所属仓库:" prop="gid">
|
||||
<el-select @change="handleGranaryChange" style="width: 100%;" v-model="formData.gid" filterable clearable placeholder="请选择所属仓库">
|
||||
<el-option v-for="item in siteGranaries" :key="item.id" :label="granaryLabel(item)" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="品种类型:">
|
||||
<el-tag type="info" size="medium">{{ typeName || '随仓库自动匹配' }}</el-tag>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="记录日期:" prop="record_date">
|
||||
<el-date-picker style="width: 100%;" value-format="yyyy-MM" v-model="formData.record_date" type="month" placeholder="请选择记录日期"></el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="季节:" prop="season">
|
||||
<el-radio-group v-model="formData.season" size="small">
|
||||
<el-radio-button :label="1">春季</el-radio-button>
|
||||
<el-radio-button :label="2">秋季</el-radio-button>
|
||||
<el-radio-button :label="3">满仓</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8">
|
||||
<el-form-item label="排序:" prop="sort">
|
||||
<el-input type="number" placeholder="排序序号" style="width: 100%;" v-model="formData.sort"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="检测参数:" required style="margin-top: 10px;">
|
||||
<div class="quality-editor-card">
|
||||
<div class="quality-editor-toolbar">
|
||||
<div><strong>录入提示:</strong>先填实测值、预警值和警告值,再选择指标偏好。大屏显示列可开启或关闭该参数在大屏上的展示。等于阈值时归入较低一级。</div>
|
||||
<div class="quality-legend" aria-label="颜色规则">
|
||||
<span class="good">绿 · 达标</span>
|
||||
<span class="warn">黄 · 预警</span>
|
||||
<span class="bad">红 · 警告</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table :data="currentParams" border highlight-current-row style="width: 100%;">
|
||||
<el-table-column prop="num" width="60" label="序号" align="center"></el-table-column>
|
||||
<el-table-column prop="name" min-width="150" label="检测项目" align="center"></el-table-column>
|
||||
<el-table-column prop="unit" width="120" label="单位" align="center">
|
||||
<template scope="scope">
|
||||
<el-input style="width: 95px;" placeholder="单位" size="small" maxlength="15" v-model="scope.row.unit"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="val" width="140" label="值" align="center">
|
||||
<template scope="scope">
|
||||
<el-input style="width: 115px;" placeholder="输入检测值" size="small" maxlength="50" v-model="scope.row.val"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="warning" width="140" label="预警值" align="center">
|
||||
<template scope="scope">
|
||||
<el-input style="width: 115px;" placeholder="输入预警值" size="small" maxlength="50" v-model="scope.row.warning"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="alert" width="140" label="警告值" align="center">
|
||||
<template scope="scope">
|
||||
<el-input style="width: 115px;" placeholder="输入警告值" size="small" maxlength="50" v-model="scope.row.alert"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="is_number" width="110" label="大屏显示" align="center">
|
||||
<template scope="scope">
|
||||
<el-button @click="handelIsNumber(scope.$index, 2)" size="mini" v-if="scope.row.is_number == 1" type="success" icon="el-icon-check">显示</el-button>
|
||||
<el-button @click="handelIsNumber(scope.$index, 1)" size="mini" v-else type="warning" icon="el-icon-close">隐藏</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="280" label="指标偏好与颜色规则" align="left">
|
||||
<template scope="scope">
|
||||
<template v-if="isNumericRule(scope.row)">
|
||||
<el-button-group class="quality-direction-toggle" :aria-label="'选择' + scope.row.name + '的指标偏好'">
|
||||
<el-button size="mini" :type="ruleDirection(scope.row) === 'lower' ? 'success' : 'info'"
|
||||
:plain="ruleDirection(scope.row) !== 'lower'"
|
||||
@click="setRuleDirection(scope.row, 'lower')">越大越好</el-button>
|
||||
<el-button size="mini" :type="ruleDirection(scope.row) === 'upper' ? 'success' : 'info'"
|
||||
:plain="ruleDirection(scope.row) !== 'upper'"
|
||||
@click="setRuleDirection(scope.row, 'upper')">越小越好</el-button>
|
||||
</el-button-group>
|
||||
<div v-if="ruleError(scope.row)" style="color: #c0392b; margin-top: 6px;">{{ruleError(scope.row)}}</div>
|
||||
<div v-else class="quality-rule-ranges">
|
||||
<span style="color: #16844a;">绿 {{ruleRanges(scope.row)[0]}}</span>
|
||||
<span style="color: #946200;">黄 {{ruleRanges(scope.row)[1]}}</span>
|
||||
<span style="color: #c0392b;">红 {{ruleRanges(scope.row)[2]}}</span>
|
||||
</div>
|
||||
</template>
|
||||
<span v-else-if="ruleError(scope.row)" style="color: #c0392b;">{{ruleError(scope.row)}}</span>
|
||||
<span v-else>文字指标,按检测结果判定</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="quality-direction-help">“越大越好”:低于预警值会触发风险;“越小越好”:高于预警值会触发风险。文字指标按检测结果判定。</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="page-footer-bar">
|
||||
<el-button @click="goBack" icon="el-icon-close">返回列表</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="submit" icon="el-icon-check">保存提交</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="__CDN__/assets/element-ui-2.15.14/js/vue.js"></script>
|
||||
<script src="__CDN__/assets/element-ui-2.15.14/js/index.js"></script>
|
||||
<script src="/assets/js/sweetalert.min.js"></script>
|
||||
<script src="__CDN__/assets/js/jquery-2.1.1.min.js"></script>
|
||||
|
||||
<script>
|
||||
var SERVER_DATA = {
|
||||
item: {:json_encode($item, JSON_UNESCAPED_UNICODE)},
|
||||
granaryList: {:json_encode($granaryList, JSON_UNESCAPED_UNICODE)},
|
||||
typeList: {:json_encode($typeList, JSON_UNESCAPED_UNICODE)},
|
||||
siteOptions: {:json_encode($siteOptions, JSON_UNESCAPED_UNICODE)}
|
||||
};
|
||||
|
||||
new Vue({
|
||||
el: '#vue',
|
||||
data: function () {
|
||||
var rawItem = SERVER_DATA.item;
|
||||
var granaryList = SERVER_DATA.granaryList || [];
|
||||
var typeList = SERVER_DATA.typeList || {};
|
||||
var siteOptions = SERVER_DATA.siteOptions || [];
|
||||
|
||||
var formSite = '';
|
||||
var formData = {
|
||||
id: 0,
|
||||
gid: '',
|
||||
type: 'rapeseed',
|
||||
record_date: '',
|
||||
season: 1,
|
||||
sort: '',
|
||||
content: []
|
||||
};
|
||||
var typeName = '';
|
||||
|
||||
if (rawItem) {
|
||||
formSite = (rawItem.granary && rawItem.granary.site) ? rawItem.granary.site : ((siteOptions[0] || {}).id || '');
|
||||
formData = {
|
||||
id: rawItem.id,
|
||||
gid: rawItem.gid,
|
||||
type: rawItem.type,
|
||||
season: rawItem.season,
|
||||
record_date: rawItem.year + '-' + (rawItem.month < 10 ? '0' + parseInt(rawItem.month) : rawItem.month),
|
||||
sort: rawItem.sort,
|
||||
content: []
|
||||
};
|
||||
typeName = (rawItem.granary && rawItem.granary.varieties) ? rawItem.granary.varieties : '';
|
||||
if (typeList[rawItem.type]) {
|
||||
typeList[rawItem.type]['content'] = JSON.parse(JSON.stringify(rawItem.testing_params || []));
|
||||
}
|
||||
} else {
|
||||
formSite = (siteOptions[0] || {}).id || '';
|
||||
}
|
||||
|
||||
return {
|
||||
siteOptions: siteOptions,
|
||||
granaryList: granaryList,
|
||||
typeList: typeList,
|
||||
formSite: formSite,
|
||||
typeName: typeName,
|
||||
formData: formData,
|
||||
submitting: false,
|
||||
rules: {
|
||||
gid: [{ required: true, message: '请选择所属仓库', trigger: 'blur' }],
|
||||
record_date: [{ required: true, message: '请选择记录日期', trigger: 'blur' }]
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
siteGranaries: function () {
|
||||
var self = this;
|
||||
if (!self.formSite) return self.granaryList;
|
||||
return self.granaryList.filter(function (item) {
|
||||
return item.site === self.formSite;
|
||||
});
|
||||
},
|
||||
currentParams: function () {
|
||||
var group = this.typeList[this.formData.type];
|
||||
return group ? group.content : [];
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
if (!this.formData.id && this.siteGranaries.length > 0) {
|
||||
var first = this.siteGranaries[0];
|
||||
this.formData.gid = first.id;
|
||||
this.handleGranaryChange(first.id);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
granaryLabel: function (item) {
|
||||
return (item.site_name ? item.site_name + ' · ' : '') + item.name + (item.varieties ? ' (' + item.varieties + ')' : '');
|
||||
},
|
||||
formSiteChanged: function () {
|
||||
var valid = this.siteGranaries.some(function (g) { return g.id === this.formData.gid; }.bind(this));
|
||||
if (!valid && this.siteGranaries.length > 0) {
|
||||
this.formData.gid = this.siteGranaries[0].id;
|
||||
this.handleGranaryChange(this.formData.gid);
|
||||
} else if (this.siteGranaries.length === 0) {
|
||||
this.formData.gid = '';
|
||||
this.typeName = '';
|
||||
}
|
||||
},
|
||||
handleGranaryChange: function (gid) {
|
||||
var item = this.granaryList.find(function (v) { return v.id === gid; });
|
||||
if (!item) return;
|
||||
this.typeName = item.varieties || '';
|
||||
this.formData.type = item.type || 'rapeseed';
|
||||
},
|
||||
handelIsNumber: function (index, val) {
|
||||
var params = this.currentParams;
|
||||
if (params && params[index]) {
|
||||
this.$set(params[index], 'is_number', val);
|
||||
}
|
||||
},
|
||||
isRuleNumber: function (val) {
|
||||
return (typeof val === 'string' || typeof val === 'number')
|
||||
&& /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/.test(String(val).trim())
|
||||
&& Number.isFinite(Number(val));
|
||||
},
|
||||
isNumericRule: function (item) {
|
||||
return this.isRuleNumber(item.warning) && this.isRuleNumber(item.alert);
|
||||
},
|
||||
ruleDirection: function (item) {
|
||||
if (item.direction === 'upper' || item.direction === 'lower') return item.direction;
|
||||
return (this.isNumericRule(item) && Number(item.warning) > Number(item.alert)) ? 'lower' : 'upper';
|
||||
},
|
||||
setRuleDirection: function (item, dir) {
|
||||
this.$set(item, 'direction', dir);
|
||||
},
|
||||
ruleRanges: function (item) {
|
||||
var w = item.warning, a = item.alert;
|
||||
return this.ruleDirection(item) === 'upper'
|
||||
? ['当前值 ≤ ' + w, w + ' < 当前值 ≤ ' + a, '当前值 > ' + a]
|
||||
: ['当前值 ≥ ' + w, a + ' ≤ 当前值 < ' + w, '当前值 < ' + a];
|
||||
},
|
||||
ruleError: function (item) {
|
||||
var expectsNumeric = item.rule_numeric === true || Number(item.is_number) === 1
|
||||
|| this.isRuleNumber(item.warning) || this.isRuleNumber(item.alert);
|
||||
if (expectsNumeric && !this.isNumericRule(item)) return '预警值和警告值必须都是有限数字';
|
||||
if (!this.isNumericRule(item)) return '';
|
||||
if (!this.isRuleNumber(item.val)
|
||||
&& !/^(?:\/|--?|未检测|未提供|暂无|未检出|未检出\s*ND|ND)$/i.test(String(item.val ?? '').trim())) {
|
||||
return '检测值必须是有限数字,缺测可填 /';
|
||||
}
|
||||
var upper = this.ruleDirection(item) === 'upper';
|
||||
return (upper && Number(item.warning) > Number(item.alert)) || (!upper && Number(item.warning) < Number(item.alert))
|
||||
? (upper ? '越小越好指标要求:预警值 ≤ 警告值(高值预警)' : '越大越好指标要求:预警值 ≥ 警告值(低值预警)') : '';
|
||||
},
|
||||
goBack: function (refresh) {
|
||||
if (typeof top !== 'undefined' && top && top.Backend && top.Backend.api && top.Backend.api.closetabs) {
|
||||
if (refresh && top.$) {
|
||||
var listIframe = top.$('.tab-pane iframe[src*="testing/index"], .tab-pane iframe[src*="testing"]');
|
||||
if (listIframe.length && listIframe[0].contentWindow && listIframe[0].contentWindow.location) {
|
||||
listIframe[0].contentWindow.location.reload();
|
||||
}
|
||||
}
|
||||
var currentNav = top.$("#nav ul.nav-tabs li.active");
|
||||
if (currentNav.length > 0) {
|
||||
currentNav.find(".close-tab").trigger("click");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (window.history.length > 1) {
|
||||
window.history.back();
|
||||
} else {
|
||||
window.location.href = 'testing/index';
|
||||
}
|
||||
},
|
||||
submit: function () {
|
||||
var self = this;
|
||||
self.$refs.form.validate(function (valid) {
|
||||
if (!valid) return false;
|
||||
var content = self.currentParams;
|
||||
for (var i = 0; i < content.length; i++) {
|
||||
var p = content[i];
|
||||
var err = self.ruleError(p);
|
||||
if (err) {
|
||||
swal({ title: '温馨提示', text: p.name + ':' + err, type: 'warning' });
|
||||
return false;
|
||||
}
|
||||
self.$set(p, 'direction', self.ruleDirection(p));
|
||||
if (p.val === '' || p.val === null || p.val === undefined) {
|
||||
swal({ title: '温馨提示', text: '请您输入' + p.name + '值', type: 'warning' });
|
||||
return false;
|
||||
}
|
||||
if (p.warning === '') {
|
||||
swal({ title: '温馨提示', text: '请您输入' + p.name + '预警值', type: 'warning' });
|
||||
return false;
|
||||
}
|
||||
if (p.alert === '') {
|
||||
swal({ title: '温馨提示', text: '请您输入' + p.name + '警告值', type: 'warning' });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
self.formData.content = content;
|
||||
self.submitting = true;
|
||||
|
||||
$.ajax({
|
||||
url: 'testing/add',
|
||||
type: 'POST',
|
||||
data: self.formData,
|
||||
dataType: 'json',
|
||||
success: function (res) {
|
||||
self.submitting = false;
|
||||
if (res.code === 200) {
|
||||
swal({
|
||||
title: '保存成功',
|
||||
text: res.msg || '质检报告已成功保存',
|
||||
type: 'success',
|
||||
confirmButtonColor: '#7367f0',
|
||||
confirmButtonText: '确定'
|
||||
}, function () {
|
||||
self.goBack(true);
|
||||
});
|
||||
} else {
|
||||
swal({ title: '保存失败', text: res.msg, type: 'error' });
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
self.submitting = false;
|
||||
swal({ title: '网络错误', text: '提交失败,请稍后重试', type: 'error' });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -231,8 +231,7 @@
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="search-select screen-container-right display-flex keyword">
|
||||
<el-button @click="openAddDialog('add', '')" size="small" type="primary" plain icon="el-icon-plus">添加
|
||||
</el-button>
|
||||
<a href="testing/add" @click.prevent="openAddPage" class="el-button el-button--primary el-button--small is-plain btn-addtabs" title="添加检测报告"><i class="el-icon-plus"></i><span>添加</span></a>
|
||||
<el-button @click="del" size="small" type="danger" plain icon="el-icon-delete">删除
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -275,12 +274,12 @@
|
||||
align="center"></el-table-column>
|
||||
<el-table-column align="center" width="320" fixed="right" label="操作">
|
||||
<template scope="scope">
|
||||
<button @click="openAddDialog('edit', scope.row)" type="button"
|
||||
class="el-button el-button--primary el-button--small"><i
|
||||
class="el-icon-edit"></i><span>编辑</span></button>
|
||||
<button @click="openDialogDetail(scope.row)" type="button"
|
||||
class="el-button el-button--success el-button--small"><i
|
||||
class="el-icon-tickets"></i><span>详情</span></button>
|
||||
<a :href="'testing/edit?ids=' + scope.row.id" @click.prevent="openEditPage(scope.row)"
|
||||
class="el-button el-button--primary el-button--small btn-addtabs" title="编辑检测报告"><i
|
||||
class="el-icon-edit"></i><span>编辑</span></a>
|
||||
<a :href="'testing/detail?ids=' + scope.row.id" @click.prevent="openDetailPage(scope.row)"
|
||||
class="el-button el-button--success el-button--small btn-addtabs" title="检测报告详情"><i
|
||||
class="el-icon-tickets"></i><span>详情</span></a>
|
||||
<button @click="dell(scope.row.id)" type="button"
|
||||
class="el-button el-button--danger el-button--small"><i
|
||||
class="el-icon-delete"></i><span>删除</span></button>
|
||||
|
||||
在新工单中引用
屏蔽一个用户