ProjectInfo.vue 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987
  1. <template>
  2. <div class="project-info">
  3. <div class="header">
  4. <div class="go-back" @click="router.replace({ name: 'Automate' })">
  5. <van-button size="small"><van-icon name="arrow-left" />返回</van-button>
  6. </div>
  7. <div class="project-name">
  8. <div class="name">
  9. {{ crtProject!.name }}
  10. </div>
  11. <van-tag type="primary" v-show="crtProject?.isCompiled" size="medium">已编译</van-tag>
  12. <van-tag type="warning" v-show="!crtProject?.isCompiled" size="medium">未编译</van-tag>
  13. </div>
  14. <div class="more"><van-button type="primary" size="small" @click="showMorePopup = true">更多</van-button></div>
  15. </div>
  16. <div class="command-container">
  17. <van-swipe-cell v-for="item in crtProject!.commandList" :key="item.id">
  18. <van-cell
  19. clickable
  20. :border="false"
  21. :title="item.name"
  22. :label="item.time"
  23. @click="router.push(`/command-info/${crtProject!.id}/${item.id}`)"
  24. >
  25. <template #right-icon>
  26. <i class="iconfont icon-copy" @click.stop="copyCommand(item)"></i>
  27. </template>
  28. </van-cell>
  29. <template #right>
  30. <van-button square type="danger" text="删除" class="del-button" @click="handleDelete(item.id)" />
  31. </template>
  32. </van-swipe-cell>
  33. </div>
  34. <div class="add-btn">
  35. <van-button type="primary" block @click="handleAddCommond">添加任务</van-button>
  36. </div>
  37. <van-popup v-model:show="showMorePopup" position="right" :style="{ width: '50%', height: '100%' }">
  38. <template v-if="showMorePopup">
  39. <van-cell-group :style="{ marginTop: '16px' }">
  40. <van-cell title="编辑工程名称" clickable @click="handleEditName" :title-style="{ color: '#07c160' }" />
  41. <van-cell title="编译文件" @click="get_c_code('wx')" clickable :title-style="{ color: '#1989fa' }" />
  42. <van-cell title="仿真模拟" @click="get_c_code('wxsimu')" clickable :title-style="{ color: '#1989fa' }" />
  43. <van-cell clickable v-show="crtProject?.isCompiled">
  44. <template #title>
  45. <div v-html="wxtag" class="wx-tag"></div>
  46. </template>
  47. </van-cell>
  48. <van-cell title="删除工程" @click="delProject" clickable :title-style="{ color: '#fd5632' }" />
  49. <van-cell clickable v-if="isInWx">
  50. <template #title>
  51. <div v-html="wxShareTag" class="wx-tag"></div>
  52. </template>
  53. </van-cell>
  54. <!-- <van-cell title="分享" @click="shareProject" clickable /> -->
  55. </van-cell-group>
  56. </template>
  57. </van-popup>
  58. <van-popup v-model:show="showEditPopup" round :style="{ width: '80%' }">
  59. <div class="label" style="margin: 16px">编辑工程名称</div>
  60. <van-form @submit="onSubmit">
  61. <van-cell-group inset>
  62. <van-field
  63. border
  64. v-model="newProjectName"
  65. name="newProjectName"
  66. placeholder="工程名称"
  67. maxlength="20"
  68. :rules="[{ required: true, message: '请填写工程名称' }]"
  69. />
  70. </van-cell-group>
  71. <div class="van-button-group">
  72. <van-button @click="handleCancel" size="small">取消</van-button>
  73. <van-button type="primary" native-type="submit" size="small">确定</van-button>
  74. </div>
  75. </van-form>
  76. </van-popup>
  77. <van-popup v-model:show="showSharePopup" round :style="{ width: '80%' }">
  78. <div class="share-container">
  79. <!-- <canvas ref="qrcodeCanvas"></canvas> -->
  80. <img :src="shareImg" alt="" width="100%" />
  81. <div class="tip">长按图片进行分享</div>
  82. </div>
  83. </van-popup>
  84. </div>
  85. </template>
  86. <script setup lang="ts">
  87. import { useGlobalStore } from '@/stores/global'
  88. import type { CommandType, ProjectType } from '@/types/global'
  89. import { formatDateTime, deepEqual, deepClone } from '@/utils/tools'
  90. import { storeToRefs } from 'pinia'
  91. import { v4 as uuid4 } from 'uuid'
  92. import { showConfirmDialog, showLoadingToast, showFailToast } from 'vant'
  93. import qrcode from 'qrcode'
  94. const route = useRoute()
  95. const router = useRouter()
  96. const { projectList } = storeToRefs(useGlobalStore())
  97. const crtProject = ref<ProjectType>()
  98. const wxtag = ref('')
  99. const wxShareTag = ref('')
  100. const isInWx = window.isInWx
  101. let wx = window.wx
  102. // fetch('https://plceditor.worldflying.cn/api/build/getjsconfig', {
  103. // method: 'POST',
  104. // body: JSON.stringify({ url: location.origin + location.pathname + location.search })
  105. // })
  106. // .then((res) => res.json())
  107. // .then((res) => {
  108. // wx.config(res.data)
  109. // wx.ready(function () {
  110. // console.log('微信初始化成功')
  111. // showWxAppBtn.value = true
  112. // })
  113. // wx.error(function (res: any) {
  114. // console.log('微信初始化失败', res)
  115. // })
  116. // })
  117. const initWxEnv = () => {
  118. if (!window.isInWx) return showFailToast('请在微信中打开')
  119. const url = location.origin + location.pathname + location.search
  120. const wxConfigStr = localStorage.getItem(url)
  121. if (!wxConfigStr) showFailToast('初始化失败')
  122. else {
  123. const wxConfig = JSON.parse(wxConfigStr)
  124. wx.config(wxConfig)
  125. wx.ready(function () {
  126. console.log('微信初始化成功')
  127. })
  128. wx.error(function (res: any) {
  129. console.log('微信初始化失败', res)
  130. })
  131. }
  132. }
  133. initWxEnv()
  134. watch(
  135. () => route,
  136. () => {
  137. crtProject.value = projectList.value.find((item) => item.id === route.params.id)
  138. // console.log(JSON.stringify(crtProject.value))
  139. wxShareTag.value = `<wx-open-launch-weapp appid="wx4c5a777c71f2981c" style="width: 100%;" path="pages/sharefile/index?content=${encodeURIComponent(JSON.stringify({ ...crtProject.value, qrcodeType: 'worldflying_plc_editor' }))}&filename=${crtProject.value?.name}.jmpec"><template><text style="color: #896ef4;">分享</text></template></wx-open-launch-weapp>`
  140. let imgobjStr = localStorage.getItem('imgobj' + crtProject.value!.id)
  141. if (imgobjStr) {
  142. try {
  143. let imgobj = JSON.parse(imgobjStr)
  144. let now = new Date().getTime() // 当前时间戳
  145. if (now < imgobj.deadline) {
  146. crtProject.value!.isCompiled = true
  147. wxtag.value = `<wx-open-launch-weapp appid="wx4c5a777c71f2981c" style="width: 100%;" path="pages/index/rj45cfgbybt/plc/index?imgurl=${imgobj.url}"><template><text style="color: #7232dd;">烧录设备</text></template></wx-open-launch-weapp>`
  148. } else {
  149. crtProject.value!.isCompiled = false
  150. localStorage.removeItem('imgobj' + crtProject.value!.id)
  151. }
  152. } catch (e) {
  153. console.log(e)
  154. }
  155. }
  156. },
  157. {
  158. deep: true,
  159. immediate: true,
  160. once: true
  161. }
  162. )
  163. const showMorePopup = ref(false)
  164. const handleEditName = () => {
  165. showEditPopup.value = true
  166. showMorePopup.value = false
  167. newProjectName.value = crtProject.value!.name
  168. }
  169. const showEditPopup = ref(false)
  170. const newProjectName = ref('')
  171. const onSubmit = (values: Record<string, string>) => {
  172. console.log(values)
  173. const isExist = projectList.value.some(
  174. (item) => item.name === values.newProjectName && item.id !== crtProject.value?.id
  175. )
  176. if (isExist) {
  177. showFailToast('工程名称已存在')
  178. return
  179. } else {
  180. crtProject.value!.name = values.newProjectName
  181. wxShareTag.value = `<wx-open-launch-weapp appid="wx4c5a777c71f2981c" style="width: 100%;" path="pages/sharefile/index?content=${encodeURIComponent(JSON.stringify({ ...crtProject.value, qrcodeType: 'worldflying_plc_editor' }))}&filename=${crtProject.value?.name}.jmpec"><template><text style="color: #896ef4;">分享</text></template></wx-open-launch-weapp>`
  182. console.log(wxShareTag.value)
  183. handleCancel()
  184. }
  185. }
  186. const handleCancel = async () => {
  187. showEditPopup.value = false
  188. await nextTick()
  189. newProjectName.value = ''
  190. }
  191. const handleDelete = (val: string) => {
  192. if (val) {
  193. const project = projectList.value.find((item) => (item.id = crtProject.value!.id))
  194. if (project) {
  195. if (project.commandList.length === 1) return showFailToast('请至少保留一个任务!')
  196. project.commandList = project.commandList.filter((item) => item.id !== val)
  197. crtProject.value!.commandList = crtProject.value!.commandList.filter((item) => item.id !== val)
  198. if (crtProject.value?.isCompiled) {
  199. crtProject.value.isCompiled = false
  200. localStorage.removeItem('imgobj' + crtProject.value!.id)
  201. }
  202. }
  203. }
  204. }
  205. let flag = false
  206. let timer: any
  207. const handleAddCommond = () => {
  208. if (flag) return
  209. if (timer) clearTimeout(timer)
  210. flag = true
  211. // const lastCmdName = crtProject.value?.commandList[0].name || '任务'
  212. // const baseName = lastCmdName.replace(/\s*\-\d+/, '')
  213. let maxSuffix = 0
  214. // 遍历任务列表,找到与基础名称匹配的最大编号
  215. crtProject.value?.commandList.forEach((item) => {
  216. if (item.name.startsWith('任务')) {
  217. const match = item.name.match(/\-(\d+)/) // 匹配末尾的 "(数字)"
  218. if (match) {
  219. const suffix = parseInt(match[1], 10)
  220. if (suffix > maxSuffix) {
  221. maxSuffix = suffix
  222. }
  223. }
  224. }
  225. })
  226. // 生成新的任务名称
  227. const newSuffix = maxSuffix + 1
  228. const name = `任务-${newSuffix}`
  229. // let name = `任务${Math.floor(Date.now())}`
  230. crtProject.value!.commandList.unshift({
  231. id: '' + Date.now(),
  232. name,
  233. time: new Date().toLocaleString(),
  234. stepList: [],
  235. // x: 100,
  236. // y: 100 + crtProject.value!.commandList.length * 2000,
  237. parentId: crtProject.value!.id
  238. })
  239. if (crtProject.value?.isCompiled) {
  240. crtProject.value.isCompiled = false
  241. localStorage.removeItem('imgobj' + crtProject.value!.id)
  242. }
  243. timer = setTimeout(() => {
  244. flag = false
  245. }, 500)
  246. }
  247. // 文件编译
  248. // const getXMLFile = () => {
  249. // if (!crtProject.value) return
  250. // if (crtProject.value.commandList.length === 0) return showFailToast('请先添加任务!')
  251. // if (crtProject.value.commandList.length === 1 && crtProject.value.commandList[0].stepList.length === 0) {
  252. // return showFailToast('任务内容为空!')
  253. // }
  254. // if (crtProject.value.isCompiled) {
  255. // return showFailToast('工程已编译!')
  256. // }
  257. // const isExistExec = crtProject.value.commandList.some((item) =>
  258. // item.stepList.some((cItem) => cItem.type === 'exec' && cItem.list?.length !== 0)
  259. // )
  260. // if (!isExistExec) return showFailToast('请先添加执行任务!')
  261. // const loading = showLoadingToast({
  262. // message: '正在编译中...',
  263. // forbidClick: true,
  264. // duration: 0
  265. // })
  266. // let xml = ''
  267. // // 头部
  268. // xml += `<?xml version="1.0" encoding="UTF-8"?>
  269. // <project xmlns="http://www.plcopen.org/xml/tc6_0201" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:ns1="http://www.plcopen.org/xml/tc6.xsd">
  270. // <fileHeader companyName="${'未知'}" productName="${'未命名'}" productVersion="1.0" creationDateTime="${formatDateTime(new Date(), 'T')}" />
  271. // <contentHeader name="${crtProject.value.name}" modificationDateTime="${formatDateTime(new Date(), 'T')}">
  272. // <coordinateInfo>
  273. // <fbd>
  274. // <scaling x="10" y="10"/>
  275. // </fbd>
  276. // <ld>
  277. // <scaling x="10" y="10"/>
  278. // </ld>
  279. // <sfc>
  280. // <scaling x="10" y="10"/>
  281. // </sfc>
  282. // </coordinateInfo>
  283. // </contentHeader>
  284. // <types>
  285. // <dataTypes/>
  286. // <pous>
  287. // `
  288. // // <pou name="proogram0" pouType="program">
  289. // // <interface>
  290. // // <localVars>
  291. // const commandVarMap: Record<string, string> = {}
  292. // const weekMap: Record<string, number> = {
  293. // 周一: 4,
  294. // 周二: 5,
  295. // 周三: 6,
  296. // 周四: 0,
  297. // 周五: 1,
  298. // 周六: 2,
  299. // 周日: 3
  300. // }
  301. // const globalVarList = [
  302. // 'DI0',
  303. // 'DI1',
  304. // 'DI2',
  305. // 'DI3',
  306. // 'DI4',
  307. // 'DI5',
  308. // 'DI6',
  309. // 'DI7',
  310. // 'DI8',
  311. // 'DI9',
  312. // 'AI0',
  313. // 'AI1',
  314. // 'AI2',
  315. // 'AI3',
  316. // 'DO0',
  317. // 'DO1',
  318. // 'DO2',
  319. // 'DO3',
  320. // 'DO4',
  321. // 'DO5',
  322. // 'DO6',
  323. // 'DO7',
  324. // 'DO8',
  325. // 'DO9',
  326. // 'AO0',
  327. // 'AO1'
  328. // ]
  329. // let instanceXml = ''
  330. // let globalVarsXml = ''
  331. // globalVarList.forEach((item) => {
  332. // globalVarsXml += `<variable name="${item}">
  333. // <type><${item.includes('A') ? 'UINT' : 'BOOL'} /></type>
  334. // </variable>`
  335. // })
  336. // crtProject.value.commandList.forEach((item, index) => {
  337. // if (!item.stepList.some((cItem) => cItem.type === 'exec' && cItem.list?.length !== 0)) return
  338. // instanceXml += `<pouInstance name="instance${index}" typeName="program${index}"/>`
  339. // xml += `<pou name="program${index}" pouType="program">
  340. // <interface>
  341. // <externalVars>
  342. // ${globalVarsXml}
  343. // <variable name="CRT_DATA">
  344. // <type><DT /></type>
  345. // </variable>
  346. // </externalVars>
  347. // <localVars>
  348. // <variable name="MOD_HOUR">
  349. // <type><ULINT /></type>
  350. // <initialValue>
  351. // <simpleValue value="24" />
  352. // </initialValue>
  353. // </variable>
  354. // <variable name="HOURS">
  355. // <type><ULINT /></type>
  356. // <initialValue>
  357. // <simpleValue value="3600" />
  358. // </initialValue>
  359. // </variable>
  360. // <variable name="DAYS">
  361. // <type><ULINT /></type>
  362. // <initialValue>
  363. // <simpleValue value="86400" />
  364. // </initialValue>
  365. // </variable>
  366. // <variable name="MOD_WEEK">
  367. // <type><ULINT /></type>
  368. // <initialValue>
  369. // <simpleValue value="7" />
  370. // </initialValue>
  371. // </variable>
  372. // <variable name="MINUTE">
  373. // <type><ULINT /></type>
  374. // <initialValue>
  375. // <simpleValue value="60" />
  376. // </initialValue>
  377. // </variable>
  378. // <variable name="MUL_NUM">
  379. // <type><INT /></type>
  380. // <initialValue>
  381. // <simpleValue value="1" />
  382. // </initialValue>
  383. // </variable>
  384. // `
  385. // // 临时变量
  386. // // const tempVarNum = item.stepList.filter((cItem) => cItem.type === 'condition').length
  387. // const tempVarNum = item.stepList.length
  388. // for (let i = 1; i <= tempVarNum; i++) {
  389. // xml += `<variable name="temp${i - 1}">
  390. // <type><BOOL /></type>
  391. // </variable>`
  392. // }
  393. // // 定义所需变量
  394. // item.stepList.forEach((item, index) => {
  395. // if (item.type === 'delay') {
  396. // // RTC 数量
  397. // xml += `<variable name="TON${index}">
  398. // <type>
  399. // <derived name="TON" />
  400. // </type>
  401. // </variable>
  402. // <variable name="PT${index}">
  403. // <type>
  404. // <TIME />
  405. // </type>
  406. // <initialValue>
  407. // <simpleValue value="T#${item.value}s" />
  408. // </initialValue>
  409. // </variable>`
  410. // } else {
  411. // item.list?.forEach((cItem, cIndex) => {
  412. // // PT 数量
  413. // if (cItem.type === 'time') {
  414. // xml += `<variable name="RTC${index}_${cIndex}">
  415. // <type>
  416. // <derived name="RTC" />
  417. // </type>
  418. // </variable>`
  419. // const timeArr = cItem.value.split(':')
  420. // xml += `<variable name="HOUR${index}_${cIndex}">
  421. // <type><ULINT /></type>
  422. // <initialValue>
  423. // <simpleValue value="${+timeArr[0]}" />
  424. // </initialValue>
  425. // </variable>`
  426. // xml += `<variable name="MIN${index}_${cIndex}">
  427. // <type><ULINT /></type>
  428. // <initialValue>
  429. // <simpleValue value="${+timeArr[1]}" />
  430. // </initialValue>
  431. // </variable>`
  432. // if (Object.keys(weekMap).includes(cItem.label)) {
  433. // xml += `<variable name="RTC${index}_${cIndex}_WEEK">
  434. // <type><ULINT /></type>
  435. // <initialValue>
  436. // <simpleValue value="${weekMap[cItem.label]}" />
  437. // </initialValue>
  438. // </variable>`
  439. // } else if (cItem.label !== '每天') {
  440. // const timeArr = cItem.value.split('-')
  441. // xml += `<variable name="RTC${index}_${cIndex}_START">
  442. // <type><ULINT /></type>
  443. // <initialValue>
  444. // <simpleValue value="${new Date(timeArr[0] + '').getTime() / 1000}" />
  445. // </initialValue>
  446. // </variable>`
  447. // xml += `<variable name="RTC${index}_${cIndex}_END">
  448. // <type><ULINT /></type>
  449. // <initialValue>
  450. // <simpleValue value="${new Date(timeArr[2] + '').getTime() / 1000}" />
  451. // </initialValue>
  452. // </variable>`
  453. // }
  454. // } else if (cItem.type === 'input' && cItem.label.includes('AI')) {
  455. // // 判断AI变量
  456. // xml += `<variable name="COMPARE_AI${index}_${cIndex}">
  457. // <type><UINT /></type>
  458. // <initialValue>
  459. // <simpleValue value="${+cItem.value * 100}" />
  460. // </initialValue>
  461. // </variable>`
  462. // } else if (cItem.type === 'output' && cItem.label.includes('AO')) {
  463. // // 赋值AO变量
  464. // xml += `<variable name="SET_AI${index}_${cIndex}">
  465. // <type><UINT /></type>
  466. // <initialValue>
  467. // <simpleValue value="${+cItem.value * 100}" />
  468. // </initialValue>
  469. // </variable>`
  470. // }
  471. // })
  472. // }
  473. // })
  474. // xml += `</localVars></interface>`
  475. // xml += `<body><LD>`
  476. // // 左侧电源导轨
  477. // const firstStep = item.stepList[0]
  478. // // const powerRailH = firstStep.type === 'delay' ? 40 : 40 + 20 * firstStep.list!.length
  479. // xml += `<leftPowerRail localId="${item.id}" width="20" height="40">
  480. // <position x="${item.x}" y="${item.y}"/>`
  481. // // if (firstStep.type === 'delay') {
  482. // xml += `<connectionPointOut formalParameter="">`
  483. // xml += `<relPosition x="40" y="20"/>`
  484. // xml += `</connectionPointOut>`
  485. // // } else {
  486. // // for (let i = 1; i <= firstStep.list!.length; i++) {
  487. // // xml += `<connectionPointOut formalParameter="">`
  488. // // xml += `<relPosition x="20" y="${20 * i}"/>`
  489. // // xml += `</connectionPointOut>`
  490. // // }
  491. // // }
  492. // xml += `</leftPowerRail>`
  493. // let tempVarId = `99${index}`
  494. // item.stepList.forEach((sItem, sIndex) => {
  495. // let tempXML = ''
  496. // let tempConnectXML = ''
  497. // if (sItem.type === 'condition' || sItem.type === 'exec') {
  498. // for (let i = 0; i < sItem.list!.length; i++) {
  499. // const cItem = sItem.list![i]
  500. // if (cItem.label.includes('DI') || cItem.label.includes('DO')) {
  501. // xml += `<${cItem.label.includes('DI') ? 'contact' : 'coil'} localId="${cItem.id}" negated="${cItem.value === '打开'}" width="40" height="40">`
  502. // xml += `<position x="${cItem.x}" y="${cItem.y}" />
  503. // <connectionPointIn>
  504. // <relPosition x="-20" y="20" />
  505. // <connection refLocalId="${sIndex === 0 ? item.id : tempVarId}">
  506. // <position x="${sIndex === 0 ? item.x + 40 : sItem.x - 40}" y="${sItem.y + 20}" />
  507. // <position x="${cItem.x - 20}" y="${cItem.y + 20}" />
  508. // </connection>
  509. // </connectionPointIn>
  510. // <connectionPointOut>
  511. // <relPosition x="60" y="20"/>
  512. // </connectionPointOut>
  513. // <variable>${cItem.label}</variable>
  514. // `
  515. // xml += `</${cItem.label.includes('DI') ? 'contact' : 'coil'}>`
  516. // tempConnectXML += `
  517. // <connection refLocalId="${cItem.id}" >
  518. // <position x="${cItem.x + 60}" y="${cItem.y + 20}" />
  519. // <position x="${sItem.x - 120}" y="${sItem.y + 20}" />
  520. // </connection>`
  521. // } else if (cItem.type === 'time') {
  522. // let setTimeVarID = `${index + 1}${sIndex}${i}11`
  523. // // 赋值当前时间
  524. // xml += `
  525. // <inVariable localId="${setTimeVarID}" width="40" height="40" negated="false">
  526. // <position x="${cItem.x - 100}" y="${cItem.y + 200}" />
  527. // <connectionPointOut>
  528. // <relPosition x="60" y="20" />
  529. // </connectionPointOut>
  530. // <expression>CRT_DATA</expression>
  531. // </inVariable>`
  532. // let RTCID1 = `${index + 1}${sIndex}${i}12`
  533. // // 定义RTC变量
  534. // xml += `
  535. // <block
  536. // localId="${RTCID1}"
  537. // typeName="RTC"
  538. // instanceName="RTC${sIndex}_${i}"
  539. // width="80"
  540. // height="80"
  541. // >
  542. // <position x="${cItem.x}" y="${cItem.y}" />
  543. // <inputVariables>
  544. // <variable formalParameter="IN">
  545. // <connectionPointIn>
  546. // <relPosition x="-20" y="20" />
  547. // <connection refLocalId="${sIndex === 0 ? item.id : tempVarId}">
  548. // <position x="${sIndex === 0 ? item.x + 40 : sItem.x - 40}" y="${sItem.y + 20}" />
  549. // <position x="${cItem.x - 20}" y="${cItem.y + 20}" />
  550. // </connection>
  551. // </connectionPointIn>
  552. // </variable>
  553. // <variable formalParameter="PDT">
  554. // <connectionPointIn>
  555. // <relPosition x="-20" y="60" />
  556. // <connection refLocalId="${setTimeVarID}">
  557. // <position x="${cItem.x - 40}" y="${cItem.y + 220}" />
  558. // <position x="${cItem.x - 20}" y="${cItem.y + 60}" />
  559. // </connection>
  560. // </connectionPointIn>
  561. // </variable>
  562. // </inputVariables>
  563. // <inOutVariables />
  564. // <outputVariables>
  565. // <variable formalParameter="Q">
  566. // <connectionPointOut>
  567. // <relPosition x="100" y="20" />
  568. // </connectionPointOut>
  569. // </variable>
  570. // <variable formalParameter="CDT">
  571. // <connectionPointOut>
  572. // <relPosition x="100" y="60" />
  573. // </connectionPointOut>
  574. // </variable>
  575. // </outputVariables>
  576. // </block>
  577. // `
  578. // // DT TO ULINGT
  579. // let dtToULIntId1 = `${index + 1}${sIndex}${i}13`
  580. // xml += `
  581. // <block localId="${dtToULIntId1}" typeName="DT_TO_ULINT" width="100" height="40">
  582. // <position x="${cItem.x + 200}" y="${cItem.y}" />
  583. // <inputVariables>
  584. // <variable formalParameter="IN">
  585. // <connectionPointIn>
  586. // <relPosition x="-20" y="20" />
  587. // <connection refLocalId="${RTCID1}" formalParameter="CDT">
  588. // <position x="${cItem.x + 100}" y="${cItem.y + 60}" />
  589. // <position x="${cItem.x + 180}" y="${cItem.y + 20}" />
  590. // </connection>
  591. // </connectionPointIn>
  592. // </variable>
  593. // </inputVariables>
  594. // <inOutVariables />
  595. // <outputVariables>
  596. // <variable formalParameter="OUT">
  597. // <connectionPointOut>
  598. // <relPosition x="120" y="20" />
  599. // </connectionPointOut>
  600. // </variable>
  601. // </outputVariables>
  602. // </block>`
  603. // let joinXML = ''
  604. // let isJoin = false
  605. // if (Object.keys(weekMap).includes(cItem.label)) {
  606. // isJoin = true
  607. // let varId6 = `${index + 1}${sIndex}${i}14`
  608. // // 天被除数变量
  609. // xml += `
  610. // <inVariable localId="${varId6}" width="40" height="40" negated="false">
  611. // <position x="${cItem.x + 300}" y="${cItem.y + 200}" />
  612. // <connectionPointOut>
  613. // <relPosition x="60" y="20" />
  614. // </connectionPointOut>
  615. // <expression>DAYS</expression>
  616. // </inVariable>`
  617. // let DIVID3 = `${index + 1}${sIndex}${i}15`
  618. // // 计算天数
  619. // xml += `
  620. // <block localId="${DIVID3}" typeName="DIV" width="70" height="60">
  621. // <position x="${cItem.x + 400}" y="${cItem.y}" />
  622. // <inputVariables>
  623. // <variable formalParameter="IN1">
  624. // <connectionPointIn>
  625. // <relPosition x="-20" y="20" />
  626. // <connection refLocalId="${dtToULIntId1}" formalParameter="OUT">
  627. // <position x="${cItem.x + 320}" y="${cItem.y + 20}" />
  628. // <position x="${cItem.x + 380}" y="${cItem.y + 20}" />
  629. // </connection>
  630. // </connectionPointIn>
  631. // </variable>
  632. // <variable formalParameter="IN2">
  633. // <connectionPointIn>
  634. // <relPosition x="-20" y="40" />
  635. // <connection refLocalId="${varId6}">
  636. // <position x="${cItem.x + 360}" y="${cItem.y + 220}" />
  637. // <position x="${cItem.x + 380}" y="${cItem.y + 40}" />
  638. // </connection>
  639. // </connectionPointIn>
  640. // </variable>
  641. // </inputVariables>
  642. // <inOutVariables />
  643. // <outputVariables>
  644. // <variable formalParameter="OUT">
  645. // <connectionPointOut>
  646. // <relPosition x="90" y="20" />
  647. // </connectionPointOut>
  648. // </variable>
  649. // </outputVariables>
  650. // </block>
  651. // `
  652. // let varId7 = `${index + 1}${sIndex}${i}16`
  653. // // 取模变量
  654. // xml += `
  655. // <inVariable localId="${varId7}" width="40" height="40" negated="false">
  656. // <position x="${cItem.x + 500}" y="${cItem.y + 200}" />
  657. // <connectionPointOut>
  658. // <relPosition x="60" y="20" />
  659. // </connectionPointOut>
  660. // <expression>MOD_WEEK</expression>
  661. // </inVariable>`
  662. // let MODID4 = `${index + 1}${sIndex}${i}17`
  663. // // 计算当前为周几 0为周四
  664. // xml += `
  665. // <block localId="${MODID4}" typeName="MOD" width="70" height="60">
  666. // <position x="${cItem.x + 600}" y="${cItem.y}" />
  667. // <inputVariables>
  668. // <variable formalParameter="IN1">
  669. // <connectionPointIn>
  670. // <relPosition x="-20" y="20" />
  671. // <connection refLocalId="${DIVID3}" formalParameter="OUT">
  672. // <position x="${cItem.x + 490}" y="${cItem.y + 20}" />
  673. // <position x="${cItem.x + 580}" y="${cItem.y + 20}" />
  674. // </connection>
  675. // </connectionPointIn>
  676. // </variable>
  677. // <variable formalParameter="IN2">
  678. // <connectionPointIn>
  679. // <relPosition x="-20" y="40" />
  680. // <connection refLocalId="${varId7}">
  681. // <position x="${cItem.x + 560}" y="${cItem.y + 220}" />
  682. // <position x="${cItem.x + 580}" y="${cItem.y + 40}" />
  683. // </connection>
  684. // </connectionPointIn>
  685. // </variable>
  686. // </inputVariables>
  687. // <inOutVariables />
  688. // <outputVariables>
  689. // <variable formalParameter="OUT">
  690. // <connectionPointOut>
  691. // <relPosition x="90" y="20" />
  692. // </connectionPointOut>
  693. // </variable>
  694. // </outputVariables>
  695. // </block>
  696. // `
  697. // // 设置的周几变量
  698. // let weekVarId = `${index + 1}${sIndex}${i}18`
  699. // xml += `
  700. // <inVariable localId="${weekVarId}" width="40" height="40" negated="false">
  701. // <position x="${cItem.x + 700}" y="${cItem.y + 200}" />
  702. // <connectionPointOut>
  703. // <relPosition x="60" y="20" />
  704. // </connectionPointOut>
  705. // <expression>RTC${sIndex}_${i}_WEEK</expression>
  706. // </inVariable>`
  707. // let GTID3 = `${index + 1}${sIndex}${i}19`
  708. // // 判断是否为指定的周几(等于)
  709. // xml += `
  710. // <block localId="${GTID3}" typeName="EQ" width="70" height="60">
  711. // <position x="${cItem.x + 800}" y="${cItem.y}" />
  712. // <inputVariables>
  713. // <variable formalParameter="IN1">
  714. // <connectionPointIn>
  715. // <relPosition x="-20" y="20" />
  716. // <connection refLocalId="${MODID4}" formalParameter="OUT">
  717. // <position x="${cItem.x + 690}" y="${cItem.y + 20}" />
  718. // <position x="${cItem.x + 780}" y="${cItem.y + 20}" />
  719. // </connection>
  720. // </connectionPointIn>
  721. // </variable>
  722. // <variable formalParameter="IN2">
  723. // <connectionPointIn>
  724. // <relPosition x="-20" y="40" />
  725. // <connection refLocalId="${weekVarId}">
  726. // <position x="${cItem.x + 760}" y="${cItem.y + 20}" />
  727. // <position x="${cItem.x + 780}" y="${cItem.y + 20}" />
  728. // </connection>
  729. // </connectionPointIn>
  730. // </variable>
  731. // </inputVariables>
  732. // <inOutVariables />
  733. // <outputVariables>
  734. // <variable formalParameter="OUT">
  735. // <connectionPointOut>
  736. // <relPosition x="90" y="20" />
  737. // </connectionPointOut>
  738. // </variable>
  739. // </outputVariables>
  740. // </block>
  741. // `
  742. // joinXML += `
  743. // <variable formalParameter="EN">
  744. // <connectionPointIn>
  745. // <relPosition x="-20" y="20" />
  746. // <connection refLocalId="${GTID3}" formalParameter="OUT">
  747. // <position x="${cItem.x + 890}" y="${cItem.y + 20}" />
  748. // <position x="${cItem.x + 980}" y="${cItem.y + 20}" />
  749. // </connection>
  750. // </connectionPointIn>
  751. // </variable>
  752. // `
  753. // } else if (cItem.label !== '每天') {
  754. // isJoin = true
  755. // // 判断是否再日期范围内
  756. // let startTimeID = `${index + 1}${sIndex}37`
  757. // let endTimeID = `${index + 1}${sIndex}36`
  758. // // 开始时间变量
  759. // xml += `
  760. // <inVariable localId="${startTimeID}" width="40" height="40" negated="false">
  761. // <position x="${cItem.x + 300}" y="${cItem.y + 200}" />
  762. // <connectionPointOut>
  763. // <relPosition x="60" y="20" />
  764. // </connectionPointOut>
  765. // <expression>RTC${sIndex}_${i}_START</expression>
  766. // </inVariable>`
  767. // // 大于等于最小值
  768. // let GEID1 = `${index + 1}${sIndex}35`
  769. // xml += `
  770. // <block localId="${GEID1}" typeName="GE" width="70" height="60">
  771. // <position x="${cItem.x + 400}" y="${cItem.y}" />
  772. // <inputVariables>
  773. // <variable formalParameter="IN1">
  774. // <connectionPointIn>
  775. // <relPosition x="-20" y="20" />
  776. // <connection refLocalId="${dtToULIntId1}" formalParameter="OUT">
  777. // <position x="${cItem.x + 320}" y="${cItem.y + 20}" />
  778. // <position x="${cItem.x + 380}" y="${cItem.y + 20}" />
  779. // </connection>
  780. // </connectionPointIn>
  781. // </variable>
  782. // <variable formalParameter="IN2">
  783. // <connectionPointIn>
  784. // <relPosition x="-20" y="40" />
  785. // <connection refLocalId="${startTimeID}">
  786. // <position x="${cItem.x + 360}" y="${cItem.y + 220}" />
  787. // <position x="${cItem.x + 380}" y="${cItem.y + 40}" />
  788. // </connection>
  789. // </connectionPointIn>
  790. // </variable>
  791. // </inputVariables>
  792. // <inOutVariables />
  793. // <outputVariables>
  794. // <variable formalParameter="OUT">
  795. // <connectionPointOut>
  796. // <relPosition x="90" y="30" />
  797. // </connectionPointOut>
  798. // </variable>
  799. // </outputVariables>
  800. // </block>
  801. // `
  802. // // 结束时间变量
  803. // xml += `
  804. // <inVariable localId="${endTimeID}" width="40" height="40" negated="false">
  805. // <position x="${cItem.x + 500}" y="${cItem.y + 200}" />
  806. // <connectionPointOut>
  807. // <relPosition x="60" y="20" />
  808. // </connectionPointOut>
  809. // <expression>RTC${sIndex}_${i}_END</expression>
  810. // </inVariable>`
  811. // // 小于等于最大值
  812. // let LEID1 = `${index + 1}${sIndex}34`
  813. // xml += `
  814. // <block localId="${LEID1}" typeName="LE" width="70" height="60">
  815. // <position x="${cItem.x + 600}" y="${cItem.y}" />
  816. // <inputVariables>
  817. // <variable formalParameter="EN">
  818. // <connectionPointIn>
  819. // <relPosition x="-20" y="20" />
  820. // <connection refLocalId="${GEID1}" formalParameter="OUT">
  821. // <position x="${cItem.x + 490}" y="${cItem.y + 30}" />
  822. // <position x="${cItem.x + 580}" y="${cItem.y + 20}" />
  823. // </connection>
  824. // </connectionPointIn>
  825. // </variable>
  826. // <variable formalParameter="IN1">
  827. // <connectionPointIn>
  828. // <relPosition x="-20" y="40" />
  829. // <connection refLocalId="${dtToULIntId1}" formalParameter="OUT">
  830. // <position x="${cItem.x + 320}" y="${cItem.y + 20}" />
  831. // <position x="${cItem.x + 580}" y="${cItem.y + 40}" />
  832. // </connection>
  833. // </connectionPointIn>
  834. // </variable>
  835. // <variable formalParameter="IN2">
  836. // <connectionPointIn>
  837. // <relPosition x="-20" y="60" />
  838. // <connection refLocalId="${endTimeID}" formalParameter="OUT">
  839. // <position x="${cItem.x + 560}" y="${cItem.y + 220}" />
  840. // <position x="${cItem.x + 580}" y="${cItem.y + 60}" />
  841. // </connection>
  842. // </connectionPointIn>
  843. // </variable>
  844. // </inputVariables>
  845. // <inOutVariables />
  846. // <outputVariables>
  847. // <variable formalParameter="ENO">
  848. // <connectionPointOut>
  849. // <relPosition x="90" y="20" />
  850. // </connectionPointOut>
  851. // </variable>
  852. // <variable formalParameter="OUT">
  853. // <connectionPointOut>
  854. // <relPosition x="90" y="40" />
  855. // </connectionPointOut>
  856. // </variable>
  857. // </outputVariables>
  858. // </block>
  859. // `
  860. // joinXML += `
  861. // <variable formalParameter="EN">
  862. // <connectionPointIn>
  863. // <relPosition x="-20" y="20" />
  864. // <connection refLocalId="${LEID1}" formalParameter="OUT">
  865. // <position x="${cItem.x + 690}" y="${cItem.y + 40}" />
  866. // <position x="${cItem.x + 980}" y="${cItem.y + 20}" />
  867. // </connection>
  868. // </connectionPointIn>
  869. // </variable>
  870. // `
  871. // }
  872. // let varId2 = `${index + 1}${sIndex}${i}20`
  873. // // 小时被除数
  874. // xml += `
  875. // <inVariable localId="${varId2}" width="40" height="40" negated="false">
  876. // <position x="${cItem.x + 900}" y="${cItem.y + 200}" />
  877. // <connectionPointOut>
  878. // <relPosition x="60" y="20" />
  879. // </connectionPointOut>
  880. // <expression>HOURS</expression>
  881. // </inVariable>`
  882. // let DIVID1 = `${index + 1}${sIndex}${i}21`
  883. // // 计算小时
  884. // xml += `
  885. // <block localId="${DIVID1}" typeName="DIV" width="70" height="60">
  886. // <position x="${cItem.x + 1000}" y="${cItem.y}" />
  887. // <inputVariables>
  888. // ${joinXML}
  889. // <variable formalParameter="IN1">
  890. // <connectionPointIn>
  891. // <relPosition x="-20" y="${isJoin ? 40 : 20}" />
  892. // <connection refLocalId="${dtToULIntId1}" formalParameter="OUT">
  893. // <position x="${cItem.x + 320}" y="${cItem.y + 20}" />
  894. // <position x="${cItem.x + 980}" y="${cItem.y + (isJoin ? 40 : 20)}" />
  895. // </connection>
  896. // </connectionPointIn>
  897. // </variable>
  898. // <variable formalParameter="IN2">
  899. // <connectionPointIn>
  900. // <relPosition x="-20" y="${isJoin ? 60 : 40}" />
  901. // <connection refLocalId="${varId2}">
  902. // <position x="${cItem.x + 960}" y="${cItem.y + 220}" />
  903. // <position x="${cItem.x + 980}" y="${cItem.y + (isJoin ? 60 : 40)}" />
  904. // </connection>
  905. // </connectionPointIn>
  906. // </variable>
  907. // </inputVariables>
  908. // <inOutVariables />
  909. // <outputVariables>
  910. // ${
  911. // isJoin
  912. // ? `<variable formalParameter="ENO">
  913. // <connectionPointOut>
  914. // <relPosition x="90" y="20" />
  915. // </connectionPointOut>
  916. // </variable>`
  917. // : ''
  918. // }
  919. // <variable formalParameter="OUT">
  920. // <connectionPointOut>
  921. // <relPosition x="90" y="40" />
  922. // </connectionPointOut>
  923. // </variable>
  924. // </outputVariables>
  925. // </block>
  926. // `
  927. // let varId3 = `${index + 1}${sIndex}${i}22`
  928. // // 小时取模变量
  929. // xml += `
  930. // <inVariable localId="${varId3}" width="40" height="40" negated="false">
  931. // <position x="${cItem.x + 1100}" y="${cItem.y + 200}" />
  932. // <connectionPointOut>
  933. // <relPosition x="60" y="20" />
  934. // </connectionPointOut>
  935. // <expression>MOD_HOUR</expression>
  936. // </inVariable>`
  937. // let MODID1 = `${index + 1}${sIndex}${i}23`
  938. // // 计算当前时间为几点
  939. // xml += `
  940. // <block localId="${MODID1}" typeName="MOD" width="70" height="60">
  941. // <position x="${cItem.x + 1200}" y="${cItem.y}" />
  942. // <inputVariables>
  943. // <variable formalParameter="IN1">
  944. // <connectionPointIn>
  945. // <relPosition x="-20" y="20" />
  946. // <connection refLocalId="${DIVID1}" formalParameter="OUT">
  947. // <position x="${cItem.x + 1090}" y="${cItem.y + 40}" />
  948. // <position x="${cItem.x + 1180}" y="${cItem.y + 20}" />
  949. // </connection>
  950. // </connectionPointIn>
  951. // </variable>
  952. // <variable formalParameter="IN2">
  953. // <connectionPointIn>
  954. // <relPosition x="-20" y="40" />
  955. // <connection refLocalId="${varId3}">
  956. // <position x="${cItem.x + 1160}" y="${cItem.y + 220}" />
  957. // <position x="${cItem.x + 1180}" y="${cItem.y + 40}" />
  958. // </connection>
  959. // </connectionPointIn>
  960. // </variable>
  961. // </inputVariables>
  962. // <inOutVariables />
  963. // <outputVariables>
  964. // <variable formalParameter="OUT">
  965. // <connectionPointOut>
  966. // <relPosition x="90" y="20" />
  967. // </connectionPointOut>
  968. // </variable>
  969. // </outputVariables>
  970. // </block>
  971. // `
  972. // // 设置的小时数变量
  973. // let hourVarId = `${index + 1}${sIndex}${i}24`
  974. // xml += `
  975. // <inVariable localId="${hourVarId}" width="40" height="40" negated="false">
  976. // <position x="${cItem.x + 1300}" y="${cItem.y + 200}" />
  977. // <connectionPointOut>
  978. // <relPosition x="60" y="20" />
  979. // </connectionPointOut>
  980. // <expression>HOUR${sIndex}_${i}</expression>
  981. // </inVariable>`
  982. // let GTID1 = `${index + 1}${sIndex}${i}25`
  983. // // 判断小时数是否相等
  984. // xml += `
  985. // <block localId="${GTID1}" typeName="EQ" width="70" height="60">
  986. // <position x="${cItem.x + 1400}" y="${cItem.y}" />
  987. // <inputVariables>
  988. // <variable formalParameter="IN1">
  989. // <connectionPointIn>
  990. // <relPosition x="-20" y="20" />
  991. // <connection refLocalId="${MODID1}" formalParameter="OUT">
  992. // <position x="${cItem.x + 1290}" y="${cItem.y + 20}" />
  993. // <position x="${cItem.x + 1380}" y="${cItem.y + 20}" />
  994. // </connection>
  995. // </connectionPointIn>
  996. // </variable>
  997. // <variable formalParameter="IN2">
  998. // <connectionPointIn>
  999. // <relPosition x="-20" y="40" />
  1000. // <connection refLocalId="${hourVarId}" formalParameter="OUT">
  1001. // <position x="${cItem.x + 1360}" y="${cItem.y + 220}" />
  1002. // <position x="${cItem.x + 1380}" y="${cItem.y + 40}" />
  1003. // </connection>
  1004. // </connectionPointIn>
  1005. // </variable>
  1006. // </inputVariables>
  1007. // <inOutVariables />
  1008. // <outputVariables>
  1009. // <variable formalParameter="OUT">
  1010. // <connectionPointOut>
  1011. // <relPosition x="90" y="20" />
  1012. // </connectionPointOut>
  1013. // </variable>
  1014. // </outputVariables>
  1015. // </block>
  1016. // `
  1017. // let varId4 = `${index + 1}${sIndex}${i}26`
  1018. // // 分钟被除数
  1019. // xml += `
  1020. // <inVariable localId="${varId4}" width="40" height="40" negated="false">
  1021. // <position x="${cItem.x + 1500}" y="${cItem.y + 200}" />
  1022. // <connectionPointOut>
  1023. // <relPosition x="60" y="20" />
  1024. // </connectionPointOut>
  1025. // <expression>MINUTE</expression>
  1026. // </inVariable>`
  1027. // let DIVID2 = `${index + 1}${sIndex}${i}27`
  1028. // // 计算分钟
  1029. // xml += `
  1030. // <block localId="${DIVID2}" typeName="DIV" width="70" height="60">
  1031. // <position x="${cItem.x + 1600}" y="${cItem.y}" />
  1032. // <inputVariables>
  1033. // <variable formalParameter="EN">
  1034. // <connectionPointIn>
  1035. // <relPosition x="-20" y="20"/>
  1036. // <connection refLocalId="${GTID1}" formalParameter="OUT">
  1037. // <position x="${cItem.x + 1490}" y="${cItem.y + 20}"/>
  1038. // <position x="${cItem.x + 1580}" y="${cItem.y + 20}"/>
  1039. // </connection>
  1040. // </connectionPointIn>
  1041. // </variable>
  1042. // <variable formalParameter="IN1">
  1043. // <connectionPointIn>
  1044. // <relPosition x="-20" y="40" />
  1045. // <connection refLocalId="${dtToULIntId1}" formalParameter="OUT">
  1046. // <position x="${cItem.x + 320}" y="${cItem.y + 20}" />
  1047. // <position x="${cItem.x + 1580}" y="${cItem.y + 40}" />
  1048. // </connection>
  1049. // </connectionPointIn>
  1050. // </variable>
  1051. // <variable formalParameter="IN2">
  1052. // <connectionPointIn>
  1053. // <relPosition x="-20" y="60" />
  1054. // <connection refLocalId="${varId4}">
  1055. // <position x="${cItem.x + 1560}" y="${cItem.y + 220}" />
  1056. // <position x="${cItem.x + 1580}" y="${cItem.y + 60}" />
  1057. // </connection>
  1058. // </connectionPointIn>
  1059. // </variable>
  1060. // </inputVariables>
  1061. // <inOutVariables />
  1062. // <outputVariables>
  1063. // <variable formalParameter="ENO">
  1064. // <connectionPointOut>
  1065. // <relPosition x="90" y="20"/>
  1066. // </connectionPointOut>
  1067. // </variable>
  1068. // <variable formalParameter="OUT">
  1069. // <connectionPointOut>
  1070. // <relPosition x="90" y="40" />
  1071. // </connectionPointOut>
  1072. // </variable>
  1073. // </outputVariables>
  1074. // </block>
  1075. // `
  1076. // let varId5 = `${index + 1}${sIndex}${i}28`
  1077. // // 取模变量
  1078. // xml += `
  1079. // <inVariable localId="${varId5}" width="40" height="40" negated="false">
  1080. // <position x="${cItem.x + 1700}" y="${cItem.y + 200}" />
  1081. // <connectionPointOut>
  1082. // <relPosition x="60" y="20" />
  1083. // </connectionPointOut>
  1084. // <expression>MINUTE</expression>
  1085. // </inVariable>`
  1086. // let MODID2 = `${index + 1}${sIndex}${i}29`
  1087. // // 计算当前时间为几分
  1088. // xml += `
  1089. // <block localId="${MODID2}" typeName="MOD" width="70" height="60">
  1090. // <position x="${cItem.x + 1800}" y="${cItem.y}" />
  1091. // <inputVariables>
  1092. // <variable formalParameter="IN1">
  1093. // <connectionPointIn>
  1094. // <relPosition x="-20" y="20" />
  1095. // <connection refLocalId="${DIVID2}" formalParameter="OUT">
  1096. // <position x="${cItem.x + 1690}" y="${cItem.y + 40}" />
  1097. // <position x="${cItem.x + 1780}" y="${cItem.y + 20}" />
  1098. // </connection>
  1099. // </connectionPointIn>
  1100. // </variable>
  1101. // <variable formalParameter="IN2">
  1102. // <connectionPointIn>
  1103. // <relPosition x="-20" y="40" />
  1104. // <connection refLocalId="${varId5}">
  1105. // <position x="${cItem.x + 1760}" y="${cItem.y + 220}" />
  1106. // <position x="${cItem.x + 1780}" y="${cItem.y + 40}" />
  1107. // </connection>
  1108. // </connectionPointIn>
  1109. // </variable>
  1110. // </inputVariables>
  1111. // <inOutVariables />
  1112. // <outputVariables>
  1113. // <variable formalParameter="OUT">
  1114. // <connectionPointOut>
  1115. // <relPosition x="90" y="20" />
  1116. // </connectionPointOut>
  1117. // </variable>
  1118. // </outputVariables>
  1119. // </block>
  1120. // `
  1121. // // 设置的分钟数变量
  1122. // let minVarId = `${index + 1}${sIndex}${i}30`
  1123. // xml += `
  1124. // <inVariable localId="${minVarId}" width="40" height="40" negated="false">
  1125. // <position x="${cItem.x + 1900}" y="${cItem.y + 200}" />
  1126. // <connectionPointOut>
  1127. // <relPosition x="60" y="20" />
  1128. // </connectionPointOut>
  1129. // <expression>MIN${sIndex}_${i}</expression>
  1130. // </inVariable>`
  1131. // let GTID2 = `${index + 1}${sIndex}${i}31`
  1132. // // 判断分钟数是否相等
  1133. // xml += `
  1134. // <block localId="${GTID2}" typeName="EQ" width="70" height="60">
  1135. // <position x="${cItem.x + 2000}" y="${cItem.y}" />
  1136. // <inputVariables>
  1137. // <variable formalParameter="IN1">
  1138. // <connectionPointIn>
  1139. // <relPosition x="-20" y="20" />
  1140. // <connection refLocalId="${MODID2}" formalParameter="OUT">
  1141. // <position x="${cItem.x + 1990}" y="${cItem.y + 20}" />
  1142. // <position x="${cItem.x + 1980}" y="${cItem.y + 20}" />
  1143. // </connection>
  1144. // </connectionPointIn>
  1145. // </variable>
  1146. // <variable formalParameter="IN2">
  1147. // <connectionPointIn>
  1148. // <relPosition x="-20" y="40" />
  1149. // <connection refLocalId="${minVarId}">
  1150. // <position x="${cItem.x + 1960}" y="${cItem.y + 220}" />
  1151. // <position x="${cItem.x + 1980}" y="${cItem.y + 40}" />
  1152. // </connection>
  1153. // </connectionPointIn>
  1154. // </variable>
  1155. // </inputVariables>
  1156. // <inOutVariables />
  1157. // <outputVariables>
  1158. // <variable formalParameter="OUT">
  1159. // <connectionPointOut>
  1160. // <relPosition x="90" y="20" />
  1161. // </connectionPointOut>
  1162. // </variable>
  1163. // </outputVariables>
  1164. // </block>
  1165. // `
  1166. // tempConnectXML += `
  1167. // <connection refLocalId="${GTID2}" formalParameter="OUT">
  1168. // <position x="${cItem.x + 2090}" y="${cItem.y + 20}" />
  1169. // <position x="${sItem.x - 120}" y="${sItem.y + 20}" />
  1170. // </connection>`
  1171. // } else if (cItem.label.includes('AI')) {
  1172. // let compareVarID = `${index + 1}${sIndex}${i}33`
  1173. // // 对AI进行比较的变量
  1174. // xml += `
  1175. // <inVariable localId="${compareVarID}" width="40" height="40" negated="false">
  1176. // <position x="${cItem.x - 100}" y="${cItem.y + 200}" />
  1177. // <connectionPointOut>
  1178. // <relPosition x="60" y="20" />
  1179. // </connectionPointOut>
  1180. // <expression>COMPARE_AI${sIndex}_${i}</expression>
  1181. // </inVariable>`
  1182. // // AI变量
  1183. // let AIID = `${index + 1}${sIndex}${i}34`
  1184. // xml += `
  1185. // <inVariable localId="${AIID}" width="40" height="40" negated="false">
  1186. // <position x="${cItem.x - 100}" y="${cItem.y + 200}" />
  1187. // <connectionPointOut>
  1188. // <relPosition x="60" y="20" />
  1189. // </connectionPointOut>
  1190. // <expression>${cItem.label}</expression>
  1191. // </inVariable>`
  1192. // let compareBlockID = `${index + 1}${sIndex}${i}35`
  1193. // let operationMap: Record<string, string> = {
  1194. // '≥': 'GE',
  1195. // '≤': 'LE',
  1196. // '>': 'GT',
  1197. // '<': 'LT',
  1198. // '=': 'EQ',
  1199. // '≠': 'NE'
  1200. // }
  1201. // xml += `<block localId="${compareBlockID}" typeName="${operationMap[cItem.operation!]}" width="70" height="60">
  1202. // <position x="${cItem.x}" y="${cItem.y + 200}" />
  1203. // <inputVariables>
  1204. // <variable formalParameter="IN1">
  1205. // <connectionPointIn>
  1206. // <relPosition x="-20" y="40" />
  1207. // <connection refLocalId="${compareVarID}" formalParameter="OUT">
  1208. // <position x="${cItem.x - 40}" y="${cItem.y + 220}" />
  1209. // <position x="${cItem.x - 20}" y="${cItem.y + 240}" />
  1210. // </connection>
  1211. // </connectionPointIn>
  1212. // </variable>
  1213. // <variable formalParameter="IN2">
  1214. // <connectionPointIn>
  1215. // <relPosition x="-20" y="60" />
  1216. // <connection refLocalId="${AIID}" formalParameter="OUT">
  1217. // <position x="${cItem.x - 40}" y="${cItem.y + 220}" />
  1218. // <position x="${cItem.x - 20}" y="${cItem.y + 260}" />
  1219. // </connection>
  1220. // </connectionPointIn>
  1221. // </variable>
  1222. // </inputVariables>
  1223. // <inOutVariables />
  1224. // <outputVariables>
  1225. // <variable formalParameter="OUT">
  1226. // <connectionPointOut>
  1227. // <relPosition x="90" y="20" />
  1228. // </connectionPointOut>
  1229. // </variable>
  1230. // </outputVariables>
  1231. // </block>`
  1232. // tempConnectXML += `
  1233. // <connection refLocalId="${compareBlockID}" formalParameter="OUT">
  1234. // <position x="${cItem.x + 690}" y="${cItem.y + 20}" />
  1235. // <position x="${sItem.x - 120}" y="${sItem.y + 20}" />
  1236. // </connection>`
  1237. // } else if (cItem.label.includes('AO')) {
  1238. // // 乘数id
  1239. // let mulID = `${index + 1}${sIndex}${i}36`
  1240. // xml += `
  1241. // <inVariable localId="${mulID}" width="40" height="40" negated="false">
  1242. // <position x="${cItem.x - 100}" y="${cItem.y + 200}" />
  1243. // <connectionPointOut>
  1244. // <relPosition x="60" y="20" />
  1245. // </connectionPointOut>
  1246. // <expression>MUL_NUM</expression>
  1247. // </inVariable>`
  1248. // // 赋值id
  1249. // let setID = `${index + 1}${sIndex}${i}37`
  1250. // xml += `
  1251. // <inVariable localId="${setID}" width="40" height="40" negated="false">
  1252. // <position x="${cItem.x - 100}" y="${cItem.y + 200}" />
  1253. // <connectionPointOut>
  1254. // <relPosition x="60" y="20" />
  1255. // </connectionPointOut>
  1256. // <expression>SET_AI${sIndex}_${i}</expression>
  1257. // </inVariable>`
  1258. // let mulBlockId = `${index + 1}${sIndex}${i}38`
  1259. // xml += `
  1260. // <block localId="${mulBlockId}" typeName="DIV" width="70" height="60">
  1261. // <position x="${cItem.x}" y="${cItem.y}" />
  1262. // <inputVariables>
  1263. // <variable formalParameter="EN">
  1264. // <connectionPointIn>
  1265. // <relPosition x="-20" y="20"/>
  1266. // <connection refLocalId="${sIndex === 0 ? item.id : tempVarId}" formalParameter="OUT">
  1267. // <position x="${sIndex === 0 ? item.x + 40 : sItem.x - 40}" y="${sItem.y + 20}"/>
  1268. // <position x="${cItem.x - 20}" y="${cItem.y + 20}"/>
  1269. // </connection>
  1270. // </connectionPointIn>
  1271. // </variable>
  1272. // <variable formalParameter="IN1">
  1273. // <connectionPointIn>
  1274. // <relPosition x="-20" y="40" />
  1275. // <connection refLocalId="${mulID}" formalParameter="OUT">
  1276. // <position x="${cItem.x - 40}" y="${cItem.y + 220}" />
  1277. // <position x="${cItem.x - 20}" y="${cItem.y + 40}" />
  1278. // </connection>
  1279. // </connectionPointIn>
  1280. // </variable>
  1281. // <variable formalParameter="IN2">
  1282. // <connectionPointIn>
  1283. // <relPosition x="-20" y="60" />
  1284. // <connection refLocalId="${setID}">
  1285. // <position x="${cItem.x - 40}" y="${cItem.y + 220}" />
  1286. // <position x="${cItem.x - 20}" y="${cItem.y + 60}" />
  1287. // </connection>
  1288. // </connectionPointIn>
  1289. // </variable>
  1290. // </inputVariables>
  1291. // <inOutVariables />
  1292. // <outputVariables>
  1293. // <variable formalParameter="ENO">
  1294. // <connectionPointOut>
  1295. // <relPosition x="90" y="20"/>
  1296. // </connectionPointOut>
  1297. // </variable>
  1298. // <variable formalParameter="OUT">
  1299. // <connectionPointOut>
  1300. // <relPosition x="90" y="40" />
  1301. // </connectionPointOut>
  1302. // </variable>
  1303. // </outputVariables>
  1304. // </block>
  1305. // `
  1306. // // 赋值AO变量
  1307. // let AOID = `${index + 1}${sIndex}${i}38`
  1308. // xml += `
  1309. // <outVariable localId="${AOID}" width="40" height="40" negated="false">
  1310. // <position x="${cItem.x - 400}" y="${cItem.y + 200}" />
  1311. // <connectionPointIn>
  1312. // <relPosition x="60" y="20" />
  1313. // <connection refLocalId="${mulBlockId}" formalParameter="OUT">
  1314. // <position x="${cItem.x + 90}" y="${cItem.y + 4}" />
  1315. // <position x="${cItem.x - 340}" y="${cItem.y + 20}" />
  1316. // </connection>
  1317. // </connectionPointIn>
  1318. // <expression>${cItem.label}</expression>
  1319. // </outVariable>`
  1320. // }
  1321. // }
  1322. // } else if (sItem.type === 'delay') {
  1323. // // 延时时间变量
  1324. // let delayVarId = `${index + 1}${sIndex}32`
  1325. // xml += `
  1326. // <inVariable localId="${delayVarId}" width="40" height="40" negated="false">
  1327. // <position x="${sItem.x - 100}" y="${sItem.y + 200}" />
  1328. // <connectionPointOut>
  1329. // <relPosition x="60" y="20" />
  1330. // </connectionPointOut>
  1331. // <expression>PT${sIndex}</expression>
  1332. // </inVariable>
  1333. // `
  1334. // xml += `
  1335. // <block
  1336. // localId="${sItem.id}"
  1337. // typeName="TON"
  1338. // instanceName="TON${sIndex}"
  1339. // width="50"
  1340. // height="60"
  1341. // >
  1342. // <position x="${sItem.x}" y="${sItem.y}" />
  1343. // <inputVariables>
  1344. // <variable formalParameter="IN">
  1345. // <connectionPointIn>
  1346. // <relPosition x="-20" y="20" />
  1347. // <connection refLocalId="${sIndex === 0 ? item.id : tempVarId}">
  1348. // <position x="${sIndex === 0 ? item.x + 40 : sItem.x - 40}" y="${sItem.y + 20}" />
  1349. // <position x="${sItem.x - 20}" y="${sItem.y + 20}" />
  1350. // </connection>
  1351. // </connectionPointIn>
  1352. // </variable>
  1353. // <variable formalParameter="PT">
  1354. // <connectionPointIn>
  1355. // <relPosition x="-20" y="40" />
  1356. // <connection refLocalId="${delayVarId}">
  1357. // <position x="${sItem.x - 40}" y="${sItem.y + 220}" />
  1358. // <position x="${sItem.x - 20}" y="${sItem.y + 40}" />
  1359. // </connection>
  1360. // </connectionPointIn>
  1361. // </variable>
  1362. // </inputVariables>
  1363. // <inOutVariables />
  1364. // <outputVariables>
  1365. // <variable formalParameter="Q">
  1366. // <connectionPointOut>
  1367. // <relPosition x="70" y="20" />
  1368. // </connectionPointOut>
  1369. // </variable>
  1370. // <variable formalParameter="ET">
  1371. // <connectionPointOut>
  1372. // <relPosition x="70" y="40" />
  1373. // </connectionPointOut>
  1374. // </variable>
  1375. // </outputVariables>
  1376. // </block>
  1377. // `
  1378. // tempConnectXML += `
  1379. // <connection refLocalId="${sItem.id}" formalParameter="Q">
  1380. // <position x="${sItem.x + 70}" y="${sItem.y + 20}" />
  1381. // <position x="${sItem.x - 120}" y="${sItem.y + 20}" />
  1382. // </connection>`
  1383. // }
  1384. // if (sIndex !== 0) {
  1385. // tempVarId = `${index + 1}${sIndex}33`
  1386. // }
  1387. // tempXML += `<inOutVariable localId="${tempVarId}" width="40" height="40" negatedOut="false" negatedIn="false">
  1388. // <position x="${sItem.x - 100}" y="${sItem.y}" />
  1389. // <connectionPointIn>
  1390. // <relPosition x="-20" y="20" />
  1391. // `
  1392. // tempXML += tempConnectXML
  1393. // tempXML += `
  1394. // </connectionPointIn>
  1395. // <connectionPointOut>
  1396. // <relPosition x="60" y="20"/>
  1397. // </connectionPointOut>
  1398. // <expression>temp${sIndex}</expression></inOutVariable>`
  1399. // if (sIndex !== item.stepList.length - 1) {
  1400. // xml += tempXML
  1401. // }
  1402. // })
  1403. // xml += `
  1404. // </LD>
  1405. // </body>
  1406. // </pou>
  1407. // `
  1408. // })
  1409. // // 尾部
  1410. // xml += `
  1411. // </pous>
  1412. // </types>
  1413. // <instances>
  1414. // <configurations>
  1415. // <configuration name="Config0">
  1416. // <resource name="Res0">
  1417. // <task name="task0" priority="0" interval="T#20ms">
  1418. // ${instanceXml}
  1419. // </task>
  1420. // </resource>
  1421. // <globalVars>
  1422. // ${globalVarsXml}
  1423. // <variable name="CRT_DATA">
  1424. // <type><DT /></type>
  1425. // <initialValue>
  1426. // <simpleValue value="DT#${formatDateTime(new Date(), '-')}" />
  1427. // </initialValue>
  1428. // </variable>
  1429. // </globalVars>
  1430. // </configuration>
  1431. // </configurations>
  1432. // </instances>
  1433. // </project>`
  1434. // // console.log(xml)
  1435. // // 生成文件下载
  1436. // // const blob = new Blob([xml], { type: 'text/plain;charset=utf-8' })
  1437. // // const formdata = new FormData()
  1438. // // formdata.append('file', blob, 'project.xml')
  1439. // const params = {
  1440. // devicetype: 'PLC101',
  1441. // xml
  1442. // }
  1443. // fetch('https://plceditor.worldflying.cn/api/build/buildcode', {
  1444. // method: 'POST',
  1445. // body: JSON.stringify(params),
  1446. // headers: {
  1447. // 'Content-Type': 'application/x-www-form-urlencoded',
  1448. // 'Content-Length': xml.length + ''
  1449. // }
  1450. // })
  1451. // .then((res) => res.json())
  1452. // .then((res) => {
  1453. // console.log(res)
  1454. // // 关闭loading
  1455. // loading.close()
  1456. // if (res.errcode === 3000) {
  1457. // showFailToast('编译失败!')
  1458. // } else if (res.errcode === 0) {
  1459. // localStorage.setItem(
  1460. // 'imgobj' + crtProject.value!.id,
  1461. // JSON.stringify({
  1462. // url: res.url,
  1463. // deadline: new Date().getTime() + 30 * 60 * 1000
  1464. // })
  1465. // )
  1466. // crtProject.value!.isCompiled = true
  1467. // crtProject.value!.CompileTime = formatDateTime(new Date())!
  1468. // wxtag.value = `<wx-open-launch-weapp appid="wx4c5a777c71f2981c" path="pages/index/rj45cfgbybt/plc/index?imgurl=${res.url}"><template><text style="color: #7232dd">烧录设备</text></template></wx-open-launch-weapp>`
  1469. // console.log('本地存储成功')
  1470. // showSuccessToast('编译成功!')
  1471. // }
  1472. // })
  1473. // // const link = document.createElement('a')
  1474. // // link.href = URL.createObjectURL(blob)
  1475. // // link.download = 'project.xml'
  1476. // // link.click()
  1477. // // URL.revokeObjectURL(link.href)
  1478. // // link.remove()
  1479. // }
  1480. const get_c_code = (codetype: string) => {
  1481. if (!crtProject.value) return
  1482. if (crtProject.value.commandList.length === 0) return showFailToast('请先添加任务!')
  1483. if (crtProject.value.commandList.length === 1 && crtProject.value.commandList[0].stepList.length === 0) {
  1484. return showFailToast('任务内容为空!')
  1485. }
  1486. if (crtProject.value.isCompiled && codetype === 'wx') {
  1487. return showFailToast('工程已编译!')
  1488. }
  1489. const isExistExec = crtProject.value.commandList.some((item) =>
  1490. item.stepList.some((cItem) => cItem.type === 'exec' && cItem.list?.length !== 0)
  1491. )
  1492. if (!isExistExec) return showFailToast('请先添加执行任务!')
  1493. const loading = showLoadingToast({
  1494. message: '正在编译中...',
  1495. forbidClick: true,
  1496. duration: 0
  1497. })
  1498. const valMap: Record<string, number> = {
  1499. 闭合: 1,
  1500. 断开: 0,
  1501. 打开: 0,
  1502. }
  1503. const weekMap: Record<string, number> = {
  1504. 每天: 0,
  1505. 周一: 1,
  1506. 周二: 2,
  1507. 周三: 3,
  1508. 周四: 4,
  1509. 周五: 5,
  1510. 周六: 6,
  1511. 周日: 7,
  1512. 仅一次: 8
  1513. }
  1514. const operationMap: Record<string, string> = {
  1515. '=': '==',
  1516. '<': '<',
  1517. '>': '>',
  1518. '≤': '<=',
  1519. '≥': '>=',
  1520. '≠': '!='
  1521. }
  1522. const timeOperationMap: Record<string, number> = {
  1523. 等于: 0,
  1524. 早于: 1,
  1525. 晚于: 2
  1526. }
  1527. let c_code = ''
  1528. if (crtProject.value) {
  1529. c_code = `#include "iec_def.h"
  1530. extern uint8_t coil[20];
  1531. extern uint16_t ai[4];
  1532. extern uint16_t ao[2];`
  1533. let call_code = ''
  1534. crtProject.value.commandList.forEach((item, index) => {
  1535. if (!item.stepList.some((cItem) => cItem.type === 'exec' && cItem.list?.length !== 0)) return
  1536. call_code += `
  1537. PROGRAM${index}_body(&p${index}, &p${index}_delay);`
  1538. let body_code = `
  1539. static struct pt p${index};
  1540. static TIME p${index}_delay;
  1541. static PT_THREAD(PROGRAM${index}_body(struct pt *pt, TIME *pt_delay))
  1542. {
  1543. PT_BEGIN(pt);`
  1544. item.stepList.forEach((sItem, sIndex) => {
  1545. if (sItem.type === 'delay') {
  1546. body_code += `
  1547. delay_set(pt_delay, ${+sItem.value! * 1000});
  1548. PT_WAIT_UNTIL(pt, delay_expired(pt_delay));`
  1549. } else {
  1550. let condition_code = ''
  1551. sItem.list!.forEach((cItem, cIndex) => {
  1552. const linkStr = cIndex === sItem.list!.length - 1 ? '' : ' || '
  1553. if (sItem.type === 'condition') {
  1554. if (cItem.label.includes('DI')) {
  1555. const idx = cItem.label.slice(2)
  1556. condition_code += `GET_DI(${idx}) == ${valMap[cItem.value]}${linkStr}`
  1557. }
  1558. if (cItem.label.includes('AI')) {
  1559. const idx = cItem.label.slice(2)
  1560. condition_code += `GET_AI(${idx}) ${operationMap[cItem.operation!]} ${+cItem.value * 100}${linkStr}`
  1561. }
  1562. if (cItem.type === 'time') {
  1563. const timeArr = cItem.value.split(':')
  1564. const sec = Math.floor(
  1565. (new Date(new Date().setHours(+timeArr[0], +timeArr[1], 0, 0)).getTime() -
  1566. new Date(new Date().setHours(0, 0, 0, 0)).getTime()) /
  1567. 1000
  1568. )
  1569. const operation = weekMap[cItem.label!]
  1570. const timeOperation = timeOperationMap[cItem.operation!]
  1571. if ((operation || operation === 0) && operation !== 8) {
  1572. condition_code += `time_compare(${sec},${timeOperation}, 0, 0, ${operation})${linkStr}`
  1573. } else if (cItem.label.includes('-')) {
  1574. // 自定义时间
  1575. const dateArr = cItem.label!.split('-')
  1576. const start = Math.floor(new Date(dateArr[0]).getTime() / 1000)
  1577. const end = Math.floor(new Date(dateArr[1]).getTime() / 1000)
  1578. condition_code += `time_compare(${sec},${timeOperation}, ${start}, ${end}, 8)${linkStr}`
  1579. console.log(condition_code)
  1580. } else {
  1581. // 特定某一天
  1582. const start = Math.floor(new Date(cItem.label).getTime() / 1000)
  1583. condition_code += `time_compare(${sec},${timeOperation}, ${start}, ${start + 24 * 60 * 60}, 8)${linkStr}`
  1584. }
  1585. }
  1586. } else if (sItem.type === 'exec') {
  1587. if (cItem.label.includes('DO')) {
  1588. const idx = cItem.label.slice(2)
  1589. body_code += `
  1590. SET_DO(${idx}, ${valMap[cItem.value]});`
  1591. }
  1592. if (cItem.label.includes('AO')) {
  1593. const idx = cItem.label.slice(2)
  1594. body_code += `
  1595. SET_AO(${idx}, ${+cItem.value * 100});`
  1596. }
  1597. }
  1598. })
  1599. if (condition_code !== '') {
  1600. body_code += `
  1601. PT_WAIT_UNTIL(pt, ${condition_code});`
  1602. }
  1603. }
  1604. })
  1605. body_code += `
  1606. PT_END(pt);
  1607. }`
  1608. c_code += body_code
  1609. })
  1610. c_code += `
  1611. void IEC_run(void)
  1612. {${call_code}
  1613. }`
  1614. }
  1615. console.log(c_code)
  1616. const params = {
  1617. devicetype: 'PLC101',
  1618. xml: c_code,
  1619. codetype,
  1620. getlog: true
  1621. }
  1622. fetch('https://plceditor.worldflying.cn/api/build/buildcode', {
  1623. method: 'POST',
  1624. body: JSON.stringify(params),
  1625. headers: {
  1626. 'Content-Type': 'application/x-www-form-urlencoded'
  1627. }
  1628. })
  1629. .then((res) => res.json())
  1630. .then((res) => {
  1631. console.log(res)
  1632. // 关闭loading
  1633. loading.close()
  1634. if (res.errcode === 3000) {
  1635. showFailToast('操作失败!')
  1636. } else if (res.errcode === 0) {
  1637. if (codetype === 'wx') {
  1638. localStorage.setItem(
  1639. 'imgobj' + crtProject.value!.id,
  1640. JSON.stringify({
  1641. url: res.url,
  1642. deadline: new Date().getTime() + 30 * 60 * 1000
  1643. })
  1644. )
  1645. crtProject.value!.isCompiled = true
  1646. crtProject.value!.CompileTime = formatDateTime(new Date())!
  1647. wxtag.value = `<wx-open-launch-weapp appid="wx4c5a777c71f2981c" style="width: 100%;" path="pages/index/rj45cfgbybt/plc/index?imgurl=${res.url}"><template><text style="color: #7232dd;">烧录设备</text></template></wx-open-launch-weapp>`
  1648. console.log('本地存储成功')
  1649. showSuccessToast('编译成功!')
  1650. } else {
  1651. router.push({
  1652. name: 'runtime',
  1653. query: {
  1654. id: crtProject.value!.id,
  1655. url: res.url
  1656. }
  1657. })
  1658. }
  1659. }
  1660. })
  1661. }
  1662. // 删除工程
  1663. const delProject = () => {
  1664. if (crtProject.value) {
  1665. showConfirmDialog({
  1666. title: '提示',
  1667. message: '确定要删除这个工程吗'
  1668. })
  1669. .then(() => {
  1670. // on confirm
  1671. console.log(projectList.value)
  1672. localStorage.removeItem('imgobj' + crtProject.value!.id)
  1673. projectList.value = projectList.value.filter((item) => crtProject.value?.id !== item.id)
  1674. router.replace({ name: 'Automate' })
  1675. })
  1676. .catch(() => {
  1677. // on cancel
  1678. })
  1679. }
  1680. }
  1681. const showSharePopup = ref(false)
  1682. const shareImg = ref('')
  1683. const qrcodeCanvas = ref<HTMLCanvasElement>()
  1684. const shareProject = async () => {
  1685. if (!window.isInWx) return
  1686. showSharePopup.value = true
  1687. await nextTick()
  1688. // const canvasEl = document.createElement('canvas')
  1689. // const ratio = window.devicePixelRatio
  1690. // const windowWidth = window.innerWidth
  1691. // const windowHeight = window.innerHeight
  1692. // const minWindowSize = Math.floor(Math.min(windowWidth, windowHeight) * 0.7)
  1693. // canvasEl!.style.width = `${minWindowSize}px`
  1694. // canvasEl!.style.height = `${minWindowSize}px`
  1695. // canvasEl!.width = minWindowSize * ratio
  1696. // canvasEl!.height = minWindowSize * ratio
  1697. // qrcode.toCanvas(canvasEl!, JSON.stringify({ ...crtProject.value, qrcodeType: 'worldflying_plc_editor' }), {
  1698. // width: minWindowSize * 2
  1699. // })
  1700. // const canvasEl1 = document.createElement('canvas')
  1701. // canvasEl1.style.width = `${minWindowSize}px`
  1702. // canvasEl1.style.height = `${minWindowSize + 50}px`
  1703. // canvasEl1.width = minWindowSize * ratio
  1704. // canvasEl1.height = (minWindowSize + 50) * ratio
  1705. // const ctx = canvasEl1?.getContext('2d')
  1706. // if (ctx) {
  1707. // ctx.imageSmoothingEnabled = false
  1708. // const fontSize = 16 * ratio
  1709. // ctx.font = `${fontSize}px Arial`
  1710. // ctx.fillText(`工程名称:${crtProject.value?.name}`, 20 * ratio, 35 * ratio)
  1711. // ctx.drawImage(canvasEl, 0, 50 * ratio, minWindowSize * ratio, minWindowSize * ratio)
  1712. // // shareImg.value = canvasEl1.toDataURL('image/png', 1)
  1713. // canvasEl1.toBlob((blob) => {
  1714. // if (!blob) return
  1715. // shareImg.value = URL.createObjectURL(blob)
  1716. // }, 'image/png', 1)
  1717. // }
  1718. qrcode.toDataURL(
  1719. JSON.stringify({ ...crtProject.value, qrcodeType: 'worldflying_plc_editor' }),
  1720. function (error, url) {
  1721. if (error) console.error(error)
  1722. // console.log(url)
  1723. const ratio = devicePixelRatio
  1724. const canvasEl = document.createElement('canvas')
  1725. const windowWidth = window.innerWidth
  1726. const windowHeight = window.innerHeight
  1727. const minWindowSize = Math.floor(Math.min(windowWidth, windowHeight) * 0.7)
  1728. canvasEl.style.width = `${minWindowSize}px`
  1729. canvasEl.style.height = `${minWindowSize + 120}px`
  1730. canvasEl.width = minWindowSize * ratio
  1731. canvasEl.height = (minWindowSize + 120) * ratio
  1732. const ctx = canvasEl?.getContext('2d')
  1733. if (ctx) {
  1734. const fontSize = 12 * ratio
  1735. ctx.font = `${fontSize}px Arial`
  1736. ctx.fillText(`工程名称:${crtProject.value?.name}`, 5 * ratio, 35 * ratio)
  1737. const img = new Image()
  1738. img.src = url
  1739. img.onload = function () {
  1740. ctx.imageSmoothingEnabled = false
  1741. ctx.drawImage(img, 0, 40 * ratio, minWindowSize * ratio, minWindowSize * ratio)
  1742. const tipText = '请打开沃航PLC手机编辑器,通过编辑页面导入该图片'
  1743. const arr = []
  1744. for (let i = 1; i <= tipText.length; i++) {
  1745. const tipMsg = ctx.measureText(tipText.slice(0, i))
  1746. if (Math.ceil(tipMsg.width / ratio) > minWindowSize) {
  1747. arr.push(tipText.slice(0, i - 1))
  1748. arr.push(tipText.slice(i - 1))
  1749. break
  1750. }
  1751. if (i === tipText.length) {
  1752. arr.push(tipText)
  1753. }
  1754. }
  1755. arr.forEach((item, index) => {
  1756. ctx.fillText(item, 5 * ratio, (minWindowSize + 55 + index * 15) * ratio)
  1757. })
  1758. const companyText = '沃航科技有限公司'
  1759. const companyMsg = ctx.measureText(companyText)
  1760. ctx.fillText(companyText, (minWindowSize - 10) * ratio - companyMsg.width, (minWindowSize + 100) * ratio)
  1761. shareImg.value = canvasEl.toDataURL('image/png', 1)
  1762. // canvasEl.toBlob(
  1763. // (blob) => {
  1764. // if (!blob) return
  1765. // shareImg.value = URL.createObjectURL(blob)
  1766. // },
  1767. // 'image/png',
  1768. // )
  1769. }
  1770. }
  1771. canvasEl.remove()
  1772. }
  1773. )
  1774. }
  1775. const getSTFile = () => {
  1776. if (!crtProject.value) return
  1777. let st = ''
  1778. crtProject.value.commandList.forEach((item, index) => {
  1779. st += `
  1780. PROGRAM program${index}
  1781. VAR
  1782. DI0: BOOL
  1783. DI1: BOOL
  1784. AI0: INT
  1785. AI1: INT
  1786. DO0: BOOL
  1787. DO1: BOOL
  1788. AO0: INT
  1789. AO1: INT
  1790. `
  1791. const tempVarNum = item.stepList.length
  1792. for (let i = 1; i <= tempVarNum; i++) {
  1793. st += `TEMP${i}: BOOL`
  1794. }
  1795. })
  1796. }
  1797. let copyStatus = false
  1798. let copyTimer: any
  1799. // 复制任务
  1800. const copyCommand = (cmd: CommandType) => {
  1801. console.log(copyStatus)
  1802. if (copyStatus) return
  1803. if (copyTimer) clearTimeout(copyTimer)
  1804. copyStatus = true
  1805. // 提取基础名称和编号
  1806. const baseName = cmd.name.replace(/\s*\(\d+\)/, '') // 去掉末尾的 "(数字)"
  1807. let maxSuffix = 0
  1808. // 遍历任务列表,找到与基础名称匹配的最大编号
  1809. crtProject.value?.commandList.forEach((item) => {
  1810. if (item.name.startsWith(baseName)) {
  1811. const match = item.name.match(/\((\d+)\)/) // 匹配末尾的 "(数字)"
  1812. if (match) {
  1813. const suffix = parseInt(match[1], 10)
  1814. if (suffix > maxSuffix) {
  1815. maxSuffix = suffix
  1816. }
  1817. }
  1818. }
  1819. })
  1820. // 生成新的任务名称
  1821. const newSuffix = maxSuffix + 1
  1822. const name = `${baseName}(${newSuffix})`
  1823. const id = '' + Date.now()
  1824. const time = new Date().toLocaleString()
  1825. crtProject.value?.commandList.unshift({
  1826. ...deepClone(cmd),
  1827. name,
  1828. id,
  1829. time
  1830. })
  1831. copyTimer = setTimeout(() => {
  1832. copyStatus = false
  1833. }, 500)
  1834. }
  1835. </script>
  1836. <style scoped>
  1837. .project-info {
  1838. padding: 16px 0 0;
  1839. height: 100%;
  1840. overflow: hidden;
  1841. }
  1842. .van-button {
  1843. padding: 2px 8px;
  1844. }
  1845. .more .van-button {
  1846. padding: 2px 16px;
  1847. }
  1848. .header {
  1849. padding: 0 16px 16px;
  1850. display: flex;
  1851. justify-content: space-between;
  1852. align-items: center;
  1853. }
  1854. .header .project-name {
  1855. height: 100%;
  1856. max-width: 70%;
  1857. display: flex;
  1858. gap: 4px;
  1859. align-items: center;
  1860. justify-content: center;
  1861. }
  1862. .header .project-name .name {
  1863. overflow: hidden;
  1864. white-space: nowrap;
  1865. text-overflow: ellipsis;
  1866. max-width: 70%;
  1867. }
  1868. .command-container {
  1869. height: calc(100% - 65px);
  1870. padding-bottom: 16px;
  1871. overflow: auto;
  1872. }
  1873. .command-container :deep(.van-cell__value) {
  1874. width: 32px;
  1875. flex: none;
  1876. }
  1877. .command-container :deep(.van-cell__title) {
  1878. overflow: hidden;
  1879. white-space: nowrap;
  1880. text-overflow: ellipsis;
  1881. }
  1882. .command-container :deep(.van-swipe-cell__right) {
  1883. }
  1884. .del-button {
  1885. width: 64px;
  1886. height: 100%;
  1887. }
  1888. .van-cell {
  1889. justify-content: space-between;
  1890. align-items: center;
  1891. margin-bottom: 2px;
  1892. gap: 16px;
  1893. }
  1894. .add-btn {
  1895. position: fixed;
  1896. bottom: 64px;
  1897. left: 50%;
  1898. transform: translateX(-50%);
  1899. width: 70%;
  1900. }
  1901. .van-button-group {
  1902. margin: 16px;
  1903. display: flex;
  1904. justify-content: flex-end;
  1905. gap: 8px;
  1906. }
  1907. .share-container {
  1908. padding: 16px;
  1909. display: flex;
  1910. justify-content: center;
  1911. flex-direction: column;
  1912. align-items: center;
  1913. }
  1914. .share-container .tip {
  1915. margin: 16px 0;
  1916. font-size: 18px;
  1917. }
  1918. .iconfont {
  1919. font-size: 24px;
  1920. }
  1921. .wx-tag {
  1922. display: flex;
  1923. width: 100%;
  1924. }
  1925. </style>