Commit fc86ebac60858ac345e9dfcfc4b103d0f9b70f1c

Authored by xp.Huang
2 parents 5b3b3a2f 2042e711

Merge branch 'main_dev' into 'main'

Main dev

See merge request yunteng/thingskit-scada!265
Showing 43 changed files with 323 additions and 105 deletions
  1 +FROM nginx:latest
  2 +
  3 +COPY ./dist/ /usr/share/nginx/html/
  4 +COPY default.conf /etc/nginx/conf.d/default.conf
  5 +
  6 +EXPOSE 8083
... ...
  1 +server {
  2 + listen 80;
  3 + listen [::]:80;
  4 + server_name 192.168.1.48;
  5 + #charset koi8-r;
  6 + #access_log /var/log/nginx/host.access.log main;
  7 +
  8 + root /usr/share/nginx/html;
  9 + index index.html index.htm;
  10 + try_files $uri $uri/ /index.html;
  11 +
  12 +
  13 +
  14 + location /api/ {
  15 + proxy_pass http://192.168.1.48:8080;
  16 + proxy_http_version 1.1;
  17 + proxy_set_header Upgrade $http_upgrade;
  18 + proxy_set_header Connection "Upgrade";
  19 + proxy_set_header Host $host;
  20 + proxy_cache_bypass $http_upgrade;
  21 + }
  22 +
  23 + location /yt/ {
  24 + proxy_pass http://192.168.1.48:8080;
  25 + proxy_http_version 1.1;
  26 + proxy_set_header Upgrade $http_upgrade;
  27 + proxy_set_header Connection "Upgrade";
  28 + proxy_set_header Host $host;
  29 + proxy_cache_bypass $http_upgrade;
  30 + }
  31 +
  32 + location /upload/ {
  33 + proxy_pass http://192.168.1.48:8080;
  34 + proxy_http_version 1.1;
  35 + proxy_set_header Upgrade $http_upgrade;
  36 + proxy_set_header Connection "Upgrade";
  37 + proxy_set_header Host $host;
  38 + proxy_cache_bypass $http_upgrade;
  39 + }
  40 +
  41 + #error_page 404 /404.html;
  42 +
  43 + # redirect server error pages to the static page /50x.html
  44 + #
  45 + error_page 500 502 503 504 /50x.html;
  46 + location = /50x.html {
  47 + root /usr/share/nginx/html;
  48 + }
  49 +}
\ No newline at end of file
... ...
... ... @@ -4296,8 +4296,13 @@ App.prototype.loadFile = function (id, sameWindow, file, success, force) {
4296 4296 document.getElementById('first-text-animation-text').querySelector('text').innerHTML = platformInfo?.name || window.PROJECT_ENV?.shortName
4297 4297 document.getElementById('first-text-animation').style.display = 'block'
4298 4298 if (this.appIcon) {
4299   - this.appIcon.style.backgroundImage = `url(${platformInfo?.logo || `${getProxyPrefix()}/logo.png`})`
  4299 + this.appIcon.style.backgroundImage = `url(${this.getAppIcon()})`
4300 4300 }
  4301 +
  4302 + const favicon = this.getAppFavicon()
  4303 + const faviconEl = document.querySelector('link[rel~="icon"]')
  4304 + faviconEl.href = favicon
  4305 +
4301 4306 const handleLoadContent = async () => {
4302 4307 /**
4303 4308 * @typedef ConfigurationContentListItemType
... ... @@ -5672,16 +5677,36 @@ App.prototype.save = function (name, done) {
5672 5677 // const data = `${Graph.xmlDeclaration}\n${this.getFileData(true, null, null, null, true, true, null, null, null, false)}`;
5673 5678 // this.currentFile.setData(data)
5674 5679
5675   - const allCells = this.editor.graph.getModel().cells || {}
  5680 + const graph = this.editor.graph
  5681 + const model = graph.model
  5682 + const pages = this.pages
  5683 +
  5684 + const currentPageContentId = this.ui.currentPage.getId()
  5685 + let originalPage
  5686 + const contentPageInfos = pages.map(page => {
  5687 + this.ui.selectPage(page)
  5688 + const cells = model.getChildCells(graph.getDefaultParent())
  5689 + const nodeIds = cells.map(cell => cell.getId())
  5690 + const contentId = this.ui.currentPage.getId()
  5691 +
  5692 + if (contentId === currentPageContentId)
  5693 + originalPage = page
  5694 +
  5695 + return {
  5696 + nodeIds,
  5697 + contentId
  5698 + }
  5699 + })
  5700 + originalPage && this.ui.selectPage(originalPage)
  5701 +
5676 5702 await doSaveConfigurationContent({
5677 5703 configurationContentList: [
5678 5704 {
5679 5705 id: currentFile.getHash(),
5680 5706 content: this.currentFile.getData(),
5681   - contentId: this.currentPage.getId(),
5682 5707 type: 1,
5683   - nodeIds: Object.keys(allCells),
5684   - name: this.currentPage.getName()
  5708 + name: this.currentPage.getName(),
  5709 + contentPageInfos
5685 5710 }
5686 5711 ],
5687 5712 configurationName: currentFile.title,
... ... @@ -6192,20 +6217,51 @@ App.prototype.convertFile = function (url, filename, mimeType, extension, succes
6192 6217 }
6193 6218 }
6194 6219
  6220 +App.prototype.isFromEdge = function () {
  6221 + const params = useParseParams()
  6222 + return params?.from === 'edge'
  6223 +}
  6224 +
  6225 +App.prototype.getAppIcon = function () {
  6226 + const platformInfo = getPlatformInfo()
  6227 +
  6228 + if (this.isFromEdge()) {
  6229 + if (platformInfo && platformInfo?.image) {
  6230 + return platformInfo?.image
  6231 + }
  6232 + return Editor.edgeLogoImage
  6233 + } else {
  6234 + if (platformInfo && platformInfo?.logo) {
  6235 + return platformInfo.logo
  6236 + }
  6237 +
  6238 + return Editor.logoImage
  6239 + }
  6240 +}
  6241 +
  6242 +App.prototype.getAppFavicon = function () {
  6243 + const platformInfo = getPlatformInfo()
  6244 + if (this.isFromEdge()) {
  6245 + if (platformInfo && platformInfo?.favicon) {
  6246 + return platformInfo?.favicon
  6247 + }
  6248 + return Editor.edgeLogoImage
  6249 + } else {
  6250 + if (platformInfo && platformInfo?.icon) {
  6251 + return platformInfo.icon
  6252 + }
  6253 + return Editor.logoImage
  6254 + }
  6255 +}
  6256 +
6195 6257 /**
6196 6258 * Adds the listener for automatically saving the diagram for local changes.
6197 6259 */
6198 6260 App.prototype.updateHeader = function () {
6199 6261 if (this.menubar != null) {
6200 6262 // TODO Thingskit 修改logo
6201   - Editor.logoImage = ''
6202   - const platformInfo = getPlatformInfo()
6203   - if (platformInfo && platformInfo?.logo) {
6204   - const { logo } = platformInfo
6205   - Editor.logoImage = logo
6206   - }
6207 6263
6208   - const logo = `url(${Editor.logoImage})`
  6264 + const logo = `url(${this.getAppIcon()})`
6209 6265 this.appIcon = document.createElement('a')
6210 6266 this.appIcon.style.display = 'block'
6211 6267 this.appIcon.style.position = 'absolute'
... ...
... ... @@ -1554,6 +1554,7 @@ var BackgroundImageDialog = function (editorUi, applyFn, img, color, showColor)
1554 1554 widthInput.style.marginLeft = '8px';
1555 1555 widthInput.style.marginRight = '16px';
1556 1556 widthInput.value = (img != null && !isPageLink) ? img.width : '';
  1557 + widthInput.setAttribute('disabled', true)
1557 1558
1558 1559 div.appendChild(widthInput);
1559 1560
... ... @@ -1565,6 +1566,7 @@ var BackgroundImageDialog = function (editorUi, applyFn, img, color, showColor)
1565 1566 heightInput.style.marginLeft = '8px';
1566 1567 heightInput.style.marginRight = '16px';
1567 1568 heightInput.value = (img != null && !isPageLink) ? img.height : '';
  1569 + heightInput.setAttribute('disabled', true)
1568 1570
1569 1571 div.appendChild(heightInput);
1570 1572 mxUtils.br(div);
... ...
... ... @@ -140,7 +140,9 @@
140 140 /**
141 141 *
142 142 */
143   - Editor.logoImage = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIKICAgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMzA2LjE4NSAxMjAuMjk2IgogICB2aWV3Qm94PSIyNCAyNiA2OCA2OCIKICAgeT0iMHB4IgogICB4PSIwcHgiCiAgIHZlcnNpb249IjEuMSI+CiAgIAkgPGc+PGxpbmUKICAgICAgIHkyPSI3Mi4zOTQiCiAgICAgICB4Mj0iNDEuMDYxIgogICAgICAgeTE9IjQzLjM4NCIKICAgICAgIHgxPSI1OC4wNjkiCiAgICAgICBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiCiAgICAgICBzdHJva2Utd2lkdGg9IjMuNTUyOCIKICAgICAgIHN0cm9rZT0iI0ZGRkZGRiIKICAgICAgIGZpbGw9Im5vbmUiIC8+PGxpbmUKICAgICAgIHkyPSI3Mi4zOTQiCiAgICAgICB4Mj0iNzUuMDc2IgogICAgICAgeTE9IjQzLjM4NCIKICAgICAgIHgxPSI1OC4wNjgiCiAgICAgICBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiCiAgICAgICBzdHJva2Utd2lkdGg9IjMuNTAwOCIKICAgICAgIHN0cm9rZT0iI0ZGRkZGRiIKICAgICAgIGZpbGw9Im5vbmUiIC8+PGc+PHBhdGgKICAgICAgICAgZD0iTTUyLjc3Myw3Ny4wODRjMCwxLjk1NC0xLjU5OSwzLjU1My0zLjU1MywzLjU1M0gzNi45OTljLTEuOTU0LDAtMy41NTMtMS41OTktMy41NTMtMy41NTN2LTkuMzc5ICAgIGMwLTEuOTU0LDEuNTk5LTMuNTUzLDMuNTUzLTMuNTUzaDEyLjIyMmMxLjk1NCwwLDMuNTUzLDEuNTk5LDMuNTUzLDMuNTUzVjc3LjA4NHoiCiAgICAgICAgIGZpbGw9IiNGRkZGRkYiIC8+PC9nPjxnCiAgICAgICBpZD0iZzM0MTkiPjxwYXRoCiAgICAgICAgIGQ9Ik02Ny43NjIsNDguMDc0YzAsMS45NTQtMS41OTksMy41NTMtMy41NTMsMy41NTNINTEuOTg4Yy0xLjk1NCwwLTMuNTUzLTEuNTk5LTMuNTUzLTMuNTUzdi05LjM3OSAgICBjMC0xLjk1NCwxLjU5OS0zLjU1MywzLjU1My0zLjU1M0g2NC4yMWMxLjk1NCwwLDMuNTUzLDEuNTk5LDMuNTUzLDMuNTUzVjQ4LjA3NHoiCiAgICAgICAgIGZpbGw9IiNGRkZGRkYiIC8+PC9nPjxnPjxwYXRoCiAgICAgICAgIGQ9Ik04Mi43NTIsNzcuMDg0YzAsMS45NTQtMS41OTksMy41NTMtMy41NTMsMy41NTNINjYuOTc3Yy0xLjk1NCwwLTMuNTUzLTEuNTk5LTMuNTUzLTMuNTUzdi05LjM3OSAgICBjMC0xLjk1NCwxLjU5OS0zLjU1MywzLjU1My0zLjU1M2gxMi4yMjJjMS45NTQsMCwzLjU1MywxLjU5OSwzLjU1MywzLjU1M1Y3Ny4wODR6IgogICAgICAgICBmaWxsPSIjRkZGRkZGIiAvPjwvZz48L2c+PC9zdmc+';
  143 + // Editor.logoImage = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIKICAgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMzA2LjE4NSAxMjAuMjk2IgogICB2aWV3Qm94PSIyNCAyNiA2OCA2OCIKICAgeT0iMHB4IgogICB4PSIwcHgiCiAgIHZlcnNpb249IjEuMSI+CiAgIAkgPGc+PGxpbmUKICAgICAgIHkyPSI3Mi4zOTQiCiAgICAgICB4Mj0iNDEuMDYxIgogICAgICAgeTE9IjQzLjM4NCIKICAgICAgIHgxPSI1OC4wNjkiCiAgICAgICBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiCiAgICAgICBzdHJva2Utd2lkdGg9IjMuNTUyOCIKICAgICAgIHN0cm9rZT0iI0ZGRkZGRiIKICAgICAgIGZpbGw9Im5vbmUiIC8+PGxpbmUKICAgICAgIHkyPSI3Mi4zOTQiCiAgICAgICB4Mj0iNzUuMDc2IgogICAgICAgeTE9IjQzLjM4NCIKICAgICAgIHgxPSI1OC4wNjgiCiAgICAgICBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiCiAgICAgICBzdHJva2Utd2lkdGg9IjMuNTAwOCIKICAgICAgIHN0cm9rZT0iI0ZGRkZGRiIKICAgICAgIGZpbGw9Im5vbmUiIC8+PGc+PHBhdGgKICAgICAgICAgZD0iTTUyLjc3Myw3Ny4wODRjMCwxLjk1NC0xLjU5OSwzLjU1My0zLjU1MywzLjU1M0gzNi45OTljLTEuOTU0LDAtMy41NTMtMS41OTktMy41NTMtMy41NTN2LTkuMzc5ICAgIGMwLTEuOTU0LDEuNTk5LTMuNTUzLDMuNTUzLTMuNTUzaDEyLjIyMmMxLjk1NCwwLDMuNTUzLDEuNTk5LDMuNTUzLDMuNTUzVjc3LjA4NHoiCiAgICAgICAgIGZpbGw9IiNGRkZGRkYiIC8+PC9nPjxnCiAgICAgICBpZD0iZzM0MTkiPjxwYXRoCiAgICAgICAgIGQ9Ik02Ny43NjIsNDguMDc0YzAsMS45NTQtMS41OTksMy41NTMtMy41NTMsMy41NTNINTEuOTg4Yy0xLjk1NCwwLTMuNTUzLTEuNTk5LTMuNTUzLTMuNTUzdi05LjM3OSAgICBjMC0xLjk1NCwxLjU5OS0zLjU1MywzLjU1My0zLjU1M0g2NC4yMWMxLjk1NCwwLDMuNTUzLDEuNTk5LDMuNTUzLDMuNTUzVjQ4LjA3NHoiCiAgICAgICAgIGZpbGw9IiNGRkZGRkYiIC8+PC9nPjxnPjxwYXRoCiAgICAgICAgIGQ9Ik04Mi43NTIsNzcuMDg0YzAsMS45NTQtMS41OTksMy41NTMtMy41NTMsMy41NTNINjYuOTc3Yy0xLjk1NCwwLTMuNTUzLTEuNTk5LTMuNTUzLTMuNTUzdi05LjM3OSAgICBjMC0xLjk1NCwxLjU5OS0zLjU1MywzLjU1My0zLjU1M2gxMi4yMjJjMS45NTQsMCwzLjU1MywxLjU5OSwzLjU1MywzLjU1M1Y3Ny4wODR6IgogICAgICAgICBmaWxsPSIjRkZGRkZGIiAvPjwvZz48L2c+PC9zdmc+';
  144 + Editor.logoImage = 'data:image/png;base64,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';
  145 + Editor.edgeLogoImage = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjZweCIgaGVpZ2h0PSIyNnB4IiB2aWV3Qm94PSIwIDAgMjYgMjYiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+TG9nby1jZTE8L3RpdGxlPgogICAgPGRlZnM+CiAgICAgICAgPHBvbHlnb24gaWQ9InBhdGgtMSIgcG9pbnRzPSIwIDAgMjYgMCAyNiAyNiAwIDI2Ij48L3BvbHlnb24+CiAgICAgICAgPGxpbmVhckdyYWRpZW50IHgxPSI1MCUiIHkxPSIxMDAlIiB4Mj0iNTAlIiB5Mj0iMCUiIGlkPSJsaW5lYXJHcmFkaWVudC0zIj4KICAgICAgICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzdGNTZEOSIgb2Zmc2V0PSIzNS4yMzgwMDA4JSI+PC9zdG9wPgogICAgICAgICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjRTk2OUZGIiBvZmZzZXQ9IjgwLjIzODAwMjUlIj48L3N0b3A+CiAgICAgICAgPC9saW5lYXJHcmFkaWVudD4KICAgICAgICA8cG9seWdvbiBpZD0icGF0aC00IiBwb2ludHM9IjAgMCAzLjI1IDAgMy4yNSAzLjI1IDAgMy4yNSI+PC9wb2x5Z29uPgogICAgPC9kZWZzPgogICAgPGcgaWQ9IkFJb1RlZGdlIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0iTWVkaXVtIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTgsIC0yNCkiPgogICAgICAgICAgICA8ZyBpZD0i6aaW6aG1LS0tMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgLTUpIj4KICAgICAgICAgICAgICAgIDxnIGlkPSLnu4QtMTEyNDEiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE4LCAyNikiPgogICAgICAgICAgICAgICAgICAgIDxnIGlkPSJMb2dvLWNlMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCwgMykiPgogICAgICAgICAgICAgICAgICAgICAgICA8cmVjdCBpZD0i6Lev5b6EIiB4PSIwIiB5PSIwIiB3aWR0aD0iMjYiIGhlaWdodD0iMjYiPjwvcmVjdD4KICAgICAgICAgICAgICAgICAgICAgICAgPG1hc2sgaWQ9Im1hc2stMiIgZmlsbD0id2hpdGUiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjcGF0aC0xIj48L3VzZT4KICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXNrPgogICAgICAgICAgICAgICAgICAgICAgICA8dXNlIGlkPSLot6/lvoQiIGZpbGwtb3BhY2l0eT0iMCIgZmlsbD0iIzAwMDAwMCIgeGxpbms6aHJlZj0iI3BhdGgtMSI+PC91c2U+CiAgICAgICAgICAgICAgICAgICAgICAgIDxnIGlkPSLnu4QtMTEwODIiIG1hc2s9InVybCgjbWFzay0yKSIgZmlsbD0idXJsKCNsaW5lYXJHcmFkaWVudC0zKSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLCAxLjc3MjkpIiBpZD0i6Lev5b6ELTEwMTIzIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMCwyMi40NTQzIEw0LjcyNzI1LDIyLjQ1NDMgTDEzLDguMjcyNTggTDIxLjI3MjcsMjIuNDU0MyBMMjUuOTk5OSwyMi40NTQzIEwxMywwIEwwLDIyLjQ1NDMgWiBNMTAuMjQyOCwyMi40NTQzIEwxMywxNy43MjcyIEwxNS43NTcxLDIyLjQ1NDMgTDIwLjUyNTgsMjIuNDU0MyBMMTMsOS40NTQzNSBMNS40NzQxNywyMi40NTQzIEwxMC4yNDI4LDIyLjQ1NDMgWiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICAgICAgICAgIDxnIGlkPSLnu4QtMTEwODQiIG1hc2s9InVybCgjbWFzay0yKSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMS4zNzUsIDEzLjQ4NzUpIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cmVjdCBpZD0i6Lev5b6EIiBzdHJva2U9Im5vbmUiIGZpbGw9Im5vbmUiIHg9IjAiIHk9IjAiIHdpZHRoPSIzLjI1IiBoZWlnaHQ9IjMuMjUiPjwvcmVjdD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWFzayBpZD0ibWFzay01IiBmaWxsPSJ3aGl0ZSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx1c2UgeGxpbms6aHJlZj0iI3BhdGgtNCI+PC91c2U+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXNrPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx1c2UgaWQ9Iui3r+W+hCIgc3Ryb2tlPSJub25lIiBmaWxsLW9wYWNpdHk9IjAiIGZpbGw9IiMwMDAwMDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIgeGxpbms6aHJlZj0iI3BhdGgtNCI+PC91c2U+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGcgaWQ9Iue7hC0xMTA4MyIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgbWFzaz0idXJsKCNtYXNrLTUpIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC42NzcsIDAuMTM1NSkiIGZpbGw9IiNGRkZGRkYiIGlkPSLot6/lvoQtMTAxMjQiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTAuNDA2Mjc4NDE4LDEuMjUzMTcgTDAuNDA2Mjc4NDE4LDAuNTQxMzgyIEMwLjQwNjI3ODQxOCwwLjI0MjQzMiAwLjY0ODgwMTQxOCwwIDAuOTQ3OTY1NDE4LDAgQzEuMjQ3MTI3NDIsMCAxLjQ4OTY0NzQyLDAuMjQyNDMyIDEuNDg5NjQ3NDIsMC41NDEzODIgTDEuNDg5NjQ3NDIsMS4yNTMxNyBDMS45NTU1OTc0MiwxLjU3NzUxIDIuMDMzNzE3NDIsMi4yMzU5NiAxLjY1NjYxNzQyLDIuNjYwNzcgQzEuMjc5NTM3NDIsMy4wODUyMSAwLjYxNjM5MTQxOCwzLjA4NTIxIDAuMjM5MzE2NDE4LDIuNjYwNzcgQy0wLjEzNzc4OTU4MiwyLjIzNTk2IC0wLjA1OTY2NDQ4MTksMS41Nzc1MSAwLjQwNjI3ODQxOCwxLjI1MzE3IFogTTAuODEyNTI4NDE4LDEuNTA2NzEgQzAuNTQ5MTAwNDE4LDEuNTc1MiAwLjM3NzYyMjQxOCwxLjgyOTEgMC40MTE5NTQ0MTgsMi4wOTkxMiBDMC40NDYyMjU0MTgsMi4zNjkyNiAwLjY3NTY4NzQxOCwyLjU3MjAyIDAuOTQ3OTY1NDE4LDIuNTcyNjMwNTEgQzEuMjIwOTQ3NDIsMi41NzMgMS40NTE0NDc0MiwyLjM3MDI0IDEuNDg1ODM3NDIsMi4wOTk0OSBDMS41MjAyNTc0MiwxLjgyODM3IDEuMzQ3NzQ3NDIsMS41NzQ1OCAxLjA4MzM5NzQyLDEuNTA2NzEgTDEuMDgzMzk3NDIsMC41NDEzODIgTDAuODEyNTI4NDE4LDAuNTQxMzgyIEwwLjgxMjUyODQxOCwxLjUwNjcxIFoiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgICAgICAgICAgPC9nPgogICAgICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+';
144 146 Editor.saveImage = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iYmxhY2siIHdpZHRoPSIxOHB4IiBoZWlnaHQ9IjE4cHgiPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48cGF0aCBkPSJNMTkgMTJ2N0g1di03SDN2N2MwIDEuMS45IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0ydi03aC0yem0tNiAuNjdsMi41OS0yLjU4TDE3IDExLjVsLTUgNS01LTUgMS40MS0xLjQxTDExIDEyLjY3VjNoMnoiLz48L3N2Zz4=';
145 147 Editor.globeImage = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTEuOTkgMkM2LjQ3IDIgMiA2LjQ4IDIgMTJzNC40NyAxMCA5Ljk5IDEwQzE3LjUyIDIyIDIyIDE3LjUyIDIyIDEyUzE3LjUyIDIgMTEuOTkgMnptNi45MyA2aC0yLjk1Yy0uMzItMS4yNS0uNzgtMi40NS0xLjM4LTMuNTYgMS44NC42MyAzLjM3IDEuOTEgNC4zMyAzLjU2ek0xMiA0LjA0Yy44MyAxLjIgMS40OCAyLjUzIDEuOTEgMy45NmgtMy44MmMuNDMtMS40MyAxLjA4LTIuNzYgMS45MS0zLjk2ek00LjI2IDE0QzQuMSAxMy4zNiA0IDEyLjY5IDQgMTJzLjEtMS4zNi4yNi0yaDMuMzhjLS4wOC42Ni0uMTQgMS4zMi0uMTQgMiAwIC42OC4wNiAxLjM0LjE0IDJINC4yNnptLjgyIDJoMi45NWMuMzIgMS4yNS43OCAyLjQ1IDEuMzggMy41Ni0xLjg0LS42My0zLjM3LTEuOS00LjMzLTMuNTZ6bTIuOTUtOEg1LjA4Yy45Ni0xLjY2IDIuNDktMi45MyA0LjMzLTMuNTZDOC44MSA1LjU1IDguMzUgNi43NSA4LjAzIDh6TTEyIDE5Ljk2Yy0uODMtMS4yLTEuNDgtMi41My0xLjkxLTMuOTZoMy44MmMtLjQzIDEuNDMtMS4wOCAyLjc2LTEuOTEgMy45NnpNMTQuMzQgMTRIOS42NmMtLjA5LS42Ni0uMTYtMS4zMi0uMTYtMiAwLS42OC4wNy0xLjM1LjE2LTJoNC42OGMuMDkuNjUuMTYgMS4zMi4xNiAyIDAgLjY4LS4wNyAxLjM0LS4xNiAyem0uMjUgNS41NmMuNi0xLjExIDEuMDYtMi4zMSAxLjM4LTMuNTZoMi45NWMtLjk2IDEuNjUtMi40OSAyLjkzLTQuMzMgMy41NnpNMTYuMzYgMTRjLjA4LS42Ni4xNC0xLjMyLjE0LTIgMC0uNjgtLjA2LTEuMzQtLjE0LTJoMy4zOGMuMTYuNjQuMjYgMS4zMS4yNiAycy0uMSAxLjM2LS4yNiAyaC0zLjM4eiIvPjwvc3ZnPg==';
146 148 Editor.commentImage = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMjEuOTkgNGMwLTEuMS0uODktMi0xLjk5LTJINGMtMS4xIDAtMiAuOS0yIDJ2MTJjMCAxLjEuOSAyIDIgMmgxNGw0IDQtLjAxLTE4ek0xOCAxNEg2di0yaDEydjJ6bTAtM0g2VjloMTJ2MnptMC0zSDZWNmgxMnYyeiIvPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48L3N2Zz4=';
... ...
... ... @@ -167,26 +167,36 @@ LocalFile.prototype.saveFile = function (title, revision, success, error, useCur
167 167 const handleSaveContent = async () => {
168 168 const { doSaveConfigurationContent, configurationId } = useContentData()
169 169 try {
170   - const allCells = this.ui.editor.graph.getModel().cells || {}
171   - // const allCells = this.shadowPages
172   - // .map(item => {
173   - // console.log(item)
174   - // return this.ui.editor.graph.createCellLookup([item.root])
175   - // })
176   - // .map(obj => Object.values(obj))
177   - // .reduce((prev, next) => [...prev, ...next], [])
178   -
  170 + const graph = this.ui.editor.graph
  171 + const model = graph.model
  172 + const pages = this.ui.pages
  173 +
  174 + const currentPageContentId = this.ui.currentPage.getId()
  175 + let originalPage
  176 + const contentPageInfos = pages.map(page => {
  177 + this.ui.selectPage(page)
  178 + const cells = model.getChildCells(graph.getDefaultParent())
  179 + const nodeIds = cells.map(cell => cell.getId())
  180 + const contentId = this.ui.currentPage.getId()
  181 +
  182 + if (contentId === currentPageContentId)
  183 + originalPage = page
  184 +
  185 + return {
  186 + nodeIds,
  187 + contentId
  188 + }
  189 + })
  190 + originalPage && this.ui.selectPage(originalPage)
  191 +
179 192 await doSaveConfigurationContent({
180 193 configurationContentList: [
181 194 {
182 195 id: this.ui.configurationContentId,
183 196 content: savedData,
184   - // contentId: this.ui.configurationContentId,
185   - contentId: this.ui.currentPage.getId(),
186 197 type: 1,
187   - // nodeIds: Array.from(new Set(allCells)),
188   - nodeIds: Object.keys(allCells),
189   - name: this.ui.currentPage.getName()
  198 + name: this.ui.currentPage.getName(),
  199 + contentPageInfos
190 200 }
191 201 ],
192 202 configurationName: this.ui.currentFile.title,
... ...
... ... @@ -1309,7 +1309,7 @@ operationPassword=操作密码
1309 1309 dataSource=数据源
1310 1310 dataInteraction=数据交互
1311 1311 display=显示
1312   -actHidden=隐藏
  1312 +acrHidden=隐藏
1313 1313 flow=流动
1314 1314 stop=停止
1315 1315 actOpen=开启
... ...
... ... @@ -165,7 +165,15 @@ function getProxyPrefix() {
165 165 return window.urlParams.isProxyMode ? window.urlParams.proxyPrefix : ''
166 166 }
167 167
168   -const drawioConfig = JSON.parse(localStorage.getItem('.drawio-config') || null)
  168 +const drawioConfig = (
  169 + () => {
  170 + try {
  171 + return JSON.parse(localStorage.getItem('.drawio-config') || null)
  172 + } catch {
  173 + return {}
  174 + }
  175 + }
  176 +)()
169 177
170 178 const localLang = drawioConfig?.language
171 179
... ...
... ... @@ -13,7 +13,7 @@ enum Api {
13 13 GET_DEVICE_BY_DEVICE_PROFILED_IDS = '/device/getListByDeviceProfileIds',
14 14 GET_THINGS_MODEL_SERVICES = '/things_model/get_services/',
15 15
16   - RPC_COMMAND = '/rpc/',
  16 + RPC_COMMAND = '/rpc',
17 17 GET_DEVICE_ACTIVE = '/plugins/telemetry/DEVICE/',
18 18 RPC_ONEWAY = '/rpc/oneway',
19 19 RPC_TWOWAY = '/rpc/twoway',
... ...
... ... @@ -25,28 +25,28 @@ export const doSaveNodeAllData = (data: SaveNodeDataParamsType) => {
25 25 }
26 26
27 27 export const doSaveNodeAct = (params: SaveNodeActParamsType) => {
28   - const { configurationId, contentId, id, data } = params
  28 + const { configurationId, contentId, configurationNodeId, data } = params
29 29 return defHttp.post({
30 30 url: Api.SAVE_NODE_ACT,
31   - params: { configurationId, contentId, id },
  31 + params: { configurationId, contentId, configurationNodeId },
32 32 data,
33 33 })
34 34 }
35 35
36 36 export const doSaveNodeDataSource = (params: SaveNodeDataSourceParamsType) => {
37   - const { configurationId, contentId, id, data } = params
  37 + const { configurationId, contentId, configurationNodeId, data } = params
38 38 return defHttp.post({
39 39 url: Api.SAVE_NODE_DATASOURCE,
40   - params: { configurationId, contentId, id },
  40 + params: { configurationId, contentId, configurationNodeId },
41 41 data,
42 42 })
43 43 }
44 44
45 45 export const doSaveNodeEvent = (params: SaveNodeEventParamsType) => {
46   - const { configurationId, contentId, id, data } = params
  46 + const { configurationId, contentId, configurationNodeId, data } = params
47 47 return defHttp.post({
48 48 url: Api.SAVE_NODE_EVENT,
49   - params: { configurationId, contentId, id },
  49 + params: { configurationId, contentId, configurationNodeId },
50 50 data,
51 51 })
52 52 }
... ...
... ... @@ -11,9 +11,10 @@ export enum DeleteNodeDataTypeEnum {
11 11 }
12 12
13 13 export interface BasicNodeBindType {
14   - id: string
15 14 contentId: string
  15 + configurationNodeId: string
16 16 configurationId: string
  17 + id?: string
17 18 }
18 19
19 20 export interface SaveNodeDataParamsType extends BasicNodeBindType {
... ... @@ -45,6 +46,7 @@ export interface NodeDataBasicType {
45 46 enabled: boolean
46 47 tenantId: string
47 48 configurationId: string
  49 + configurationNodeId: string
48 50 contentId: string
49 51 }
50 52
... ...
1 1 <script lang="ts" setup>
2 2 import { Button } from 'ant-design-vue'
3 3 import { basicProps } from '../props'
  4 +import { useTranslation } from '@/hooks/useTranslation'
4 5 defineProps(basicProps)
5 6 const emit = defineEmits(['ok', 'cancel'])
  7 +
  8 +const { t } = useTranslation()
6 9 function handleOk(e: Event) {
7 10 emit('ok', e)
8 11 }
... ... @@ -16,17 +19,11 @@ function handleCancel(e: Event) {
16 19 <div>
17 20 <slot name="insertFooter" />
18 21 <Button v-if="showCancelBtn" v-bind="cancelButtonProps" @click="handleCancel">
19   - {{ cancelText }}
  22 + {{ cancelText || t('cancel') }}
20 23 </Button>
21 24 <slot name="centerFooter" />
22   - <Button
23   - v-if="showOkBtn"
24   - :type="okType"
25   - :loading="confirmLoading"
26   - v-bind="okButtonProps"
27   - @click="handleOk"
28   - >
29   - {{ okText }}
  25 + <Button v-if="showOkBtn" :type="okType" :loading="confirmLoading" v-bind="okButtonProps" @click="handleOk">
  26 + {{ okText || t('ok') }}
30 27 </Button>
31 28 <slot name="appendFooter" />
32 29 </div>
... ...
... ... @@ -3,9 +3,7 @@ import type { ButtonProps } from 'ant-design-vue/es/button/buttonTypes'
3 3 import type { ButtonType } from 'ant-design-vue/lib/button'
4 4 import type { VueNode } from 'ant-design-vue/es/_util/type'
5 5 import type { ModalWrapperProps } from './typing'
6   -import { useTranslation } from '@/hooks/useTranslation'
7 6
8   -const { t } = useTranslation()
9 7 export const modalProps = {
10 8 open: { type: Boolean },
11 9 scrollTop: { type: Boolean, default: true },
... ... @@ -14,8 +12,8 @@ export const modalProps = {
14 12 // open drag
15 13 draggable: { type: Boolean, default: true },
16 14 centered: { type: Boolean },
17   - cancelText: { type: String, default: t('cancel') },
18   - okText: { type: String, default: t('ok') },
  15 + cancelText: { type: String },
  16 + okText: { type: String },
19 17
20 18 closeFunc: Function as PropType<() => Promise<boolean>>,
21 19 }
... ...
1 1 <script setup lang="ts">
2 2 import { ref, unref } from 'vue'
3 3 import type { ComponentExposeType } from '../../..'
  4 +import { usePublicFormContext } from '../../../usePublicFormContext'
4 5 import ImageSettingTable from './ImageSettingTable.vue'
5 6 import { formSchemas } from './config'
6 7 import { BasicForm, useForm } from '@/components/Form'
7 8 import { FormLayoutEnum } from '@/components/Form/src/enum'
8 9 import type { RangeItemType, VariableImageActDataType } from '@/api/node/model'
  10 +import { NodeUtils } from '@/hooks/business/useNodeUtils'
  11 +import type { ImageSelectorDataType } from '@/core/Library/components/ImageSelector'
  12 +import { CellAttributeKeyEnum } from '@/enums/cellAttributeEnum'
9 13
10 14 const imageSettingTableElRef = ref<InstanceType<typeof ImageSettingTable>>()
11 15
  16 +const { getCellInfo } = usePublicFormContext()
  17 +
  18 +const nodeUtils = new NodeUtils()
  19 +
12 20 const [register, formActionType] = useForm({
13 21 schemas: formSchemas,
14 22 showActionButtonGroup: false,
... ... @@ -16,6 +24,17 @@ const [register, formActionType] = useForm({
16 24 baseColProps: { span: 12 },
17 25 })
18 26
  27 +function savaDefaultImageToNodeAttribute(defaultImages: ImageSelectorDataType) {
  28 + const node = nodeUtils.getCellById(unref(getCellInfo).id)
  29 +
  30 + if (!node)
  31 + return
  32 +
  33 + node.setAttribute(CellAttributeKeyEnum.DEFAULT_IMAGE, JSON.stringify(defaultImages))
  34 +
  35 + nodeUtils.refreshCell(node)
  36 +}
  37 +
19 38 const validate = async () => {
20 39 await formActionType.validate()
21 40 await unref(imageSettingTableElRef)?.validate()
... ... @@ -24,6 +43,8 @@ const validate = async () => {
24 43 const getFieldsValue = (): VariableImageActDataType => {
25 44 const value = formActionType.getFieldsValue() as VariableImageActDataType
26 45 const tableValue = unref(imageSettingTableElRef)?.getFieldsValue() as RangeItemType[]
  46 +
  47 + savaDefaultImageToNodeAttribute(value.defaultImage)
27 48 return {
28 49 ...value,
29 50 rangeList: tableValue,
... ... @@ -51,11 +72,11 @@ defineExpose<ComponentExposeType>({
51 72 </template>
52 73
53 74 <style lang="less" scoped>
54   - .variable-image-form {
55   - >:deep(.ant-row) {
56   - >.ant-col {
57   - @apply px-4;
58   - }
  75 +.variable-image-form {
  76 + >:deep(.ant-row) {
  77 + >.ant-col {
  78 + @apply px-4;
59 79 }
60 80 }
  81 +}
61 82 </style>
... ...
... ... @@ -17,7 +17,7 @@ export const tableColumns = (): BasicColumn[] => {
17 17 title: t('state'),
18 18 dataIndex: 'type',
19 19 format(text) {
20   - return ActRangListItemTypeNameEnum[text as ActRangListItemTypeEnum]
  20 + return t(ActRangListItemTypeNameEnum[text as ActRangListItemTypeEnum])
21 21 },
22 22 },
23 23 {
... ...
... ... @@ -52,6 +52,7 @@ async function getResult() {
52 52 objectModel: unref(objectModelTsl),
53 53 deviceDetail: unref(deviceInfo),
54 54 value,
  55 + way: unref(commandWay),
55 56 })
56 57
57 58 const { createMessage } = useMessage()
... ...
... ... @@ -37,7 +37,7 @@ export const getFormSchemas = (event: EventTypeEnum): FormSchema[] => {
37 37 componentProps: {
38 38 allowClear: false,
39 39 options: [
40   - { label: EventTypeNameEnum[event], value: EventTypeEnum[event] },
  40 + { label: t(EventTypeNameEnum[event]), value: EventTypeEnum[event] },
41 41 ],
42 42 },
43 43 },
... ...
... ... @@ -177,8 +177,8 @@ defineExpose<ComponentExposeType>({
177 177 :validate-status="getValidateStatus(record[TableColumnFieldEnum.DEVICE_PROFILE_ID])"
178 178 >
179 179 <Select
180   - v-model:value="record[TableColumnFieldEnum.DEVICE_PROFILE_ID]" :options="productList" :field-names="{ label: 'name', value: 'profileId' }" placeholder="请选择产品"
181   - class="w-full"
  180 + v-model:value="record[TableColumnFieldEnum.DEVICE_PROFILE_ID]" :options="productList"
  181 + :field-names="{ label: 'name', value: 'profileId' }" placeholder="请选择产品" class="w-full"
182 182 @change="(value, option) => handleSelectProduct(value, option, record as TableRecordItemType)"
183 183 />
184 184 </FormItem>
... ... @@ -189,8 +189,8 @@ defineExpose<ComponentExposeType>({
189 189 :validate-status="getValidateStatus(record[TableColumnFieldEnum.DEVICE_ID])"
190 190 >
191 191 <Select
192   - v-model:value="record[TableColumnFieldEnum.DEVICE_ID]" :options="deviceList" :placeholder="t('chooseDevice')"
193   - class="w-full"
  192 + v-model:value="record[TableColumnFieldEnum.DEVICE_ID]" :options="deviceList"
  193 + :placeholder="t('chooseDevice')" class="w-full"
194 194 @change="(value, option) => handleSelectDevice(value, option, record as TableRecordItemType)"
195 195 />
196 196 </FormItem>
... ... @@ -198,8 +198,8 @@ defineExpose<ComponentExposeType>({
198 198 <template v-if="column.key === TableColumnFieldEnum.WAY">
199 199 <RadioGroup
200 200 v-model:value="record[TableColumnFieldEnum.WAY]" :options="[
201   - { label: CommandWayNameEnum.ONE_WAY, value: CommandWayEnum.ONE_WAY },
202   - { label: CommandWayNameEnum.TWO_WAY, value: CommandWayEnum.TWO_WAY },
  201 + { label: t(CommandWayNameEnum.ONE_WAY), value: CommandWayEnum.ONE_WAY },
  202 + { label: t(CommandWayNameEnum.TWO_WAY), value: CommandWayEnum.TWO_WAY },
203 203 ]"
204 204 />
205 205 </template>
... ...
... ... @@ -2,6 +2,7 @@ import { isBoolean } from '@wry-smile/utils-is'
2 2 import type { BasicContentComponentProps } from '../..'
3 3 import type { PublicFormSettingType } from '../../..'
4 4 import { DataSourceTypeEnum, EventTypeEnum, EventTypeNameEnum } from '@/enums/datasource'
  5 +import { useTranslation } from '@/hooks/useTranslation'
5 6
6 7 export interface DynamicEffectItemType {
7 8 label: string
... ... @@ -10,29 +11,31 @@ export interface DynamicEffectItemType {
10 11 componentProps?: BasicContentComponentProps
11 12 }
12 13
  14 +const { t } = useTranslation()
  15 +
13 16 export const getEventItem = (formSetting?: PublicFormSettingType): DynamicEffectItemType[] => {
14 17 const list = [
15 18 {
16   - label: EventTypeNameEnum.DOWN,
  19 + label: t(EventTypeNameEnum.DOWN),
17 20 key: EventTypeEnum.DOWN,
18 21 component: () => import('./MouseDownOrUpSetting/index.vue'),
19 22 componentProps: { event: EventTypeEnum.DOWN, type: DataSourceTypeEnum.EVENT },
20 23 },
21 24 {
22   - label: EventTypeNameEnum.UP,
  25 + label: t(EventTypeNameEnum.UP),
23 26 key: EventTypeEnum.UP,
24 27 component: () => import('./MouseDownOrUpSetting/index.vue'),
25 28 componentProps: { event: EventTypeEnum.UP, type: DataSourceTypeEnum.EVENT },
26 29
27 30 },
28 31 {
29   - label: EventTypeNameEnum.SINGLE,
  32 + label: t(EventTypeNameEnum.SINGLE),
30 33 key: EventTypeEnum.SINGLE,
31 34 component: () => import('./SingleClickOrDoubleClickSetting/index.vue'),
32 35 componentProps: { event: EventTypeEnum.SINGLE, type: DataSourceTypeEnum.EVENT },
33 36 },
34 37 {
35   - label: EventTypeNameEnum.DOUBLE,
  38 + label: t(EventTypeNameEnum.DOUBLE),
36 39 key: EventTypeEnum.DOUBLE,
37 40 component: () => import('./SingleClickOrDoubleClickSetting/index.vue'),
38 41 componentProps: { event: EventTypeEnum.DOUBLE, type: DataSourceTypeEnum.EVENT },
... ...
... ... @@ -7,9 +7,10 @@ import type { ModalProps } from '@/components/Modal'
7 7 import { BasicModal, useModalInner } from '@/components/Modal'
8 8 import type { ActTypeEnum, EventTypeEnum } from '@/enums/datasource'
9 9 import { DataSourceTypeEnum } from '@/enums/datasource'
10   -import type { NodeDataActJsonType, NodeDataEventJsonType, SingleClickEventDataType } from '@/api/node/model'
  10 +import type { NodeDataActJsonType, NodeDataEventJsonType } from '@/api/node/model'
11 11 import { useContentDataStoreWithOut } from '@/store/modules/contentData'
12 12 import { useTranslation } from '@/hooks/useTranslation'
  13 +import { BasicComponentEnum } from '@/core/Library/packages/Basic'
13 14
14 15 defineEmits(['register'])
15 16
... ... @@ -17,7 +18,7 @@ const { t } = useTranslation()
17 18
18 19 const contentDataStore = useContentDataStoreWithOut()
19 20
20   -const { getNodeData, getNodeAllData, saveNodeAllData } = usePublicFormContext()
  21 +const { getNodeData, getNodeAllData, saveNodeAllData, getCellInfo } = usePublicFormContext()
21 22
22 23 const contentComponent = shallowRef()
23 24
... ... @@ -63,6 +64,10 @@ const handleOk = async () => {
63 64 await handleDoSaveEventData()
64 65
65 66 await getNodeAllData()
  67 +
  68 + if (unref(getCellInfo).componentKey === BasicComponentEnum.VARIABLE_IMAGE)
  69 + window.DrawApp?.saveButton.click()
  70 +
66 71 closeModal()
67 72 contentComponent.value = null
68 73 }
... ... @@ -93,7 +98,10 @@ const handleCancel = () => {
93 98 <template>
94 99 <BasicModal destroy-on-close v-bind="modalProps" @register="register" @ok="handleOk" @cancel="handleCancel">
95 100 <!-- <Spin :spinning="spinning"> -->
96   - <component :is="contentComponent" v-bind="componentProps" ref="componentInstance" @vue:mounted="handleComponentMounted" />
  101 + <component
  102 + :is="contentComponent" v-bind="componentProps" ref="componentInstance"
  103 + @vue:mounted="handleComponentMounted"
  104 + />
97 105 <!-- </Spin> -->
98 106 <!-- -->
99 107 </BasicModal>
... ...
... ... @@ -219,10 +219,13 @@ createPublicFormContext(nodeDataActinType)
219 219 <Divider orientation="left">
220 220 {{ t('dataInteraction') }}
221 221 </Divider>
222   - <DataEvents ref="dataEventsElRef" :before-click="handleBeforeOpenEventOrActModal" :form-setting="getFormSetting" />
  222 + <DataEvents
  223 + ref="dataEventsElRef" :before-click="handleBeforeOpenEventOrActModal"
  224 + :form-setting="getFormSetting"
  225 + />
223 226 <div
224   - v-if="getCellInfo.category === PackageCategoryEnum.CONTROL" class="flex flex-col justify-center passwordInput"
225   - :class="getFormSetting?.actSetting === false && 'mb-4'"
  227 + v-if="getCellInfo.category === PackageCategoryEnum.CONTROL"
  228 + class="flex flex-col justify-center passwordInput" :class="getFormSetting?.actSetting === false && 'mb-4'"
226 229 >
227 230 <Checkbox v-model:checked="operationPassword.checked" :disabled="getSetPasswordStatus">
228 231 <div class="flex">
... ... @@ -254,10 +257,10 @@ createPublicFormContext(nodeDataActinType)
254 257
255 258 <style lang="less" scoped>
256 259 .form-container {
257   -@apply text-sm;
  260 + @apply text-sm;
258 261
259 262 :deep(.ant-divider) {
260   - @apply text-sm;
  263 + @apply text-sm;
261 264 }
262 265 }
263 266
... ...
... ... @@ -52,17 +52,23 @@ export function useNodeData({ cell, immediate = true }: UseNodeDataParamsType) {
52 52 }
53 53
54 54 const basicNodeBindData = (type: ActionType): BasicNodeBindType => {
55   - return {
56   - id: type === ActionType.GET ? getSourceCellID () || getCellID () : getCellID(),
  55 + const res: BasicNodeBindType = {
  56 + configurationNodeId: type === ActionType.GET ? getSourceCellID() || getCellID() : getCellID(),
57 57 contentId: window.DrawApp.currentPage.getId(),
58 58 configurationId,
59 59 }
  60 +
  61 + if (unref(nodeData)?.id)
  62 + res.id = unref(nodeData)?.id
  63 +
  64 + return res
60 65 }
61 66
62 67 const getCellInfo = computed(() => {
63 68 return {
64 69 [CellAttributeKeyEnum.CATEGORY]: cell.getAttribute(CellAttributeKeyEnum.CATEGORY),
65 70 [CellAttributeKeyEnum.COMPONENT_KEY]: cell.getAttribute(CellAttributeKeyEnum.COMPONENT_KEY),
  71 + id: cell.getId(),
66 72 }
67 73 })
68 74
... ...
... ... @@ -88,7 +88,7 @@ export function useNodeEvent(eventJson: NodeDataEventJsonType, dataSourceJson: N
88 88
89 89 if (nodeUtils.getNodeComponentKey(cell) === ControlComponentEnum.SWITCH) {
90 90 const contentDataStore = useContentDataStoreWithOut()
91   - const currentData = contentDataStore.contentData.find(item => item.id === cell.getId())
  91 + const currentData = contentDataStore.contentData.find(item => item.configurationNodeId === cell.getId())
92 92 if (!currentData) return
93 93 const { actJson } = currentData
94 94 const { rangeList } = actJson.STATUS_SETTING
... ...
... ... @@ -33,7 +33,7 @@ const initOptions = reactive<{
33 33 const { t } = useTranslation()
34 34 const fetchAlarmListConfig = computed(() => {
35 35 return contentDataStore?.contentData.find((item) => {
36   - return props.config.cellInfo?.id === item.id
  36 + return props.config.cellInfo?.id === item.configurationNodeId
37 37 })
38 38 })
39 39
... ...
1 1 <script setup lang="ts">
2 2 import { ref } from 'vue'
3   -import type { RenderComponentExposeType } from '@/core/Library/types'
  3 +import type { RenderComponentExposeType, RenderComponentProps } from '@/core/Library/types'
4 4 import type { CommandSource } from '@/core/websocket/processor'
5 5 import { NodeUtils } from '@/hooks/business/useNodeUtils'
6 6 import { getMeetTheConditionsRange } from '@/core/Library/utils'
... ... @@ -9,8 +9,29 @@ import type { VariableImageActDataType } from '@/api/node/model'
9 9 import { useLatestMessageValue } from '@/core/Library/hook/useLatestMessageValue'
10 10 import { useOnMessage } from '@/core/Library/hook/useOnMessage'
11 11 import type { SubscriptionUpdateMsg } from '@/core/websocket/type/message'
  12 +import { CellAttributeKeyEnum } from '@/enums/cellAttributeEnum'
  13 +import { useJsonParse } from '@/hooks/business/useJSONParse'
  14 +import type { ImageSelectorDataType } from '@/core/Library/components/ImageSelector'
12 15
13   -const imgSrc = ref('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="48" height="48" viewBox="0 0 48 48"%3E%3Cpath fill="%238CBCD6" d="M31 41H8c-2.2 0-4-1.8-4-4V11c0-2.2 1.8-4 4-4h32c2.2 0 4 1.8 4 4v17c0 7.2-5.8 13-13 13z"%2F%3E%3Ccircle cx="35" cy="16" r="3" fill="%23B3DDF5"%2F%3E%3Cpath fill="%239AC9E3" d="M20 16L9 32h22z"%2F%3E%3Cpath fill="%23B3DDF5" d="m31 22l-8 10h16z"%2F%3E%3Cpath fill="%23E57373" d="m47.7 29.1l-2.8-2.8c-.4-.4-1.1-.4-1.6 0L42 27.6l4.4 4.4l1.3-1.3c.4-.4.4-1.1 0-1.6z"%2F%3E%3Cpath fill="%23FF9800" d="M27.467 42.167L39.77 29.865l4.384 4.384L31.85 46.55z"%2F%3E%3Cpath fill="%23B0BEC5" d="m46.4 32.038l-2.192 2.192l-4.383-4.384l2.192-2.191z"%2F%3E%3Cpath fill="%23FFC107" d="M27.5 42.2L26 48l5.8-1.5z"%2F%3E%3Cpath fill="%2337474F" d="m26.7 45l-.7 3l3-.7z"%2F%3E%3C%2Fsvg%3E')
  16 +const props = defineProps<RenderComponentProps>()
  17 +const nodeUtils = new NodeUtils()
  18 +
  19 +const imgSrc = ref(getDefaultImage() || 'data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="48" height="48" viewBox="0 0 48 48"%3E%3Cpath fill="%238CBCD6" d="M31 41H8c-2.2 0-4-1.8-4-4V11c0-2.2 1.8-4 4-4h32c2.2 0 4 1.8 4 4v17c0 7.2-5.8 13-13 13z"%2F%3E%3Ccircle cx="35" cy="16" r="3" fill="%23B3DDF5"%2F%3E%3Cpath fill="%239AC9E3" d="M20 16L9 32h22z"%2F%3E%3Cpath fill="%23B3DDF5" d="m31 22l-8 10h16z"%2F%3E%3Cpath fill="%23E57373" d="m47.7 29.1l-2.8-2.8c-.4-.4-1.1-.4-1.6 0L42 27.6l4.4 4.4l1.3-1.3c.4-.4.4-1.1 0-1.6z"%2F%3E%3Cpath fill="%23FF9800" d="M27.467 42.167L39.77 29.865l4.384 4.384L31.85 46.55z"%2F%3E%3Cpath fill="%23B0BEC5" d="m46.4 32.038l-2.192 2.192l-4.383-4.384l2.192-2.191z"%2F%3E%3Cpath fill="%23FFC107" d="M27.5 42.2L26 48l5.8-1.5z"%2F%3E%3Cpath fill="%2337474F" d="m26.7 45l-.7 3l3-.7z"%2F%3E%3C%2Fsvg%3E')
  20 +
  21 +function getDefaultImage() {
  22 + const cell = nodeUtils.getCellById(props.config.cellInfo!.id)
  23 +
  24 + if (!cell) return
  25 +
  26 + const defaultImage = cell.getAttribute(CellAttributeKeyEnum.DEFAULT_IMAGE)
  27 +
  28 + if (!defaultImage)
  29 + return
  30 +
  31 + const { imageSource, libPath, path } = useJsonParse(defaultImage).value as ImageSelectorDataType
  32 +
  33 + return imageSource === VariableImageSourceEnum.GALLERY ? libPath : path
  34 +}
14 35
15 36 const onReceiveActMessage = (commandSource: CommandSource, message: SubscriptionUpdateMsg) => {
16 37 const { node, data, type } = commandSource
... ... @@ -50,6 +71,6 @@ defineExpose<RenderComponentExposeType>({
50 71
51 72 <template>
52 73 <div class="w-full h-full flex justify-center items-center">
53   - <img class="w-full" :src="imgSrc">
  74 + <img class="w-full h-full object-contain" :src="imgSrc">
54 75 </div>
55 76 </template>
... ...
... ... @@ -53,7 +53,8 @@ export const getVideoTypeByUrl = (url: string) => {
53 53 export async function getPlayUrl(
54 54 params: VideoItemRecordType,
55 55 ): Promise<Undefineable<{ url: string; type: StreamType }>> {
56   - const { accessMode } = params
  56 + let { accessMode } = params
  57 + accessMode = Number(accessMode)
57 58 if (accessMode === VideoAccessModeEnum.ManuallyEnter) {
58 59 const { videoUrl } = params
59 60 if (params.videoUrl) {
... ...
... ... @@ -99,7 +99,7 @@ const [register, { getFieldsValue, validate, setFieldsValue }] = useForm({
99 99 {
100 100 field: VideoFormFieldsEnum.ACCESS_MODE,
101 101 label: t(VideoFormFieldsNameEnum.ACCESS_MODE),
102   - component: ComponentEnum.INPUT,
  102 + component: ComponentEnum.INPUT_NUMBER,
103 103 ifShow: false,
104 104 },
105 105 {
... ...
... ... @@ -25,7 +25,7 @@ const loading = ref(false)
25 25 // 存储视频数据
26 26 const videoConfig = computed(() => {
27 27 return contentDataStore?.contentData.filter((item) => {
28   - return props.config.cellInfo?.id === item.id
  28 + return props.config.cellInfo?.id === item.configurationNodeId
29 29 })
30 30 })
31 31
... ...
1 1 export enum BasicComponentEnum {
2 2 TITLE = 'Title',
3 3 VARIABLE = 'Variable',
  4 + VARIABLE_IMAGE = 'VariableImage',
4 5 }
5 6
6 7 export enum BasicComponentNameEnum {
7 8 TITLE = '标题',
8 9 VARIABLE = '变量',
  10 + VARIABLE_IMAGE = '变量图片',
  11 +
9 12 }
... ...
... ... @@ -30,10 +30,10 @@ export default class Config implements CreateComponentType {
30 30 }
31 31
32 32 export const dataSubscribers: ComponentConfigModuleType['dataSubscribers'] = (telemetryService, nodeData) => {
33   - const { dataSourceJson, id } = nodeData
  33 + const { dataSourceJson, configurationNodeId } = nodeData
34 34 const { deviceId, attr, chartOption } = dataSourceJson
35 35 const { agg, interval, effectScope = 0 } = chartOption!
36   - const subscribe = TelemetrySubscriber.createHistorySubscription(telemetryService, { id: deviceId, entityType: EntityType.DEVICE }, attr, telemetryService.getCommandSource(id, DataSourceTypeEnum.DATASOURCE, dataSourceJson))
  36 + const subscribe = TelemetrySubscriber.createHistorySubscription(telemetryService, { id: deviceId, entityType: EntityType.DEVICE }, attr, telemetryService.getCommandSource(configurationNodeId, DataSourceTypeEnum.DATASOURCE, dataSourceJson))
37 37
38 38 const subscriptionCommand = subscribe.subscriptionCommand as HistorySubscriptionCmd
39 39 subscriptionCommand.agg = agg
... ...
... ... @@ -30,15 +30,15 @@ export default class Config implements CreateComponentType {
30 30 }
31 31
32 32 export const dataSubscribers: ComponentConfigModuleType['dataSubscribers'] = (telemetryService, nodeData) => {
33   - const { dataSourceJson, id } = nodeData
  33 + const { dataSourceJson, configurationNodeId } = nodeData
34 34 const { deviceId, attr, chartOption } = dataSourceJson
35 35 const { agg, interval, effectScope = 0, queryType } = chartOption!
36 36
37 37 let subscribe
38 38 if (queryType === SocketSubscriberEnum.HISTORY_CMDS)
39   - subscribe = TelemetrySubscriber.createHistorySubscription(telemetryService, { id: deviceId, entityType: EntityType.DEVICE }, attr, telemetryService.getCommandSource(id, DataSourceTypeEnum.DATASOURCE, dataSourceJson))
  39 + subscribe = TelemetrySubscriber.createHistorySubscription(telemetryService, { id: deviceId, entityType: EntityType.DEVICE }, attr, telemetryService.getCommandSource(configurationNodeId, DataSourceTypeEnum.DATASOURCE, dataSourceJson))
40 40 else
41   - subscribe = TelemetrySubscriber.createTimeseriesSubscription(telemetryService, { id: deviceId, entityType: EntityType.DEVICE }, attr, telemetryService.getCommandSource(id, DataSourceTypeEnum.DATASOURCE, dataSourceJson))
  41 + subscribe = TelemetrySubscriber.createTimeseriesSubscription(telemetryService, { id: deviceId, entityType: EntityType.DEVICE }, attr, telemetryService.getCommandSource(configurationNodeId, DataSourceTypeEnum.DATASOURCE, dataSourceJson))
42 42
43 43 const subscriptionCommand = subscribe.subscriptionCommand as HistorySubscriptionCmd
44 44 subscriptionCommand.agg = agg
... ...
... ... @@ -101,4 +101,3 @@ createPublicFormContext(nodeDataActinType)
101 101 }
102 102 }
103 103 </style>
104   -
... ...
  1 +import { isFromEdge } from './useParseParams'
1 2 import { getCurrentRolePermission } from '@/api/sys'
2 3 import { useContentDataStoreWithOut } from '@/store/modules/contentData'
3 4 import { isShareMode } from '@/utils/env'
... ... @@ -6,6 +7,10 @@ export function useAuth() {
6 7 const contentDataStore = useContentDataStoreWithOut()
7 8 const getAuthInfo = async () => {
8 9 const result = { permissions: [] as string[], hasPreview: true, hasDesign: true }
  10 +
  11 + if (isFromEdge())
  12 + return Object.assign(result, { hasDesignAuth: true, hasPreviewAuth: true })
  13 +
9 14 if (isShareMode()) return result
10 15
11 16 const permissions = await getCurrentRolePermission()
... ...
  1 +import { isFromEdge } from './useParseParams'
1 2 import type { PlatformInfo } from '#/store'
2   -import { PLATFORM_INFO_CACHE_KEY } from '@/enums/cacheEnum'
  3 +import { APP_LOCAL_CACHE_KEY, EDGE_PLATFORM_INFO_CACHE_KEY, PLATFORM_INFO_CACHE_KEY } from '@/enums/cacheEnum'
3 4 import { createStorage } from '@/utils/cache'
4 5 import { getPlatformInfo as getPlatform } from '@/api/sys'
5 6
6   -const storage = createStorage()
7   -export const getPlatformInfo = () => storage.get(PLATFORM_INFO_CACHE_KEY) as PlatformInfo
  7 +const storage = createStorage(localStorage)
  8 +export const getPlatformInfo = (): PlatformInfo => {
  9 + if (isFromEdge()) {
  10 + const common = storage.get(APP_LOCAL_CACHE_KEY)
  11 + return common?.[EDGE_PLATFORM_INFO_CACHE_KEY]?.value || {}
  12 + }
  13 + else {
  14 + return storage.get(PLATFORM_INFO_CACHE_KEY) as PlatformInfo
  15 + }
  16 +}
  17 +
8 18 export const setPlatformInfo = (info: Recordable) => storage.set(PLATFORM_INFO_CACHE_KEY, info)
9 19
10 20 export const usePlatform = async () => {
... ...
... ... @@ -67,7 +67,7 @@ export class EventHandler {
67 67 if (!cell) return
68 68 const id = cell.getId()
69 69
70   - const node = this.service.dataSource.find(item => item.id === id)
  70 + const node = this.service.dataSource.find(item => item.configurationNodeId === id)
71 71
72 72 if (node && node.eventJson) {
73 73 const instanceId = getAppInstanceId(cell)
... ...
... ... @@ -56,8 +56,8 @@ export class LightboxModeWebsocketService extends TelemetryWebsockerService {
56 56 * @returns
57 57 */
58 58 getNodeDataSubscribers(nodeData: NodeDataType) {
59   - const { dataSourceJson, actJson, id } = nodeData
60   - const cell = this.nodeUtils.getCellById(id)
  59 + const { dataSourceJson, actJson, configurationNodeId } = nodeData
  60 + const cell = this.nodeUtils.getCellById(configurationNodeId)
61 61 if (!cell) return []
62 62 const componentKey = this.nodeUtils.getNodeComponentKey(cell)
63 63 const categoryKey = this.nodeUtils.getNodeCategory(cell)
... ... @@ -77,7 +77,7 @@ export class LightboxModeWebsocketService extends TelemetryWebsockerService {
77 77 const { deviceId, attr } = actJson[key as ActTypeEnum]
78 78 // 无entityId及属性时不订阅
79 79 if (deviceId && attr) {
80   - const subscribe = TelemetrySubscriber.createTimeseriesSubscription(this, { id: deviceId, entityType: EntityType.DEVICE }, attr, this.getCommandSource(id, DataSourceTypeEnum.ACT, actJson[key as ActTypeEnum], key as ActTypeEnum))
  80 + const subscribe = TelemetrySubscriber.createTimeseriesSubscription(this, { id: deviceId, entityType: EntityType.DEVICE }, attr, this.getCommandSource(configurationNodeId, DataSourceTypeEnum.ACT, actJson[key as ActTypeEnum], key as ActTypeEnum))
81 81 subscribers.push(subscribe)
82 82 }
83 83 }
... ... @@ -86,7 +86,7 @@ export class LightboxModeWebsocketService extends TelemetryWebsockerService {
86 86 const { deviceId, attr } = dataSourceJson || {}
87 87
88 88 if (deviceId && attr) {
89   - const subscribe = TelemetrySubscriber.createTimeseriesSubscription(this, { id: deviceId, entityType: EntityType.DEVICE }, attr, this.getCommandSource(id, DataSourceTypeEnum.DATASOURCE, dataSourceJson))
  89 + const subscribe = TelemetrySubscriber.createTimeseriesSubscription(this, { id: deviceId, entityType: EntityType.DEVICE }, attr, this.getCommandSource(configurationNodeId, DataSourceTypeEnum.DATASOURCE, dataSourceJson))
90 90 subscribers.push(subscribe)
91 91 }
92 92
... ...
... ... @@ -24,7 +24,6 @@ export class MessageHandler {
24 24 const telemetrySubscriber = this.service.subscribersMap.get(subscriptionId)
25 25
26 26 if (!telemetrySubscriber) return
27   -
28 27 const { commandSource } = telemetrySubscriber
29 28 const { dataType } = commandSource
30 29 if (dataType === DataSourceTypeEnum.DATASOURCE)
... ...
... ... @@ -23,7 +23,9 @@ export const APP_DARK_MODE_KEY = '__APP__DARK__MODE__'
23 23 export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__'
24 24
25 25 // base global session key
26   -export const PLATFORM_INFO_CACHE_KEY = 'PLATFORM_INFO'
  26 +export const PLATFORM_INFO_CACHE_KEY = 'PLATFORMINFO'
  27 +
  28 +export const EDGE_PLATFORM_INFO_CACHE_KEY = 'PLATFORM__INFO'
27 29
28 30 export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY__'
29 31
... ...
... ... @@ -3,4 +3,5 @@ export enum CellAttributeKeyEnum {
3 3 CATEGORY = 'category',
4 4 SHAPE_KEY = 'shapeKey',
5 5 COPY_SOURCE = 'copySource',
  6 + DEFAULT_IMAGE = 'defaultImage',
6 7 }
... ...
... ... @@ -54,6 +54,10 @@ export class NodeUtils {
54 54 model.setVisible(cell, value)
55 55 }
56 56
  57 + refreshCell(cell: MxCell) {
  58 + this.graph.refresh(cell)
  59 + }
  60 +
57 61 getNodeComponentKey(node: string | MxCell): Nullable<ComponentKey> {
58 62 const cell = isString(node) ? this.getCellById(node) : node
59 63 const cellValue = cell.getValue() as Element
... ...
  1 +import { isFromEdge } from '@/core/LoadData/module/useParseParams'
1 2 import { isDevMode } from '@/utils/env'
2 3
3 4 // System default cache time, in seconds
... ... @@ -10,5 +11,5 @@ export const cacheCipher = {
10 11 }
11 12
12 13 // Whether the system cache is encrypted using aes
13   -export const enableStorageEncryption = !isDevMode()
  14 +export const enableStorageEncryption = !isFromEdge() && !isDevMode()
14 15
... ...
... ... @@ -34,7 +34,7 @@ export const useContentDataStore = defineStore('app-content-data', {
34 34 actions: {
35 35
36 36 getNodeDataById(id: string): Undefineable<NodeDataType> {
37   - const data = this.contentData.find(item => item.id === id)
  37 + const data = this.contentData.find(item => item.configurationNodeId === id)
38 38 return data
39 39 },
40 40
... ... @@ -68,7 +68,7 @@ export const useContentDataStore = defineStore('app-content-data', {
68 68 const { cellInfo } = config
69 69 const { id } = cellInfo || {}
70 70 if (!id) return null
71   - return this.contentData.find(item => item.id === id) || null
  71 + return this.contentData.find(item => item.configurationNodeId === id) || null
72 72 },
73 73
74 74 setPermissions(string: string[]) {
... ...
... ... @@ -39,7 +39,7 @@ export function getShareRefreshToken(): string {
39 39 }
40 40
41 41 export function getLocale() {
42   - const { language } = (JSON.parse(localStorage.getItem('.drawio-config') || '') || {}) as DrawioConfig
  42 + const { language } = (JSON.parse(localStorage.getItem('.drawio-config') || '{}') || {}) as DrawioConfig
43 43
44 44 return language
45 45 }
... ...