ProjectInfo.vue 80 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995
  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('DO')) {
  1559. const idx = cItem.label.slice(2)
  1560. condition_code += `GET_DO(${idx}) == ${valMap[cItem.value]}${linkStr}`
  1561. }
  1562. if (cItem.label.includes('AI')) {
  1563. const idx = cItem.label.slice(2)
  1564. condition_code += `GET_AI(${idx}) ${operationMap[cItem.operation!]} ${+cItem.value * 1000}${linkStr}`
  1565. }
  1566. if (cItem.label.includes('AO')) {
  1567. const idx = cItem.label.slice(2)
  1568. condition_code += `GET_AO(${idx}) ${operationMap[cItem.operation!]} ${+cItem.value * 1000}${linkStr}`
  1569. }
  1570. if (cItem.type === 'time') {
  1571. const timeArr = cItem.value.split(':')
  1572. const sec = Math.floor(
  1573. (new Date(new Date().setHours(+timeArr[0], +timeArr[1], 0, 0)).getTime() -
  1574. new Date(new Date().setHours(0, 0, 0, 0)).getTime()) /
  1575. 1000
  1576. )
  1577. const operation = weekMap[cItem.label!]
  1578. const timeOperation = timeOperationMap[cItem.operation!]
  1579. if ((operation || operation === 0) && operation !== 8) {
  1580. condition_code += `time_compare(${sec},${timeOperation}, 0, 0, ${operation})${linkStr}`
  1581. } else if (cItem.label.includes('-')) {
  1582. // 自定义时间
  1583. const dateArr = cItem.label!.split('-')
  1584. const start = Math.floor(new Date(dateArr[0]).getTime() / 1000)
  1585. const end = Math.floor(new Date(dateArr[1]).getTime() / 1000)
  1586. condition_code += `time_compare(${sec},${timeOperation}, ${start}, ${end}, 8)${linkStr}`
  1587. console.log(condition_code)
  1588. } else {
  1589. // 特定某一天
  1590. const start = Math.floor(new Date(cItem.label).getTime() / 1000)
  1591. condition_code += `time_compare(${sec},${timeOperation}, ${start}, ${start + 24 * 60 * 60}, 8)${linkStr}`
  1592. }
  1593. }
  1594. } else if (sItem.type === 'exec') {
  1595. if (cItem.label.includes('DO')) {
  1596. const idx = cItem.label.slice(2)
  1597. body_code += `
  1598. SET_DO(${idx}, ${valMap[cItem.value]});`
  1599. }
  1600. if (cItem.label.includes('AO')) {
  1601. const idx = cItem.label.slice(2)
  1602. body_code += `
  1603. SET_AO(${idx}, ${+cItem.value * 1000});`
  1604. }
  1605. }
  1606. })
  1607. if (condition_code !== '') {
  1608. body_code += `
  1609. PT_WAIT_UNTIL(pt, ${condition_code});`
  1610. }
  1611. }
  1612. })
  1613. body_code += `
  1614. PT_END(pt);
  1615. }`
  1616. c_code += body_code
  1617. })
  1618. c_code += `
  1619. void IEC_run(void)
  1620. {${call_code}
  1621. }`
  1622. }
  1623. console.log(c_code)
  1624. const params = {
  1625. devicetype: 'PLC101',
  1626. xml: c_code,
  1627. codetype,
  1628. getlog: true
  1629. }
  1630. fetch('https://plceditor.worldflying.cn/api/build/buildcode', {
  1631. method: 'POST',
  1632. body: JSON.stringify(params),
  1633. headers: {
  1634. 'Content-Type': 'application/x-www-form-urlencoded'
  1635. }
  1636. })
  1637. .then((res) => res.json())
  1638. .then((res) => {
  1639. console.log(res)
  1640. // 关闭loading
  1641. loading.close()
  1642. if (res.errcode === 3000) {
  1643. showFailToast('操作失败!')
  1644. } else if (res.errcode === 0) {
  1645. if (codetype === 'wx') {
  1646. localStorage.setItem(
  1647. 'imgobj' + crtProject.value!.id,
  1648. JSON.stringify({
  1649. url: res.url,
  1650. deadline: new Date().getTime() + 30 * 60 * 1000
  1651. })
  1652. )
  1653. crtProject.value!.isCompiled = true
  1654. crtProject.value!.CompileTime = formatDateTime(new Date())!
  1655. 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>`
  1656. console.log('本地存储成功')
  1657. showSuccessToast('编译成功!')
  1658. } else {
  1659. router.push({
  1660. name: 'runtime',
  1661. query: {
  1662. id: crtProject.value!.id,
  1663. url: res.url
  1664. }
  1665. })
  1666. }
  1667. }
  1668. })
  1669. }
  1670. // 删除工程
  1671. const delProject = () => {
  1672. if (crtProject.value) {
  1673. showConfirmDialog({
  1674. title: '提示',
  1675. message: '确定要删除这个工程吗'
  1676. })
  1677. .then(() => {
  1678. // on confirm
  1679. console.log(projectList.value)
  1680. localStorage.removeItem('imgobj' + crtProject.value!.id)
  1681. projectList.value = projectList.value.filter((item) => crtProject.value?.id !== item.id)
  1682. router.replace({ name: 'Automate' })
  1683. })
  1684. .catch(() => {
  1685. // on cancel
  1686. })
  1687. }
  1688. }
  1689. const showSharePopup = ref(false)
  1690. const shareImg = ref('')
  1691. const qrcodeCanvas = ref<HTMLCanvasElement>()
  1692. const shareProject = async () => {
  1693. if (!window.isInWx) return
  1694. showSharePopup.value = true
  1695. await nextTick()
  1696. // const canvasEl = document.createElement('canvas')
  1697. // const ratio = window.devicePixelRatio
  1698. // const windowWidth = window.innerWidth
  1699. // const windowHeight = window.innerHeight
  1700. // const minWindowSize = Math.floor(Math.min(windowWidth, windowHeight) * 0.7)
  1701. // canvasEl!.style.width = `${minWindowSize}px`
  1702. // canvasEl!.style.height = `${minWindowSize}px`
  1703. // canvasEl!.width = minWindowSize * ratio
  1704. // canvasEl!.height = minWindowSize * ratio
  1705. // qrcode.toCanvas(canvasEl!, JSON.stringify({ ...crtProject.value, qrcodeType: 'worldflying_plc_editor' }), {
  1706. // width: minWindowSize * 2
  1707. // })
  1708. // const canvasEl1 = document.createElement('canvas')
  1709. // canvasEl1.style.width = `${minWindowSize}px`
  1710. // canvasEl1.style.height = `${minWindowSize + 50}px`
  1711. // canvasEl1.width = minWindowSize * ratio
  1712. // canvasEl1.height = (minWindowSize + 50) * ratio
  1713. // const ctx = canvasEl1?.getContext('2d')
  1714. // if (ctx) {
  1715. // ctx.imageSmoothingEnabled = false
  1716. // const fontSize = 16 * ratio
  1717. // ctx.font = `${fontSize}px Arial`
  1718. // ctx.fillText(`工程名称:${crtProject.value?.name}`, 20 * ratio, 35 * ratio)
  1719. // ctx.drawImage(canvasEl, 0, 50 * ratio, minWindowSize * ratio, minWindowSize * ratio)
  1720. // // shareImg.value = canvasEl1.toDataURL('image/png', 1)
  1721. // canvasEl1.toBlob((blob) => {
  1722. // if (!blob) return
  1723. // shareImg.value = URL.createObjectURL(blob)
  1724. // }, 'image/png', 1)
  1725. // }
  1726. qrcode.toDataURL(
  1727. JSON.stringify({ ...crtProject.value, qrcodeType: 'worldflying_plc_editor' }),
  1728. function (error, url) {
  1729. if (error) console.error(error)
  1730. // console.log(url)
  1731. const ratio = devicePixelRatio
  1732. const canvasEl = document.createElement('canvas')
  1733. const windowWidth = window.innerWidth
  1734. const windowHeight = window.innerHeight
  1735. const minWindowSize = Math.floor(Math.min(windowWidth, windowHeight) * 0.7)
  1736. canvasEl.style.width = `${minWindowSize}px`
  1737. canvasEl.style.height = `${minWindowSize + 120}px`
  1738. canvasEl.width = minWindowSize * ratio
  1739. canvasEl.height = (minWindowSize + 120) * ratio
  1740. const ctx = canvasEl?.getContext('2d')
  1741. if (ctx) {
  1742. const fontSize = 12 * ratio
  1743. ctx.font = `${fontSize}px Arial`
  1744. ctx.fillText(`工程名称:${crtProject.value?.name}`, 5 * ratio, 35 * ratio)
  1745. const img = new Image()
  1746. img.src = url
  1747. img.onload = function () {
  1748. ctx.imageSmoothingEnabled = false
  1749. ctx.drawImage(img, 0, 40 * ratio, minWindowSize * ratio, minWindowSize * ratio)
  1750. const tipText = '请打开沃航PLC手机编辑器,通过编辑页面导入该图片'
  1751. const arr = []
  1752. for (let i = 1; i <= tipText.length; i++) {
  1753. const tipMsg = ctx.measureText(tipText.slice(0, i))
  1754. if (Math.ceil(tipMsg.width / ratio) > minWindowSize) {
  1755. arr.push(tipText.slice(0, i - 1))
  1756. arr.push(tipText.slice(i - 1))
  1757. break
  1758. }
  1759. if (i === tipText.length) {
  1760. arr.push(tipText)
  1761. }
  1762. }
  1763. arr.forEach((item, index) => {
  1764. ctx.fillText(item, 5 * ratio, (minWindowSize + 55 + index * 15) * ratio)
  1765. })
  1766. const companyText = '沃航科技有限公司'
  1767. const companyMsg = ctx.measureText(companyText)
  1768. ctx.fillText(companyText, (minWindowSize - 10) * ratio - companyMsg.width, (minWindowSize + 100) * ratio)
  1769. shareImg.value = canvasEl.toDataURL('image/png', 1)
  1770. // canvasEl.toBlob(
  1771. // (blob) => {
  1772. // if (!blob) return
  1773. // shareImg.value = URL.createObjectURL(blob)
  1774. // },
  1775. // 'image/png',
  1776. // )
  1777. }
  1778. }
  1779. canvasEl.remove()
  1780. }
  1781. )
  1782. }
  1783. const getSTFile = () => {
  1784. if (!crtProject.value) return
  1785. let st = ''
  1786. crtProject.value.commandList.forEach((item, index) => {
  1787. st += `
  1788. PROGRAM program${index}
  1789. VAR
  1790. DI0: BOOL
  1791. DI1: BOOL
  1792. AI0: INT
  1793. AI1: INT
  1794. DO0: BOOL
  1795. DO1: BOOL
  1796. AO0: INT
  1797. AO1: INT
  1798. `
  1799. const tempVarNum = item.stepList.length
  1800. for (let i = 1; i <= tempVarNum; i++) {
  1801. st += `TEMP${i}: BOOL`
  1802. }
  1803. })
  1804. }
  1805. let copyStatus = false
  1806. let copyTimer: any
  1807. // 复制任务
  1808. const copyCommand = (cmd: CommandType) => {
  1809. console.log(copyStatus)
  1810. if (copyStatus) return
  1811. if (copyTimer) clearTimeout(copyTimer)
  1812. copyStatus = true
  1813. // 提取基础名称和编号
  1814. const baseName = cmd.name.replace(/\s*\(\d+\)/, '') // 去掉末尾的 "(数字)"
  1815. let maxSuffix = 0
  1816. // 遍历任务列表,找到与基础名称匹配的最大编号
  1817. crtProject.value?.commandList.forEach((item) => {
  1818. if (item.name.startsWith(baseName)) {
  1819. const match = item.name.match(/\((\d+)\)/) // 匹配末尾的 "(数字)"
  1820. if (match) {
  1821. const suffix = parseInt(match[1], 10)
  1822. if (suffix > maxSuffix) {
  1823. maxSuffix = suffix
  1824. }
  1825. }
  1826. }
  1827. })
  1828. // 生成新的任务名称
  1829. const newSuffix = maxSuffix + 1
  1830. const name = `${baseName}(${newSuffix})`
  1831. const id = '' + Date.now()
  1832. const time = new Date().toLocaleString()
  1833. crtProject.value?.commandList.unshift({
  1834. ...deepClone(cmd),
  1835. name,
  1836. id,
  1837. time
  1838. })
  1839. copyTimer = setTimeout(() => {
  1840. copyStatus = false
  1841. }, 500)
  1842. }
  1843. </script>
  1844. <style scoped>
  1845. .project-info {
  1846. padding: 16px 0 0;
  1847. height: 100%;
  1848. overflow: hidden;
  1849. }
  1850. .van-button {
  1851. padding: 2px 8px;
  1852. }
  1853. .more .van-button {
  1854. padding: 2px 16px;
  1855. }
  1856. .header {
  1857. padding: 0 16px 16px;
  1858. display: flex;
  1859. justify-content: space-between;
  1860. align-items: center;
  1861. }
  1862. .header .project-name {
  1863. height: 100%;
  1864. max-width: 70%;
  1865. display: flex;
  1866. gap: 4px;
  1867. align-items: center;
  1868. justify-content: center;
  1869. }
  1870. .header .project-name .name {
  1871. overflow: hidden;
  1872. white-space: nowrap;
  1873. text-overflow: ellipsis;
  1874. max-width: 70%;
  1875. }
  1876. .command-container {
  1877. height: calc(100% - 65px);
  1878. padding-bottom: 16px;
  1879. overflow: auto;
  1880. }
  1881. .command-container :deep(.van-cell__value) {
  1882. width: 32px;
  1883. flex: none;
  1884. }
  1885. .command-container :deep(.van-cell__title) {
  1886. overflow: hidden;
  1887. white-space: nowrap;
  1888. text-overflow: ellipsis;
  1889. }
  1890. .command-container :deep(.van-swipe-cell__right) {
  1891. }
  1892. .del-button {
  1893. width: 64px;
  1894. height: 100%;
  1895. }
  1896. .van-cell {
  1897. justify-content: space-between;
  1898. align-items: center;
  1899. margin-bottom: 2px;
  1900. gap: 16px;
  1901. }
  1902. .add-btn {
  1903. position: fixed;
  1904. bottom: 64px;
  1905. left: 50%;
  1906. transform: translateX(-50%);
  1907. width: 70%;
  1908. }
  1909. .van-button-group {
  1910. margin: 16px;
  1911. display: flex;
  1912. justify-content: flex-end;
  1913. gap: 8px;
  1914. }
  1915. .share-container {
  1916. padding: 16px;
  1917. display: flex;
  1918. justify-content: center;
  1919. flex-direction: column;
  1920. align-items: center;
  1921. }
  1922. .share-container .tip {
  1923. margin: 16px 0;
  1924. font-size: 18px;
  1925. }
  1926. .iconfont {
  1927. font-size: 24px;
  1928. }
  1929. .wx-tag {
  1930. display: flex;
  1931. width: 100%;
  1932. }
  1933. </style>