feat(forecast): 支持温湿度预测记录编辑与删除,修复组件调用并级联清理周期数据
这个提交包含在:
@@ -33,29 +33,29 @@ class Forecast extends GranaryBackend
|
||||
}
|
||||
}
|
||||
unset($row);
|
||||
$granaries = array_values(array_filter(GranarySite::granaries(->filterSites), function () { return in_array(['varieties'], ['小麦', '稻谷'], true); }));
|
||||
if (!empty()) {
|
||||
= array_column(, 'id');
|
||||
= Db::name('grain_forecast')->where('gid', 'in', )
|
||||
$granaries = array_values(array_filter(GranarySite::granaries($this->filterSites), function ($g) { return in_array($g['varieties'], ['小麦', '稻谷'], true); }));
|
||||
if (!empty($granaries)) {
|
||||
$gids = array_column($granaries, 'id');
|
||||
$envRecords = Db::name('grain_forecast')->where('gid', 'in', $gids)
|
||||
->field('gid,tm_i,hm_i,tm_o,hm_o,observed_date')->order('id DESC')->select();
|
||||
= [];
|
||||
foreach ( as ) {
|
||||
if (!isset([['gid']])) {
|
||||
[['gid']] = [
|
||||
'tm_i' => (float)['tm_i'],
|
||||
'hm_i' => (float)['hm_i'],
|
||||
'tm_o' => (float)['tm_o'],
|
||||
'hm_o' => (float)['hm_o'],
|
||||
'observed_date' => ['observed_date']
|
||||
$envMap = [];
|
||||
foreach ($envRecords as $rec) {
|
||||
if (!isset($envMap[$rec['gid']])) {
|
||||
$envMap[$rec['gid']] = [
|
||||
'tm_i' => (float)$rec['tm_i'],
|
||||
'hm_i' => (float)$rec['hm_i'],
|
||||
'tm_o' => (float)$rec['tm_o'],
|
||||
'hm_o' => (float)$rec['hm_o'],
|
||||
'observed_date' => $rec['observed_date']
|
||||
];
|
||||
}
|
||||
}
|
||||
foreach ( as &) {
|
||||
['last_env'] = isset([['id']]) ? [['id']] : null;
|
||||
foreach ($granaries as &$g) {
|
||||
$g['last_env'] = isset($envMap[$g['id']]) ? $envMap[$g['id']] : null;
|
||||
}
|
||||
unset();
|
||||
unset($g);
|
||||
}
|
||||
return json(['code' => 200, 'list' => , 'total' => , 'granaries' => ]);
|
||||
return json(['code' => 200, 'list' => $list, 'total' => $total, 'granaries' => $granaries]);
|
||||
}
|
||||
|
||||
public function detail()
|
||||
@@ -76,6 +76,38 @@ class Forecast extends GranaryBackend
|
||||
});
|
||||
}
|
||||
|
||||
public function edit($ids = null)
|
||||
{
|
||||
return $this->write(function ($service) use ($ids) {
|
||||
$id = $this->request->post('id/d', $ids ?: 0);
|
||||
$id = $service->update($id, $this->request->post(), $this->auth->id);
|
||||
$service->generate($id);
|
||||
return $id;
|
||||
});
|
||||
}
|
||||
|
||||
public function dell($ids = null)
|
||||
{
|
||||
if (!$this->request->isPost()) return json(['code' => 405, 'msg' => '请使用POST提交']);
|
||||
$id = $this->request->post('id', $ids ?: $this->request->get('id'));
|
||||
if (empty($id)) return json(['code' => 400, 'msg' => '请指定要删除的记录编号']);
|
||||
try {
|
||||
$service = new GrainForecast();
|
||||
$service->delete($id);
|
||||
return json(['code' => 200, 'msg' => '删除成功']);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return json(['code' => 400, 'msg' => $e->getMessage()]);
|
||||
} catch (\Exception $e) {
|
||||
\think\Log::record('Grain forecast delete: ' . $e->getMessage(), 'error');
|
||||
return json(['code' => 500, 'msg' => '删除失败,请刷新后重试']);
|
||||
}
|
||||
}
|
||||
|
||||
public function del($ids = null)
|
||||
{
|
||||
return $this->dell($ids);
|
||||
}
|
||||
|
||||
public function retry()
|
||||
{
|
||||
return $this->write(function ($service) {
|
||||
|
||||
@@ -27,11 +27,14 @@
|
||||
<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>
|
||||
<forecast-list :rows="rows" :loading="loading" @open="openRecord" @edit="editRecord" @delete="deleteRecord"></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="editing" width="760px" :close-on-click-modal="false" :before-close="closeEdit" :show-close="!saving">
|
||||
<forecast-create v-if="editing && editData" ref="edit" :granaries="granaries" :busy="saving" :initial-data="editData" :is-edit="true" @submit="updateRecord" @cancel="closeEdit"></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>
|
||||
@@ -55,7 +58,13 @@
|
||||
<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-column label="操作" width="220" fixed="right">
|
||||
<template slot-scope="s">
|
||||
<el-button type="text" size="small" @click="$emit('open', s.row.id)">查看 / 补录实测</el-button>
|
||||
<el-button type="text" size="small" @click="$emit('edit', s.row)">编辑</el-button>
|
||||
<el-button type="text" size="small" style="color: #F56C6C;" @click="$emit('delete', s.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</script>
|
||||
|
||||
@@ -97,7 +106,10 @@
|
||||
</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>
|
||||
<div class="forecast-foot">
|
||||
<el-button :disabled="busy" @click="$emit('cancel')">取消</el-button>
|
||||
<el-button type="primary" :loading="busy" @click="submit">{{ isEdit ? '保存修改并重新生成预测' : '保存并生成预测' }}</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
/**
|
||||
* 粮食质量智能预测API控制器 (原生支持 /api/forecast 路径)
|
||||
*/
|
||||
class Forecast extends Index
|
||||
{
|
||||
protected $noNeedLogin = ['*'];
|
||||
protected $noNeedRight = ['*'];
|
||||
|
||||
/**
|
||||
* 预测接口默认动作 (直接路由至 Index::forecast)
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return $this->forecast();
|
||||
}
|
||||
}
|
||||
@@ -265,10 +265,10 @@ class Index extends Api
|
||||
*/
|
||||
public function env()
|
||||
{
|
||||
= ->request->get('site', 'center');
|
||||
if (!GranarySite::valid()) ->error('无效库区');
|
||||
$site = $this->request->get('site', 'center');
|
||||
if (!GranarySite::valid($site)) $this->error('无效库区');
|
||||
|
||||
= [
|
||||
$envData = [
|
||||
'center' => [
|
||||
'site' => 'center',
|
||||
'name' => '遵义直属库中心库区',
|
||||
@@ -291,29 +291,29 @@ class Index extends Api
|
||||
]
|
||||
];
|
||||
|
||||
= isset([]) ? [] : ['center'];
|
||||
$data = isset($envData[$site]) ? $envData[$site] : $envData['center'];
|
||||
|
||||
// 优先读取该库区最新一条人工录入或设定的温湿度快照
|
||||
try {
|
||||
= Db::name('grain_forecast')
|
||||
$latestRecord = Db::name('grain_forecast')
|
||||
->alias('f')
|
||||
->join('granary g', 'f.gid = g.id')
|
||||
->where('g.site', )
|
||||
->where('g.site', $site)
|
||||
->order('f.id DESC')
|
||||
->field('f.tm_i, f.hm_i, f.tm_o, f.hm_o, f.update_time')
|
||||
->find();
|
||||
if () {
|
||||
['tm_i'] = (float)['tm_i'];
|
||||
['hm_i'] = (float)['hm_i'];
|
||||
['tm_o'] = (float)['tm_o'];
|
||||
['hm_o'] = (float)['hm_o'];
|
||||
['update_time'] = (int)['update_time'];
|
||||
if ($latestRecord) {
|
||||
$data['tm_i'] = (float)$latestRecord['tm_i'];
|
||||
$data['hm_i'] = (float)$latestRecord['hm_i'];
|
||||
$data['tm_o'] = (float)$latestRecord['tm_o'];
|
||||
$data['hm_o'] = (float)$latestRecord['hm_o'];
|
||||
$data['update_time'] = (int)$latestRecord['update_time'];
|
||||
}
|
||||
} catch (\Exception ) {
|
||||
} catch (\Exception $e) {
|
||||
// 异常时安全兜底基准工况
|
||||
}
|
||||
|
||||
->success('获取成功', );
|
||||
$this->success('获取成功', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -355,6 +355,7 @@ class Index extends Api
|
||||
|
||||
$remoteData = $this->callRemoteForecast($remoteUrl, [
|
||||
'type' => $grainType,
|
||||
'commodity' => $grainType,
|
||||
'month' => $targetMonth,
|
||||
'day' => $targetDay,
|
||||
'tm_i' => $tm_i,
|
||||
|
||||
@@ -32,7 +32,7 @@ class GranaryBackend extends Backend
|
||||
'granary' => ['index', 'add', 'detail', 'dell'],
|
||||
'testing' => ['index', 'add', 'edit', 'detail', 'sort', 'dell'],
|
||||
'content' => ['index', 'add', 'status', 'getcontent', 'dell'],
|
||||
'forecast' => ['index', 'detail', 'add', 'retry', 'actual'],
|
||||
'forecast' => ['index', 'detail', 'add', 'edit', 'retry', 'actual', 'dell', 'del'],
|
||||
];
|
||||
if (!isset($actions[$controller]) || !in_array($action, $actions[$controller], true)) $this->error('不支持此操作');
|
||||
$table = $controller === 'forecast' ? 'grain_forecast' : $controller;
|
||||
|
||||
@@ -88,7 +88,7 @@ class GrainForecast
|
||||
{
|
||||
$date = new \DateTimeImmutable($point['target_date']);
|
||||
$params = array_intersect_key($record, array_flip(['tm_i', 'tm_o', 'hm_i', 'hm_o']));
|
||||
$params += ['month' => (int)$date->format('n'), 'day' => (int)$date->format('j'), 'type' => $record['grain_type']];
|
||||
$params += ['month' => (int)$date->format('n'), 'day' => (int)$date->format('j'), 'type' => $record['grain_type'], 'commodity' => $record['grain_type']];
|
||||
$url = 'http://www.probe-cdy-pests.cn:8116/alg/grainquality/forcast?' . http_build_query($params);
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => 3, CURLOPT_TIMEOUT => 6,
|
||||
@@ -194,4 +194,103 @@ class GrainForecast
|
||||
if (!$saved) throw new \InvalidArgumentException('实测数据已被其他人更新,请关闭并重新打开后填写');
|
||||
return (int)$point['forecast_id'];
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$ids = is_array($id) ? $id : (strpos((string)$id, ',') !== false ? explode(',', (string)$id) : [(int)$id]);
|
||||
$ids = array_values(array_filter(array_map('intval', $ids)));
|
||||
if (empty($ids)) {
|
||||
throw new \InvalidArgumentException('请选择要删除的记录');
|
||||
}
|
||||
return Db::transaction(function () use ($ids) {
|
||||
Db::name('grain_forecast_point')->where('forecast_id', 'in', $ids)->delete();
|
||||
return Db::name('grain_forecast')->where('id', 'in', $ids)->delete();
|
||||
});
|
||||
}
|
||||
|
||||
public function update($id, array $input, $adminId)
|
||||
{
|
||||
$id = (int)$id;
|
||||
$existing = Db::name('grain_forecast')->where('id', $id)->find();
|
||||
if (!$existing) {
|
||||
throw new \InvalidArgumentException('预测记录不存在');
|
||||
}
|
||||
$gid = isset($input['gid']) && is_scalar($input['gid']) ? (int)$input['gid'] : 0;
|
||||
$granary = Db::name('granary')->where('id', $gid)->find();
|
||||
if (!$granary || !in_array($granary['varieties'], ['小麦', '稻谷'], true)) {
|
||||
throw new \InvalidArgumentException('请选择小麦或稻谷仓库');
|
||||
}
|
||||
$date = self::date(isset($input['observed_date']) ? $input['observed_date'] : '', '温湿度采集日期');
|
||||
$horizons = isset($input['horizons']) ? $input['horizons'] : [];
|
||||
if (!is_array($horizons) || !$horizons || count($horizons) > 4) {
|
||||
throw new \InvalidArgumentException('请选择预测周期');
|
||||
}
|
||||
foreach ($horizons as $day) {
|
||||
if (!is_scalar($day) || !in_array((string)$day, ['7', '15', '30', '60'], true)) {
|
||||
throw new \InvalidArgumentException('预测周期仅支持7、15、30、60天');
|
||||
}
|
||||
}
|
||||
$horizons = array_unique(array_map('intval', $horizons));
|
||||
sort($horizons);
|
||||
|
||||
$grainType = $granary['varieties'] === '小麦' ? 'wheat' : 'rice';
|
||||
$row = [
|
||||
'gid' => $gid,
|
||||
'granary_name' => $granary['name'],
|
||||
'storage' => $granary['storage'],
|
||||
'grain_type' => $grainType,
|
||||
'observed_date' => $date->format('Y-m-d'),
|
||||
'status' => 'pending',
|
||||
'error' => '',
|
||||
'update_time' => time()
|
||||
];
|
||||
foreach (['tm_i' => '仓内温度', 'tm_o' => '仓外温度', 'hm_i' => '仓内湿度', 'hm_o' => '仓外湿度'] as $field => $label) {
|
||||
$isTemp = strpos($field, 'tm_') === 0;
|
||||
$row[$field] = self::number(isset($input[$field]) ? $input[$field] : null, $label, $isTemp ? -50 : 0, $isTemp ? 80 : 100);
|
||||
}
|
||||
|
||||
Db::transaction(function () use ($id, $row, $horizons, $date, $grainType, $existing) {
|
||||
Db::name('grain_forecast')->where('id', $id)->update($row);
|
||||
|
||||
$oldPoints = Db::name('grain_forecast_point')->where('forecast_id', $id)->select();
|
||||
$oldPointsByHorizon = [];
|
||||
foreach ($oldPoints as $op) {
|
||||
$oldPointsByHorizon[(int)$op['horizon']] = $op;
|
||||
}
|
||||
|
||||
$grainTypeChanged = ($existing['grain_type'] !== $grainType);
|
||||
|
||||
foreach ($horizons as $days) {
|
||||
$targetDate = $date->modify('+' . $days . ' days')->format('Y-m-d');
|
||||
if (isset($oldPointsByHorizon[$days]) && !$grainTypeChanged) {
|
||||
Db::name('grain_forecast_point')->where('id', $oldPointsByHorizon[$days]['id'])->update([
|
||||
'target_date' => $targetDate,
|
||||
'predicted' => '{}',
|
||||
'update_time' => time()
|
||||
]);
|
||||
} else {
|
||||
if (isset($oldPointsByHorizon[$days])) {
|
||||
Db::name('grain_forecast_point')->where('id', $oldPointsByHorizon[$days]['id'])->delete();
|
||||
}
|
||||
Db::name('grain_forecast_point')->insert([
|
||||
'forecast_id' => $id,
|
||||
'horizon' => $days,
|
||||
'target_date' => $targetDate,
|
||||
'predicted' => '{}',
|
||||
'actual' => '{}',
|
||||
'version' => 0,
|
||||
'update_time' => time()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($oldPointsByHorizon as $h => $op) {
|
||||
if (!in_array($h, $horizons, true)) {
|
||||
Db::name('grain_forecast_point')->where('id', $op['id'])->delete();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return (int)$id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ define(['jquery', 'bootstrap', 'backend', 'backend/forecast/components'], functi
|
||||
new Vue({
|
||||
el: '#forecast-app',
|
||||
components: {'forecast-list': components.list, 'forecast-create': components.create, 'forecast-detail': components.detail},
|
||||
data: { rows: [], granaries: [], total: 0, page: 1, gid: '', site: '', siteOptions: Config.granarySites || [], loading: false, saving: false, creating: false, viewing: false, selected: null, loadSequence: 0 },
|
||||
data: { rows: [], granaries: [], total: 0, page: 1, gid: '', site: '', siteOptions: Config.granarySites || [], loading: false, saving: false, creating: false, editing: false, editData: null, viewing: false, selected: null, loadSequence: 0 },
|
||||
created: function () { this.load(); },
|
||||
methods: {
|
||||
api: function (action, data, method) {
|
||||
@@ -32,6 +32,25 @@ define(['jquery', 'bootstrap', 'backend', 'backend/forecast/components'], functi
|
||||
changePage: function (page) { this.page = page; this.load(); },
|
||||
newRecord: function () { this.creating = true; },
|
||||
closeCreate: function (done) { if (!this.saving) { this.creating = false; if (typeof done === 'function') done(); } },
|
||||
editRecord: function (row) {
|
||||
var self = this;
|
||||
this.api('detail', {id: row.id}).then(function (res) {
|
||||
var d = res.data;
|
||||
var horizons = (d.points || []).map(function (p) { return Number(p.horizon); });
|
||||
self.editData = {
|
||||
id: d.id,
|
||||
gid: d.gid,
|
||||
observed_date: d.observed_date,
|
||||
horizons: horizons.length ? horizons : [7, 15, 30, 60],
|
||||
tm_i: d.tm_i,
|
||||
hm_i: d.hm_i,
|
||||
tm_o: d.tm_o,
|
||||
hm_o: d.hm_o
|
||||
};
|
||||
self.editing = true;
|
||||
}).catch(function () {});
|
||||
},
|
||||
closeEdit: function (done) { if (!this.saving) { this.editing = false; this.editData = null; if (typeof done === 'function') done(); } },
|
||||
closeDetail: function (done) {
|
||||
var self = this;
|
||||
if (this.saving) return;
|
||||
@@ -41,6 +60,27 @@ define(['jquery', 'bootstrap', 'backend', 'backend/forecast/components'], functi
|
||||
var self = this;
|
||||
this.api('detail', {id: id}).then(function (res) { self.selected = res.data; self.viewing = true; }).catch(function () {});
|
||||
},
|
||||
deleteRecord: function (row) {
|
||||
var self = this;
|
||||
if (this.saving) return;
|
||||
this.$confirm('确定要删除【' + (row.granary_name || '') + ' · ' + (row.observed_date || '') + '】的温湿度预测记录吗?删除后关联周期的预测与实测值将一并移除且不可恢复。', '删除记录确认', {
|
||||
confirmButtonText: '确定删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function () {
|
||||
self.saving = true;
|
||||
self.api('dell', {id: row.id}, 'POST').then(function () {
|
||||
self.$message.success('删除成功');
|
||||
if (self.viewing && self.selected && self.selected.id === row.id) {
|
||||
self.viewing = false;
|
||||
self.selected = null;
|
||||
}
|
||||
self.load();
|
||||
}).catch(function () {}).then(function () {
|
||||
self.saving = false;
|
||||
});
|
||||
}).catch(function () {});
|
||||
},
|
||||
write: function (action, data, callback) {
|
||||
if (this.saving) return;
|
||||
var self = this;
|
||||
@@ -48,7 +88,7 @@ define(['jquery', 'bootstrap', 'backend', 'backend/forecast/components'], functi
|
||||
this.api(action, data, 'POST').then(function (res) {
|
||||
self.selected = res.data;
|
||||
if (action !== 'actual' && res.data.status === 'failed') self.$message.warning('温湿度已保存,算法暂不可用,可稍后重新生成');
|
||||
else self.$message.success(action === 'actual' ? '实测值已保存' : res.data.status === 'ready' ? '预测已生成并保存' : '记录已保存');
|
||||
else self.$message.success(action === 'actual' ? '实测值已保存' : action === 'edit' ? '修改成功并已更新预测' : res.data.status === 'ready' ? '预测已生成并保存' : '记录已保存');
|
||||
if (callback) callback();
|
||||
self.load();
|
||||
}).catch(function () {}).then(function () { self.saving = false; });
|
||||
@@ -57,6 +97,10 @@ define(['jquery', 'bootstrap', 'backend', 'backend/forecast/components'], functi
|
||||
var self = this;
|
||||
this.write('add', form, function () { self.creating = false; self.viewing = true; });
|
||||
},
|
||||
updateRecord: function (form) {
|
||||
var self = this;
|
||||
this.write('edit', form, function () { self.editing = false; self.editData = null; self.viewing = true; });
|
||||
},
|
||||
saveActual: function (form) { this.write('actual', form); },
|
||||
retry: function (id) {
|
||||
var self = this;
|
||||
|
||||
@@ -82,19 +82,32 @@ define([], function () {
|
||||
}
|
||||
},
|
||||
create: {
|
||||
template: '#forecast-create-template', props: ['granaries', 'busy', 'siteDefaultEnv'],
|
||||
data: function () { return {
|
||||
form: {gid: '', observed_date: today(), horizons: [7, 15, 30, 60], tm_i: 18.5, hm_i: 70.0, tm_o: 32.0, hm_o: 55.0, request_key: requestKey()},
|
||||
dateOptions: dateOptions,
|
||||
presets: PRESETS,
|
||||
selectedPresetKey: 'quasi_low',
|
||||
fields: [
|
||||
{key: 'tm_i', label: '仓内温度', unit: '℃', min: -50, max: 80, step: 0.1, placeholder: '例:18.5'},
|
||||
{key: 'hm_i', label: '仓内相对湿度', unit: '%', min: 0, max: 100, step: 0.1, placeholder: '例:70.0'},
|
||||
{key: 'tm_o', label: '仓外温度', unit: '℃', min: -50, max: 80, step: 0.1, placeholder: '例:32.0'},
|
||||
{key: 'hm_o', label: '仓外相对湿度', unit: '%', min: 0, max: 100, step: 0.1, placeholder: '例:55.0'}
|
||||
]
|
||||
}; },
|
||||
template: '#forecast-create-template', props: ['granaries', 'busy', 'initialData', 'isEdit'],
|
||||
data: function () {
|
||||
var d = this.initialData;
|
||||
return {
|
||||
form: {
|
||||
id: d && d.id ? d.id : '',
|
||||
gid: d && d.gid ? d.gid : '',
|
||||
observed_date: d && d.observed_date ? d.observed_date : today(),
|
||||
horizons: d && d.horizons ? d.horizons.slice() : [7, 15, 30, 60],
|
||||
tm_i: d && d.tm_i !== undefined ? Number(d.tm_i) : 18.5,
|
||||
hm_i: d && d.hm_i !== undefined ? Number(d.hm_i) : 70.0,
|
||||
tm_o: d && d.tm_o !== undefined ? Number(d.tm_o) : 32.0,
|
||||
hm_o: d && d.hm_o !== undefined ? Number(d.hm_o) : 55.0,
|
||||
request_key: requestKey()
|
||||
},
|
||||
dateOptions: dateOptions,
|
||||
presets: PRESETS,
|
||||
selectedPresetKey: d ? '' : 'quasi_low',
|
||||
fields: [
|
||||
{key: 'tm_i', label: '仓内温度', unit: '℃', min: -50, max: 80, step: 0.1, placeholder: '例:18.5'},
|
||||
{key: 'hm_i', label: '仓内相对湿度', unit: '%', min: 0, max: 100, step: 0.1, placeholder: '例:70.0'},
|
||||
{key: 'tm_o', label: '仓外温度', unit: '℃', min: -50, max: 80, step: 0.1, placeholder: '例:32.0'},
|
||||
{key: 'hm_o', label: '仓外相对湿度', unit: '%', min: 0, max: 100, step: 0.1, placeholder: '例:55.0'}
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tempStatus: function () {
|
||||
return evaluateTemp(this.form.tm_i, this.form.hm_i);
|
||||
@@ -107,7 +120,9 @@ define([], function () {
|
||||
watch: {
|
||||
'form.gid': function (newGid) {
|
||||
if (!newGid) return;
|
||||
this.onGranaryChange(newGid);
|
||||
if (!this.isEdit) {
|
||||
this.onGranaryChange(newGid);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -119,7 +134,7 @@ define([], function () {
|
||||
this.form.hm_i = p.hm_i;
|
||||
this.form.tm_o = p.tm_o;
|
||||
this.form.hm_o = p.hm_o;
|
||||
this..success('已套用【' + p.name + '】规范温湿度');
|
||||
this.$message.success('已套用【' + p.name + '】规范温湿度');
|
||||
},
|
||||
onGranaryChange: function (gid) {
|
||||
var granary = this.granaries.find(function (g) { return String(g.id) === String(gid); });
|
||||
@@ -131,18 +146,18 @@ define([], function () {
|
||||
this.form.tm_o = Number(granary.last_env.tm_o);
|
||||
this.form.hm_o = Number(granary.last_env.hm_o);
|
||||
this.selectedPresetKey = '';
|
||||
this..info('已自动读取【' + granary.name + '】最近一次温湿度记录');
|
||||
this.$message.info('已自动读取【' + granary.name + '】最近一次温湿度记录');
|
||||
} else if (this.form.tm_i === '' || this.form.tm_i === undefined) {
|
||||
this.applyPreset('quasi_low');
|
||||
}
|
||||
},
|
||||
submit: function () {
|
||||
if (!this.form.gid || !this.form.observed_date || !this.form.horizons.length) return this..warning('请选择仓库、采集日期和预测周期');
|
||||
if (!this.form.gid || !this.form.observed_date || !this.form.horizons.length) return this.$message.warning('请选择仓库、采集日期和预测周期');
|
||||
for (var i = 0; i < this.fields.length; i++) {
|
||||
var f = this.fields[i], v = this.form[f.key];
|
||||
if (v === '' || !Number.isFinite(Number(v)) || Number(v) < f.min || Number(v) > f.max) return this..warning('请填写有效的' + f.label + '(' + f.min + '~' + f.max + ')');
|
||||
if (v === '' || !Number.isFinite(Number(v)) || Number(v) < f.min || Number(v) > f.max) return this.$message.warning('请填写有效的' + f.label + '(' + f.min + '~' + f.max + ')');
|
||||
}
|
||||
this.('submit', JSON.parse(JSON.stringify(this.form)));
|
||||
this.$emit('submit', JSON.parse(JSON.stringify(this.form)));
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -182,7 +197,7 @@ define([], function () {
|
||||
},
|
||||
confirmDiscard: function () {
|
||||
if (this.busy) return Promise.reject();
|
||||
return this.dirty ? this.('当前周期有未保存的实测数据,确定放弃修改?', '未保存的数据', {type: 'warning'}) : Promise.resolve();
|
||||
return this.dirty ? this.$confirm('当前周期有未保存的实测数据,确定放弃修改?', '未保存的数据', {type: 'warning'}) : Promise.resolve();
|
||||
},
|
||||
beforeLeave: function () {
|
||||
return this.confirmDiscard().then(function () { return true; });
|
||||
@@ -193,10 +208,10 @@ define([], function () {
|
||||
var m = this.record.metrics[i], v = this.actual[m.key];
|
||||
if (v === '') continue;
|
||||
any = true;
|
||||
if (!Number.isFinite(Number(v)) || Number(v) < 0 || Number(v) > m.max) return this..warning('请填写有效的' + m.name + '实测值');
|
||||
if (!Number.isFinite(Number(v)) || Number(v) < 0 || Number(v) > m.max) return this.$message.warning('请填写有效的' + m.name + '实测值');
|
||||
}
|
||||
if (any && !this.actualDate) return this..warning('请选择实际检测日期');
|
||||
this.('save', {point_id: this.point.id, version: this.point.version, actual_date: this.actualDate, actual: Object.assign({}, this.actual)});
|
||||
if (any && !this.actualDate) return this.$message.warning('请选择实际检测日期');
|
||||
this.$emit('save', {point_id: this.point.id, version: this.point.version, actual_date: this.actualDate, actual: Object.assign({}, this.actual)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
在新工单中引用
屏蔽一个用户