MedicinalView.vue 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. <script setup>
  2. import { ref, onMounted, computed, unref, watch } from 'vue';
  3. import { NScrollbar, useMessage, NTabs, NTabPane, c } from 'naive-ui';
  4. import { TheChatView } from '@/components';
  5. import { controlApi } from "@/api/control";
  6. import BaseTitle from './components/BaseTitle.vue';
  7. import BaseRadioCard from './components/BaseRadioCard.vue';
  8. import BaseCard from './components/BaseCard.vue';
  9. import BaseChooseItem from './components/BaseChooseItem.vue';
  10. import BaseInput from './components/BaseInput.vue';
  11. import TheResultPanel from './components/TheResultPanel.vue';
  12. import TheEchartPanel from './components/TheEchartPanel.vue';
  13. const message = useMessage();
  14. const isVisibleBtn = ref(true);
  15. const isVisibleUpdateInfo = ref(false);
  16. const systemStatus = ref(0);
  17. const columnData = ref([
  18. { label: '后反馈设定', key: 'htfksd', value: '' },
  19. { label: '基准系数', key: 'jzxs', value: '' },
  20. { label: '修正系数', key: 'xzxs', value: '' },
  21. { label: '控制系数', key: 'kzxs', value: '' },
  22. { label: '水量分配系数', key: 'slfpxs', value: '' },
  23. { label: '碳源当量', key: 'tydl', value: '' },
  24. { label: '转换系数', key: 'zhxs', value: '' },
  25. { label: '稀释倍数', key: 'sxps', value: '' },
  26. { label: '药剂密度', key: 'yymd', value: '' },
  27. { label: '最小启动流量', key: 'zxqdll', value: '' },
  28. { label: '碳氮比', key: 'tdb', value: '' }
  29. ])
  30. const doseNum = ref(null);
  31. const flowNum = ref(null);
  32. const updateNum = ref(null);
  33. const tabKeyEnum = {
  34. 0: 'auto',
  35. 1: 'onePool',
  36. 2: 'twoPool',
  37. 3: 'worker'
  38. }
  39. // water实时数据
  40. const waterConfigParams = ref({});
  41. // 基础数据
  42. const dataSourceParams = ref({
  43. auto: {},
  44. onePool: {},
  45. twoPool: {},
  46. worker: {
  47. medicineAmount: null
  48. }
  49. })
  50. // 系数
  51. const baseSourceParams = ref({
  52. numberBeng: 0,
  53. type: 0
  54. })
  55. // 当前Tab选中的key
  56. const tabActiveKey = computed(() => tabKeyEnum[baseSourceParams.value.type]);
  57. // 计算碳氮比
  58. const tdbNum = computed(() => {
  59. const type = tabActiveKey.value;
  60. const {
  61. jsLlOne, jsLlTwo,
  62. jsCodOne, jsCodTwo,
  63. jsTnOne, jsTnTwo
  64. } = dataSourceParams.value[type];
  65. const {
  66. tydl, zhxs
  67. } = baseSourceParams.value
  68. const { tytjzl } = waterConfigParams.value;
  69. if ( type === 'auto' || type === 'worker' ) {
  70. const jsll = Math.max( jsLlOne, jsLlTwo );
  71. const cod = Math.max( jsCodOne, jsCodTwo );
  72. const jsTn = Math.max( jsTnOne, jsTnTwo );
  73. return Number(((tytjzl*1000/jsll*tydl+cod*zhxs*tydl)/jsTn).toFixed(2));
  74. }
  75. if ( type === 'onePool' ) {
  76. return Number(((tytjzl*1000/jsLlOne*tydl+jsCodOne*zhxs*tydl)/jsTnOne).toFixed(2));
  77. }
  78. if ( type === 'twoPool' ) {
  79. return Number(((tytjzl*1000/jsLlTwo*tydl+jsCodTwo*zhxs*tydl)/jsTnTwo).toFixed(2));
  80. }
  81. })
  82. watch(() => tdbNum.value , tdb => {
  83. columnData.value[columnData.value.length - 1].value = tdb;
  84. })
  85. // 编辑系数 - confirm
  86. const onEditConfirm = () => {
  87. isVisibleBtn.value = true;
  88. columnData.value = columnData.value.map(item => {
  89. Object.entries(baseSourceParams.value).forEach(([key, value]) => {
  90. if (key === item.key) {
  91. item.value = value;
  92. }
  93. })
  94. return item;
  95. })
  96. handleMedicateAmount();
  97. }
  98. // 编辑系数 - 取消
  99. const onEditCancel = () => {
  100. isVisibleBtn.value = true;
  101. columnData.value.map(({ key, value }) => {
  102. baseSourceParams.value[key] = value;
  103. })
  104. }
  105. const onFinalResult = () => {
  106. const addStatus = systemStatus.value === 0 ? 1 : 0;
  107. controlApi.putSystemStatus({ addStatus });
  108. systemStatus.value = addStatus;
  109. message.warning(addStatus === 0 ? '当前投药状态:已停用' : '当前投药状态:投放中');
  110. }
  111. const onUpdateTab = (index) => {
  112. const currentData = dataSourceParams.value[tabKeyEnum[index]];
  113. baseSourceParams.value.type = index;
  114. if ( !Object.keys(currentData).length ) {
  115. isVisibleUpdateInfo.value = false;
  116. return;
  117. }
  118. handleMedicateAmount();
  119. }
  120. const getTotalNum = () => {
  121. const {
  122. hycXsyOne = 0, hycXsyTwo = 0,
  123. qycAdOne = 0, qycAdTwo = 0,
  124. qycYxyOne = 0, qycYxyTwo = 0,
  125. jsLlOne = 0, jsLlTwo = 0,
  126. jsCodOne = 0, jsCodTwo = 0
  127. } = dataSourceParams.value[tabActiveKey.value];
  128. const {
  129. htfksd, xzxs, kzxs, slfpxs, zhxs, tydl, jzxs, yymd, sxps
  130. } = baseSourceParams.value;
  131. const rOne1 = (((2*hycXsyOne-htfksd)+((qycAdOne+qycYxyOne)*xzxs-htfksd))*(jzxs-1))*(jsLlOne*slfpxs)/1000;
  132. const rOne2 = (rOne1*kzxs-(jsLlOne*slfpxs*jsCodOne*zhxs/1000))/tydl;
  133. const rOne3 = rOne2/yymd/1000*sxps
  134. const rTwo1 = (((2*hycXsyTwo-htfksd)+((qycAdTwo+qycYxyTwo)*xzxs-htfksd))*(jzxs-1))*(jsLlTwo*slfpxs)/1000;
  135. const rTwo2 = (rTwo1*kzxs-(jsLlTwo*slfpxs*jsCodTwo*zhxs/1000))/tydl;
  136. const rTwo3 = rTwo2/yymd/1000*sxps
  137. const r1 = Number((rOne3 < 0 || !rOne3) ? 0 : rOne3.toFixed(3)) || 0;
  138. const r2 = Number((rTwo3 < 0 || !rTwo3) ? 0 : rTwo3.toFixed(3)) || 0;
  139. return [ r1, r2 ];
  140. }
  141. const onConfirmUpdate = async () => {
  142. await controlApi.postAddRecord({
  143. ...dataSourceParams.value[tabKeyEnum[baseSourceParams.value.type]],
  144. ...baseSourceParams.value,
  145. });
  146. isVisibleUpdateInfo.value = false;
  147. message.success("系统加药量,更新成功");
  148. doseNum.value = updateNum.value;
  149. }
  150. // 更新投药结果
  151. const handleMedicateAmount = () => {
  152. const type = tabActiveKey.value;
  153. const lastNum = unref(updateNum);
  154. const tdb = tdbNum.value;
  155. if ( type === 'worker' ) {
  156. const medicineNum = dataSourceParams.value.worker.medicineAmount;
  157. if ( medicineNum || medicineNum == 0 ) {
  158. updateNum.value = medicineNum;
  159. isVisibleUpdateInfo.value = true;
  160. baseSourceParams.value.tdb = tdb;
  161. message.warning("有新投放方案, 请查看")
  162. } else {
  163. updateNum.value = null;
  164. isVisibleUpdateInfo.value = false;
  165. }
  166. return;
  167. }
  168. const [r1, r2] = getTotalNum();
  169. const maxR = Math.max( r1, r2 );
  170. if ( type === 'auto' && maxR !== lastNum) {
  171. updateNum.value = maxR;
  172. isVisibleUpdateInfo.value = true;
  173. baseSourceParams.value.tdb = tdb;
  174. message.warning("有新的投放方案, 请查看");
  175. }
  176. if ( type === 'onePool' && r1 != lastNum) {
  177. updateNum.value = r1;
  178. isVisibleUpdateInfo.value = true;
  179. baseSourceParams.value.tdb = tdb;
  180. message.warning("有新的投放方案, 请查看");
  181. }
  182. if ( type === 'twoPool' && r2 != lastNum ) {
  183. updateNum.value = r2;
  184. isVisibleUpdateInfo.value = true;
  185. baseSourceParams.value.tdb = tdb;
  186. message.warning("有新的投放方案, 请查看");
  187. }
  188. }
  189. onMounted(async () => {
  190. // 获取最后一条记录 getSystemStatus
  191. await controlApi.getBaseData().then(({ data }) => {
  192. const {
  193. numberBeng = 0, type = 0,
  194. htfksd, jzxs, xzxs, kzxs, slfpxs, tydl, zhxs, sxps, yymd, zxqdll,
  195. medicineAmount,
  196. addType,
  197. tytjTransientLL
  198. } = data;
  199. baseSourceParams.value = {
  200. ...baseSourceParams.value,
  201. numberBeng, type,
  202. htfksd, jzxs, xzxs, kzxs, slfpxs, tydl, zhxs, sxps, yymd, zxqdll,
  203. addType
  204. };
  205. updateNum.value = medicineAmount;
  206. doseNum.value = medicineAmount;
  207. flowNum.value = tytjTransientLL;
  208. dataSourceParams.value[tabActiveKey.value] = data;
  209. })
  210. // 获取实时数据
  211. controlApi.getNumValue().then(({ data }) => {
  212. Object.entries(data).forEach(([key, val]) => {
  213. data[key] = val;
  214. });
  215. // water实时数据
  216. waterConfigParams.value = data;
  217. // 重新计算碳氮比
  218. const tdb = tdbNum.value;
  219. baseSourceParams.value.tdb = tdb;
  220. columnData.value = columnData.value.map(item => {
  221. item.value = item.key === 'tdb' ? tdb : dataSourceParams.value[tabActiveKey.value][item.key];
  222. return item;
  223. })
  224. const params = {
  225. jsLlType: 1,
  226. jsLlOne: data.jslYB,
  227. jsLlTwo: data.jslYB,
  228. jsCodType: 1,
  229. jsCodOne: data.jsCodYB,
  230. jsCodTwo: data.jsCodYB,
  231. hycXsyType: 1,
  232. hycXsyOne: data.hyXsyHYOne,
  233. hycXsyTwo: data.hyXsyHYTwo,
  234. qycYxyType: 1,
  235. qycYxyOne: data.qyXsyHYOne,
  236. qycYxyTwo: data.qyXsyHYTwo,
  237. qycAdType: 1,
  238. qycAdOne: data.qyAdHYOne,
  239. qycAdTwo: data.qyAdHYTwo,
  240. jsTnType: 1,
  241. jsTnOne: data.jsTnYB,
  242. jsTnTwo: data.jsTnYB
  243. }
  244. Object.keys(dataSourceParams.value).forEach(key => {
  245. const item = dataSourceParams.value[key];
  246. if ( !Object.keys(item).length ) {
  247. dataSourceParams.value[key] = { ...params };
  248. }
  249. })
  250. })
  251. // 获取是否允许投药开关
  252. controlApi.getSystemStatus().then(({ data }) => {
  253. // 0不允许 1允许
  254. systemStatus.value = data;
  255. });
  256. })
  257. </script>
  258. <template>
  259. <section class="flex items-start h-full">
  260. <TheChatView leftTitle="智适应碳源投加" :isChatSlot="false" :isFooter="false">
  261. <template #control>
  262. <div class="control-container space-x-[12px]">
  263. <div class="left-section">
  264. <BaseTitle title="智能投加计算"></BaseTitle>
  265. <n-scrollbar class="scrollbar" style="height: 100%;">
  266. <div class="form-content">
  267. <BaseCard title="选择加药泵">
  268. <BaseRadioCard v-model="baseSourceParams.numberBeng"></BaseRadioCard>
  269. </BaseCard>
  270. <BaseCard title="投加运行方式">
  271. <span class="status-bar">
  272. <i>{{ baseSourceParams.addType === 0 ? '启用智适应碳源投加' : '手动碳源投加' }}</i>
  273. </span>
  274. </BaseCard>
  275. <BaseCard title="选择池组手自动方式">
  276. <n-tabs justify-content="space-between" type="line" :bar-width="40"
  277. tab-style="min-width: 89px;" tab-class="custom-tab_item" animated :on-update:value="onUpdateTab" :value="baseSourceParams.type">
  278. <n-tab-pane :name="0" tab="自动">
  279. <div class="panel-header_main">
  280. <p>设置数据来源</p>
  281. <p class="space-x-[20px] text-center">
  282. <span>1号池</span>
  283. <span>2号池</span>
  284. </p>
  285. </div>
  286. <div class="space-y-[12px]">
  287. <BaseChooseItem
  288. tab-key="auto"
  289. title="进水流量"
  290. unit="m³"
  291. isDouble
  292. @on-update="handleMedicateAmount"
  293. v-model:type="dataSourceParams.auto.jsLlType"
  294. v-model:value1="dataSourceParams.auto.jsLlOne"
  295. v-model:value2="dataSourceParams.auto.jsLlTwo"
  296. :btn-group="[
  297. { label: '手动', value1: '', value2: '' },
  298. { label: '仪表', value1: waterConfigParams.jslYB, value2: waterConfigParams.jslYB }
  299. ]"
  300. ></BaseChooseItem>
  301. <BaseChooseItem
  302. tab-key="auto"
  303. title="进水COD"
  304. unit="mg/L"
  305. isDouble
  306. @on-update="handleMedicateAmount"
  307. v-model:type="dataSourceParams.auto.jsCodType"
  308. v-model:value1="dataSourceParams.auto.jsCodOne"
  309. v-model:value2="dataSourceParams.auto.jsCodTwo"
  310. :btn-group="[
  311. { label: '手动', value1: '', value2: '' },
  312. { label: '仪表', value1: waterConfigParams.jsCodYB, value2: waterConfigParams.jsCodYB },
  313. { label: '化验', value1: waterConfigParams.jsCodHY, value2: waterConfigParams.jsCodHY }
  314. ]"
  315. ></BaseChooseItem>
  316. <BaseChooseItem
  317. tab-key="auto"
  318. title="好氧池硝酸盐"
  319. unit="mg/L"
  320. isDouble
  321. @on-update="handleMedicateAmount"
  322. v-model:type="dataSourceParams.auto.hycXsyType"
  323. v-model:value1="dataSourceParams.auto.hycXsyOne"
  324. v-model:value2="dataSourceParams.auto.hycXsyTwo"
  325. :btn-group="[
  326. { label: '手动', value1: '', value2: '' },
  327. { label: '化验', value1: waterConfigParams.hyXsyHYOne, value2: waterConfigParams.hyXsyHYTwo },
  328. { label: '预测', value1: waterConfigParams.hyXsyYCOne, value2: waterConfigParams.hyXsyYCTwo }
  329. ]"
  330. ></BaseChooseItem>
  331. <BaseChooseItem
  332. tab-key="auto"
  333. title="缺氧池硝酸盐"
  334. unit="mg/L"
  335. isDouble
  336. @on-update="handleMedicateAmount"
  337. v-model:type="dataSourceParams.auto.qycYxyType"
  338. v-model:value1="dataSourceParams.auto.qycYxyOne"
  339. v-model:value2="dataSourceParams.auto.qycYxyTwo"
  340. :btn-group="[
  341. { label: '手动', value1: '', value2: '' },
  342. { label: '化验', value1: waterConfigParams.qyXsyHYOne, value2: waterConfigParams.qyXsyHYTwo }
  343. ]"
  344. ></BaseChooseItem>
  345. <BaseChooseItem
  346. tab-key="auto"
  347. title="缺氧池氨氮"
  348. unit="mg/L"
  349. isDouble
  350. @on-update="handleMedicateAmount"
  351. v-model:type="dataSourceParams.auto.qycAdType"
  352. v-model:value1="dataSourceParams.auto.qycAdOne"
  353. v-model:value2="dataSourceParams.auto.qycAdTwo"
  354. :btn-group="[
  355. { label: '手动', value1: '', value2: '' },
  356. { label: '化验', value1: waterConfigParams.qyAdHYOne, value2: waterConfigParams.qyAdHYTwo }
  357. ]"
  358. ></BaseChooseItem>
  359. <BaseChooseItem
  360. tab-key="auto"
  361. title="进水总氮"
  362. unit="mg/L"
  363. isDouble
  364. @on-update="handleMedicateAmount"
  365. v-model:type="dataSourceParams.auto.jsTnType"
  366. v-model:value1="dataSourceParams.auto.jsTnOne"
  367. v-model:value2="dataSourceParams.auto.jsTnTwo"
  368. :btn-group="[
  369. { label: '手动', value1: '', value2: '' },
  370. { label: '仪表', value1: waterConfigParams.jsTnYB, value2: waterConfigParams.jsTnYB }
  371. ]"
  372. ></BaseChooseItem>
  373. </div>
  374. </n-tab-pane>
  375. <n-tab-pane :name="1" tab="1号池">
  376. <div class="panel-header_main">
  377. <p>设置数据来源</p>
  378. <p class="space-x-[20px] text-center">
  379. <span>1号池</span>
  380. </p>
  381. </div>
  382. <div class="space-y-[12px]">
  383. <BaseChooseItem
  384. tab-key="onePool"
  385. title="进水流量"
  386. unit="m³"
  387. @on-update="handleMedicateAmount"
  388. v-model:type="dataSourceParams.onePool.jsLlType"
  389. v-model:value1="dataSourceParams.onePool.jsLlOne"
  390. :btn-group="[
  391. { label: '手动', value1: '', value2: '' },
  392. { label: '仪表', value1: waterConfigParams.jslYB, value2: waterConfigParams.jslYB }
  393. ]"
  394. ></BaseChooseItem>
  395. <BaseChooseItem
  396. tab-key="onePool"
  397. title="进水COD"
  398. unit="mg/L"
  399. @on-update="handleMedicateAmount"
  400. v-model:type="dataSourceParams.onePool.jsCodType"
  401. v-model:value1="dataSourceParams.onePool.jsCodOne"
  402. :btn-group="[
  403. { label: '手动', value1: '', value2: '' },
  404. { label: '仪表', value1: waterConfigParams.jsCodYB, value2: waterConfigParams.jsCodYB },
  405. { label: '化验', value1: waterConfigParams.jsCodHY, value2: waterConfigParams.jsCodHY }
  406. ]"
  407. ></BaseChooseItem>
  408. <BaseChooseItem
  409. tab-key="onePool"
  410. title="好氧池硝酸盐"
  411. unit="mg/L"
  412. @on-update="handleMedicateAmount"
  413. v-model:type="dataSourceParams.onePool.hycXsyType"
  414. v-model:value1="dataSourceParams.onePool.hycXsyOne"
  415. :btn-group="[
  416. { label: '手动', value1: '', value2: '' },
  417. { label: '化验', value1: waterConfigParams.hyXsyHYOne, value2: waterConfigParams.hyXsyHYTwo },
  418. { label: '预测', value1: waterConfigParams.hyXsyYCOne, value2: waterConfigParams.hyXsyYCTwo }
  419. ]"
  420. ></BaseChooseItem>
  421. <BaseChooseItem
  422. tab-key="onePool"
  423. title="缺氧池硝酸盐"
  424. unit="mg/L"
  425. @on-update="handleMedicateAmount"
  426. v-model:type="dataSourceParams.onePool.qycYxyType"
  427. v-model:value1="dataSourceParams.onePool.qycYxyOne"
  428. v-model:value2="dataSourceParams.onePool.qycYxyTwo"
  429. :btn-group="[
  430. { label: '手动', value1: '', value2: '' },
  431. { label: '化验', value1: waterConfigParams.qyXsyHYOne, value2: waterConfigParams.qyXsyHYTwo }
  432. ]"
  433. ></BaseChooseItem>
  434. <BaseChooseItem
  435. tab-key="onePool"
  436. title="缺氧池氨氮"
  437. unit="mg/L"
  438. @on-update="handleMedicateAmount"
  439. v-model:type="dataSourceParams.onePool.qycAdType"
  440. v-model:value1="dataSourceParams.onePool.qycAdOne"
  441. :btn-group="[
  442. { label: '手动', value1: '', value2: '' },
  443. { label: '化验', value1: waterConfigParams.qyAdHYOne, value2: waterConfigParams.qyAdHYTwo }
  444. ]"
  445. ></BaseChooseItem>
  446. <BaseChooseItem
  447. tab-key="onePool"
  448. title="进水总氮"
  449. unit="mg/L"
  450. @on-update="handleMedicateAmount"
  451. v-model:type="dataSourceParams.onePool.jsTnType"
  452. v-model:value1="dataSourceParams.onePool.jsTnOne"
  453. :btn-group="[
  454. { label: '手动', value1: '', value2: '' },
  455. { label: '仪表', value1: waterConfigParams.jsTnYB, value2: waterConfigParams.jsTnYB }
  456. ]"
  457. ></BaseChooseItem>
  458. </div>
  459. </n-tab-pane>
  460. <n-tab-pane :name="2" tab="2号池">
  461. <div class="panel-header_main">
  462. <p>设置数据来源</p>
  463. <p class="space-x-[20px] text-center">
  464. <span>2号池</span>
  465. </p>
  466. </div>
  467. <div class="space-y-[12px]">
  468. <BaseChooseItem
  469. tab-key="twoPool"
  470. title="进水流量"
  471. unit="m³"
  472. @on-update="handleMedicateAmount"
  473. v-model:type="dataSourceParams.twoPool.jsLlType"
  474. v-model:value1="dataSourceParams.twoPool.jsLlTwo"
  475. :btn-group="[
  476. { label: '手动', value1: '', value2: '' },
  477. { label: '仪表', value1: waterConfigParams.jslYB, value2: waterConfigParams.jslYB }
  478. ]"
  479. ></BaseChooseItem>
  480. <BaseChooseItem
  481. tab-key="twoPool"
  482. title="进水COD"
  483. unit="mg/L"
  484. @on-update="handleMedicateAmount"
  485. v-model:type="dataSourceParams.twoPool.jsCodType"
  486. v-model:value1="dataSourceParams.twoPool.jsCodTwo"
  487. :btn-group="[
  488. { label: '手动', value1: '', value2: '' },
  489. { label: '仪表', value1: waterConfigParams.jsCodYB, value2: waterConfigParams.jsCodYB },
  490. { label: '化验', value1: waterConfigParams.jsCodHY, value2: waterConfigParams.jsCodHY }
  491. ]"
  492. ></BaseChooseItem>
  493. <BaseChooseItem
  494. tab-key="twoPool"
  495. title="好氧池硝酸盐"
  496. unit="mg/L"
  497. @on-update="handleMedicateAmount"
  498. v-model:type="dataSourceParams.twoPool.hycXsyType"
  499. v-model:value1="dataSourceParams.twoPool.hycXsyTwo"
  500. :btn-group="[
  501. { label: '手动', value1: '', value2: '' },
  502. { label: '化验', value1: waterConfigParams.hyXsyHYOne, value2: waterConfigParams.hyXsyHYTwo },
  503. { label: '预测', value1: waterConfigParams.hyXsyYCOne, value2: waterConfigParams.hyXsyYCTwo }
  504. ]"
  505. ></BaseChooseItem>
  506. <BaseChooseItem
  507. tab-key="twoPool"
  508. title="缺氧池硝酸盐"
  509. unit="mg/L"
  510. @on-update="handleMedicateAmount"
  511. v-model:type="dataSourceParams.twoPool.qycYxyType"
  512. v-model:value1="dataSourceParams.twoPool.qycYxyTwo"
  513. :btn-group="[
  514. { label: '手动', value1: '', value2: '' },
  515. { label: '化验', value1: waterConfigParams.qyXsyHYOne, value2: waterConfigParams.qyXsyHYTwo }
  516. ]"
  517. ></BaseChooseItem>
  518. <BaseChooseItem
  519. tab-key="twoPool"
  520. title="缺氧池氨氮"
  521. unit="mg/L"
  522. @on-update="handleMedicateAmount"
  523. v-model:type="dataSourceParams.twoPool.qycAdType"
  524. v-model:value1="dataSourceParams.twoPool.qycAdTwo"
  525. :btn-group="[
  526. { label: '手动', value1: '', value2: '' },
  527. { label: '化验', value1: waterConfigParams.qyAdHYOne, value2: waterConfigParams.qyAdHYTwo }
  528. ]"
  529. ></BaseChooseItem>
  530. <BaseChooseItem
  531. tab-key="twoPool"
  532. title="进水总氮"
  533. unit="mg/L"
  534. @on-update="handleMedicateAmount"
  535. v-model:type="dataSourceParams.twoPool.jsTnType"
  536. v-model:value1="dataSourceParams.twoPool.jsTnTwo"
  537. :btn-group="[
  538. { label: '手动', value1: '', value2: '' },
  539. { label: '仪表', value1: waterConfigParams.jsTnYB, value2: waterConfigParams.jsTnYB }
  540. ]"
  541. ></BaseChooseItem>
  542. </div>
  543. </n-tab-pane>
  544. <n-tab-pane :name="3" tab="人工投放">
  545. <div class="panel-header_main">
  546. <p>设置数据来源</p>
  547. <p class="space-x-[20px] text-center">
  548. <span>人工投放</span>
  549. </p>
  550. </div>
  551. <div class="w-full flex items-center justify-between">
  552. <span>人工投放:</span>
  553. <div class="w-[200px]">
  554. <BaseInput
  555. :isCloseIcon="false"
  556. v-model="dataSourceParams.worker.medicineAmount"
  557. @on-blur="handleMedicateAmount"
  558. ></BaseInput>
  559. </div>
  560. </div>
  561. </n-tab-pane>
  562. </n-tabs>
  563. </BaseCard>
  564. <BaseCard title="设定参数系数" style="margin: 0" tips="建议使用默认值,非必要不修改">
  565. <template #titleRight>
  566. <div>
  567. <div class="flex items-center space-x-[4px] cursor-pointer text-[#2454FF] text-[13px]"
  568. v-show="isVisibleBtn" @click="isVisibleBtn = false">
  569. <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
  570. <path d="M2.33337 14H14.3334" stroke="#2454FF" stroke-linecap="round"
  571. stroke-linejoin="round" />
  572. <path d="M3.66663 8.90663V11.3333H6.10569L13 4.43603L10.565 2L3.66663 8.90663Z"
  573. stroke="#2454FF" stroke-linejoin="round" />
  574. </svg>
  575. <span>编辑</span>
  576. </div>
  577. <ul class="flex items-center text-[13px] space-x-[8px] cursor-pointer" v-show="!isVisibleBtn">
  578. <li class="cursor-pointer" @click="onEditConfirm" style="color: #2454FF">确定</li>
  579. <li class="cursor-pointer text-[#B0B7C0]" @click="onEditCancel">取消</li>
  580. </ul>
  581. </div>
  582. </template>
  583. <ul class="data-source-list space-y-[12px]">
  584. <li class="data-soruce-item" v-for="item, index in columnData">
  585. <span>{{ item.label }}:</span>
  586. <span class="unit" v-show="isVisibleBtn">
  587. {{ item.value }}
  588. {{ index === 0 ? 'mg/L' : '' }}
  589. </span>
  590. <div style="width: 140px;" v-show="!isVisibleBtn">
  591. <BaseInput :unit="index === 0 ? 'mg/L' : ''" size='small' :isNeedFlotBtn="false"
  592. v-model="baseSourceParams[item.key]" isCenter placeholder="" :readonly="index === columnData.length - 1"></BaseInput>
  593. </div>
  594. </li>
  595. </ul>
  596. </BaseCard>
  597. </div>
  598. </n-scrollbar>
  599. </div>
  600. <div class="right-section">
  601. <TheResultPanel
  602. :updateNum="updateNum"
  603. :flowNum="flowNum"
  604. :doseNum="doseNum"
  605. :configuration-status="baseSourceParams.addType"
  606. v-model:system="systemStatus"
  607. v-model="isVisibleUpdateInfo"
  608. @on-click="onFinalResult"
  609. @on-update="onConfirmUpdate"
  610. ></TheResultPanel>
  611. <TheEchartPanel></TheEchartPanel>
  612. </div>
  613. </div>
  614. </template>
  615. </TheChatView>
  616. </section>
  617. </template>
  618. <style lang="scss" scoped>
  619. .control-container {
  620. @include flex(x, start, start);
  621. height: 100%;
  622. .left-section {
  623. display: flex;
  624. flex-flow: column;
  625. flex-shrink: 0;
  626. width: 440px;
  627. height: 100%;
  628. border-radius: 10px;
  629. background: #fff;
  630. .status-bar {
  631. display: inline-block;
  632. padding: 4px 14px;
  633. margin-left: 20px;
  634. border-top: 0.5px solid rgba(212, 241, 255, 0.00);
  635. border-bottom: 0.5px solid rgba(212, 241, 255, 0.00);
  636. background: linear-gradient(90deg, rgba(240, 250, 255, 0.00) 0%, #E9F8FF 27.27%, rgba(240, 250, 255, 0.00) 100%);
  637. i {
  638. line-height: 24px;
  639. background: linear-gradient(92deg, #5ABBF2 12.24%, #2454FF 63.2%);
  640. background-clip: text;
  641. -webkit-background-clip: text;
  642. -webkit-text-fill-color: transparent;
  643. font-weight: bold;
  644. }
  645. }
  646. .scrollbar {
  647. height: 100%;
  648. }
  649. .form-content {
  650. padding: 0 16px 24px 16px;
  651. }
  652. .panel-header_main {
  653. @include flex(x, center, between);
  654. margin-bottom: 12px;
  655. color: #86909C;
  656. span {
  657. display: inline-block;
  658. width: 60px;
  659. }
  660. }
  661. }
  662. .data-source-list {
  663. .data-soruce-item {
  664. @include flex(x, center, between);
  665. .inp-inner {
  666. width: 112px;
  667. }
  668. .unit {
  669. font-family: "D-DIN-PRO-700-Bold";
  670. font-weight: bold;
  671. font-size: 12px;
  672. color: #333;
  673. }
  674. }
  675. }
  676. }
  677. .right-section {
  678. width: 100%;
  679. height: 100%;
  680. border-radius: 8px;
  681. background: #fff;
  682. overflow: hidden;
  683. // .top {
  684. // flex-shrink: 1;
  685. // height: 214px;
  686. // border-radius: 8px;
  687. // border: 0.5px solid #FFF;
  688. // background: linear-gradient(90deg, #E0E8FC 0%, #F2F4FF 100%);
  689. // }
  690. // .bottom {
  691. // height: 100%;
  692. // background: pink;
  693. // }
  694. }
  695. // 通用区域的样式
  696. .btn {
  697. width: 80px;
  698. height: 32px;
  699. border-radius: 4px;
  700. border: 1px solid #D3D7DD;
  701. text-align: center;
  702. font-size: 14px;
  703. line-height: 32px;
  704. color: #1A2029;
  705. }
  706. .btn-primary {
  707. border: 0;
  708. background: var(--Linear, linear-gradient(270deg, #3BD6E3 0%, #019AFE 100%));
  709. font-weight: bold;
  710. color: #fff;
  711. }
  712. .btn-info {
  713. width: 44px;
  714. height: 28px;
  715. border-radius: 4px;
  716. border: 1px solid #D3D7DD;
  717. background: #fff;
  718. font-size: 12px;
  719. text-align: center;
  720. line-height: 28px;
  721. color: #1A2029;
  722. cursor: pointer;
  723. }
  724. .btn-info_active {
  725. color: #2454FF;
  726. border: 1px solid #2454FF;
  727. background: #EBF0FF;
  728. }
  729. .radio {
  730. display: block;
  731. width: 12px;
  732. height: 12px;
  733. border-radius: 100%;
  734. border: 1px solid #ccc;
  735. cursor: pointer;
  736. }
  737. .radio_big {
  738. width: 16px;
  739. height: 16px;
  740. }
  741. .radio-active {
  742. transition: all .1s;
  743. border: 3px solid #2454FF;
  744. }
  745. .radio_big.radio-active {
  746. border: 4px solid #2454FF;
  747. }
  748. </style>
  749. <style lang="scss">
  750. .custom-tab_item {
  751. @include flex (x, center, center);
  752. height: 35px;
  753. border-radius: 4px;
  754. background: #F3F5FA;
  755. &.n-tabs-tab--active {
  756. transition: none !important;
  757. border-radius: 4px;
  758. transition: none !important;
  759. background: url('https://static.fuxicarbon.com/bigModel/pc/tab-border-item-2x.png') -3px 0px no-repeat, linear-gradient(180deg, #F1F3FE 0%, #FFF 100%);
  760. background-size: 107% 100%;
  761. }
  762. }
  763. .control-container .left-section {
  764. .n-tabs-nav-scroll-content {
  765. padding-bottom: 10px;
  766. }
  767. }
  768. </style>