diff --git a/.env b/.env index a10cc6f..5867188 100644 --- a/.env +++ b/.env @@ -1,5 +1,5 @@ # port 端口号 -VITE_PORT = 8888 +VITE_PORT = 4466 # open 运行 npm run dev 时自动打开浏览器 VITE_OPEN = false @@ -8,4 +8,4 @@ VITE_OPEN = false VITE_OPEN_CDN = false # public path 配置线上环境路径(打包)、本地通过 http-server 访问时,请置空即可 -VITE_PUBLIC_PATH = \ No newline at end of file +VITE_PUBLIC_PATH = \ No newline at end of file diff --git a/.gitignore b/.gitignore index 403adbc..bf9c2e8 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ pnpm-debug.log* *.njsproj *.sln *.sw? +!/yarn.lock diff --git a/index.html b/index.html index 5e83ac0..e1f6aed 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@ 网关采集配置器 - +
diff --git a/package.json b/package.json index c9e6372..3f5eded 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,10 @@ "dependencies": { "@element-plus/icons-vue": "^2.1.0", "axios": "^1.3.5", + "dayjs": "^1.11.13", "echarts": "^5.4.2", - "element-plus": "^2.5.0", + "element-plus": "^2.9.0", + "file-saver": "^2.0.5", "js-cookie": "^3.0.1", "mitt": "^3.0.0", "nprogress": "^0.2.0", @@ -26,7 +28,8 @@ "vue-clipboard3": "^2.0.0", "vue-demi": "^0.13.11", "vue-next-admin-template-js": "file:", - "vue-router": "^4.1.6" + "vue-router": "^4.1.6", + "xlsx": "^0.18.5" }, "devDependencies": { "@vitejs/plugin-vue": "^4.1.0", diff --git a/public/config.js b/public/config.js deleted file mode 100644 index 67b8ea3..0000000 --- a/public/config.js +++ /dev/null @@ -1,8 +0,0 @@ -// 手动配置的地址 -window.baseConfig = { - ip: 'digital-core.drgyen.com', - port: '', - prodApi: '', - protocol: 'https://', - wsProtocol: 'wss://' -} diff --git a/public/js/config.js b/public/js/config.js new file mode 100644 index 0000000..ff830b9 --- /dev/null +++ b/public/js/config.js @@ -0,0 +1,16 @@ +// 手动配置的地址 +// window.baseConfig = { +// ip: 'digital-core.drgyen.com', +// port: '', +// prodApi: '', +// protocol: 'https://', +// wsProtocol: 'wss://' +// } + +window.baseConfig = { + ip: '192.168.1.17', + port: '8000', + prodApi: '', + protocol: 'http://', + wsProtocol: 'ws://' +} \ No newline at end of file diff --git a/src/api/gateway/collectdatamonitor.js b/src/api/gateway/collectdatamonitor.js new file mode 100644 index 0000000..21fd1ed --- /dev/null +++ b/src/api/gateway/collectdatamonitor.js @@ -0,0 +1,30 @@ +import request from '/@/utils/request'; + +export function getDeviceCollectli(id) { + return request({ + url: '/data/collect?equipId='+id, + method: 'get', + }); +} + +export function getDeviceEquipli(data) { + return request({ + url: '/data/equip/list', + method: 'get', + data, + }); +} + +export function startDeviceCollect(id) { + return request({ + url: '/data/collect/start?equipId='+id, + method: 'get', + }); +} + +export function endDeviceCollect(id) { + return request({ + url: '/data/collect/end?equipId='+id, + method: 'get', + }); +} \ No newline at end of file diff --git a/src/api/gateway/northboundtask.js b/src/api/gateway/northboundtask.js new file mode 100644 index 0000000..d4df04a --- /dev/null +++ b/src/api/gateway/northboundtask.js @@ -0,0 +1,17 @@ +import request from '/@/utils/request'; + +export function getPlatformConf(data) { + return request({ + url: '/config/platform/query', + method: 'get', + data, + }); +} + +export function setPlatformConf(data) { + return request({ + url: '/config/platform/add', + method: 'post', + data, + }); +} diff --git a/src/api/gateway/southdirection.js b/src/api/gateway/southdirection.js new file mode 100644 index 0000000..437861d --- /dev/null +++ b/src/api/gateway/southdirection.js @@ -0,0 +1,25 @@ +import request from '/@/utils/request'; + +export function getDeviceConf(data) { + return request({ + url: '/config/equip/query', + method: 'get', + data, + }); +} + +export function setDeviceConf(data) { + return request({ + url: '/config/equip/add', + method: 'post', + data, + }); +} + +export function getSerialPortDataList(data) { + return request({ + url: '/config/serials', + method: 'get', + data, + }); +} diff --git a/src/layout/routerView/parent.vue b/src/layout/routerView/parent.vue index d6b3e22..97c8fa0 100644 --- a/src/layout/routerView/parent.vue +++ b/src/layout/routerView/parent.vue @@ -3,7 +3,7 @@ - + diff --git a/src/router/index.js b/src/router/index.js index 4b18bb7..6225fc8 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -108,7 +108,7 @@ router.beforeEach(async (to, from, next) => { Session.clear(); NProgress.done(); } else if (token && to.path === '/login') { - next('/home'); + next('/'); NProgress.done(); } else { const storesRoutesList = useRoutesList(pinia); diff --git a/src/router/route.js b/src/router/route.js index dcbfd2b..3672612 100644 --- a/src/router/route.js +++ b/src/router/route.js @@ -23,119 +23,164 @@ export const dynamicRoutes = [ path: '/', name: '/', component: () => import('/@/layout/index.vue'), - redirect: '/home', + redirect: '/southdirection', meta: { isKeepAlive: true, }, children: [ + // { + // path: '/home', + // name: 'home', + // component: () => import('/@/views/home/index.vue'), + // meta: { + // title: '首页', + // isLink: '', + // isHide: false, + // isKeepAlive: true, + // isAffix: true, + // isIframe: false, + // roles: ['admin', 'common'], + // icon: 'iconfont icon-shouye', + // }, + // }, { - path: '/home', - name: 'home', - component: () => import('/@/views/home/index.vue'), + path: '/southdirection', + name: 'southdirection', + component: () => import('/@/views/gateway/southdirection.vue'), meta: { - title: '首页', + title: '南向采集配置', isLink: '', isHide: false, isKeepAlive: true, isAffix: true, isIframe: false, roles: ['admin', 'common'], - icon: 'iconfont icon-shouye', + icon: 'ele-Bottom', }, }, { - path: '/system', - name: 'system', - component: () => import('/@/layout/routerView/parent.vue'), - redirect: '/system/menu', + path: '/northboundtask', + name: 'northboundtask', + component: () => import('/@/views/gateway/northboundtask.vue'), meta: { - title: '系统设置', + title: '北向任务配置', isLink: '', isHide: false, isKeepAlive: true, - isAffix: false, + isAffix: true, isIframe: false, - roles: ['admin'], - icon: 'iconfont icon-xitongshezhi', + roles: ['admin', 'common'], + icon: 'ele-Top', }, - children: [ - { - path: '/system/menu', - name: 'systemMenu', - component: () => import('/@/views/system/menu/index.vue'), - meta: { - title: '菜单管理', - isLink: '', - isHide: false, - isKeepAlive: true, - isAffix: false, - isIframe: false, - roles: ['admin'], - icon: 'iconfont icon-caidan', - }, - }, - { - path: '/system/role', - name: 'systemRole', - component: () => import('/@/views/system/role/index.vue'), - meta: { - title: '角色管理', - isLink: '', - isHide: false, - isKeepAlive: true, - isAffix: false, - isIframe: false, - roles: ['admin'], - icon: 'ele-ColdDrink', - }, - }, - { - path: '/system/user', - name: 'systemUser', - component: () => import('/@/views/system/user/index.vue'), - meta: { - title: '用户管理', - isLink: '', - isHide: false, - isKeepAlive: true, - isAffix: false, - isIframe: false, - roles: ['admin'], - icon: 'iconfont icon-icon-', - }, - }, - { - path: '/system/dept', - name: 'systemDept', - component: () => import('/@/views/system/dept/index.vue'), - meta: { - title: '部门管理', - isLink: '', - isHide: false, - isKeepAlive: true, - isAffix: false, - isIframe: false, - roles: ['admin'], - icon: 'ele-OfficeBuilding', - }, - }, - { - path: '/system/dic', - name: 'systemDic', - component: () => import('/@/views/system/dic/index.vue'), - meta: { - title: '字典管理', - isLink: '', - isHide: false, - isKeepAlive: true, - isAffix: false, - isIframe: false, - roles: ['admin'], - icon: 'ele-SetUp', - }, - }, - ], }, + { + path: '/collectdatamonitor', + name: 'collectdatamonitor', + component: () => import('/@/views/gateway/collectdatamonitor.vue'), + meta: { + title: '采集数据监视', + isLink: '', + isHide: false, + isKeepAlive: true, + isAffix: true, + isIframe: false, + roles: ['admin', 'common'], + icon: 'ele-Tickets', + }, + }, + // { + // path: '/system', + // name: 'system', + // component: () => import('/@/layout/routerView/parent.vue'), + // redirect: '/system/menu', + // meta: { + // title: '系统设置', + // isLink: '', + // isHide: false, + // isKeepAlive: true, + // isAffix: false, + // isIframe: false, + // roles: ['admin'], + // icon: 'iconfont icon-xitongshezhi', + // }, + // children: [ + // { + // path: '/system/menu', + // name: 'systemMenu', + // component: () => import('/@/views/system/menu/index.vue'), + // meta: { + // title: '菜单管理', + // isLink: '', + // isHide: false, + // isKeepAlive: true, + // isAffix: false, + // isIframe: false, + // roles: ['admin'], + // icon: 'iconfont icon-caidan', + // }, + // }, + // { + // path: '/system/role', + // name: 'systemRole', + // component: () => import('/@/views/system/role/index.vue'), + // meta: { + // title: '角色管理', + // isLink: '', + // isHide: false, + // isKeepAlive: true, + // isAffix: false, + // isIframe: false, + // roles: ['admin'], + // icon: 'ele-ColdDrink', + // }, + // }, + // { + // path: '/system/user', + // name: 'systemUser', + // component: () => import('/@/views/system/user/index.vue'), + // meta: { + // title: '用户管理', + // isLink: '', + // isHide: false, + // isKeepAlive: true, + // isAffix: false, + // isIframe: false, + // roles: ['admin'], + // icon: 'iconfont icon-icon-', + // }, + // }, + // { + // path: '/system/dept', + // name: 'systemDept', + // component: () => import('/@/views/system/dept/index.vue'), + // meta: { + // title: '部门管理', + // isLink: '', + // isHide: false, + // isKeepAlive: true, + // isAffix: false, + // isIframe: false, + // roles: ['admin'], + // icon: 'ele-OfficeBuilding', + // }, + // }, + // { + // path: '/system/dic', + // name: 'systemDic', + // component: () => import('/@/views/system/dic/index.vue'), + // meta: { + // title: '字典管理', + // isLink: '', + // isHide: false, + // isKeepAlive: true, + // isAffix: false, + // isIframe: false, + // roles: ['admin'], + // icon: 'ele-SetUp', + // }, + // }, + // ], + // }, ], }, ]; diff --git a/src/stores/themeConfig.js b/src/stores/themeConfig.js index 8c7aedc..64b1656 100644 --- a/src/stores/themeConfig.js +++ b/src/stores/themeConfig.js @@ -82,7 +82,7 @@ export const useThemeConfig = defineStore('themeConfig', { // 初始化变量,用于 el-scrollbar 的高度更新,请勿删除 isShowLogoChange: false, // 是否开启 Breadcrumb,强制经典、横向布局不显示 - isBreadcrumb: false, + isBreadcrumb: true, // 是否开启 Tagsview isTagsview: false, // 是否开启 Breadcrumb 图标 @@ -145,7 +145,7 @@ export const useThemeConfig = defineStore('themeConfig', { // 默认初始语言,可选值"",默认 zh-cn globalI18n: 'zh-cn', // 默认全局组件大小,可选值"",默认 'large' - globalComponentSize: 'large', + globalComponentSize: 'default', }, }), actions: { diff --git a/src/utils/function.js b/src/utils/function.js new file mode 100644 index 0000000..bb06555 --- /dev/null +++ b/src/utils/function.js @@ -0,0 +1,6 @@ +export function guidGenerator() { + var S4 = function() { + return ((1 + Math.random())*0X10000|0).toString(16).substring(1); + }; + return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); +} diff --git a/src/views/gateway/collectdatamonitor.vue b/src/views/gateway/collectdatamonitor.vue new file mode 100644 index 0000000..b79f0dc --- /dev/null +++ b/src/views/gateway/collectdatamonitor.vue @@ -0,0 +1,263 @@ + + + + + diff --git a/src/views/gateway/northboundtask.vue b/src/views/gateway/northboundtask.vue new file mode 100644 index 0000000..ce9d284 --- /dev/null +++ b/src/views/gateway/northboundtask.vue @@ -0,0 +1,655 @@ + + + + + + diff --git a/src/views/gateway/southdirection.vue b/src/views/gateway/southdirection.vue new file mode 100644 index 0000000..42a9b01 --- /dev/null +++ b/src/views/gateway/southdirection.vue @@ -0,0 +1,1048 @@ + + + + + + diff --git a/vite.config.js b/vite.config.js index 22c62fe..9bf6a54 100644 --- a/vite.config.js +++ b/vite.config.js @@ -29,12 +29,17 @@ const viteConfig = defineConfig((mode) => { open: JSON.parse(env.VITE_OPEN), hmr: true, proxy: { - '/gitee': { - target: 'https://gitee.com', - ws: true, - changeOrigin: true, - rewrite: (path) => path.replace(/^\/gitee/, ''), - }, + // '/gitee': { + // target: 'https://gitee.com', + // ws: true, + // changeOrigin: true, + // rewrite: (path) => path.replace(/^\/gitee/, ''), + // }, + // '/config': { + // target: 'http://192.168.1.17:8000', + // changeOrigin: true, + // rewrite: (path) => path.replace(/^\/config/, ''), + // }, }, }, build: { diff --git a/yarn.lock b/yarn.lock index eaf67b2..8f8ecaf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -383,6 +383,11 @@ acorn@^8.8.0: resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== +adler-32@~1.3.0: + version "1.3.1" + resolved "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz#1dbf0b36dda0012189a32b3679061932df1821e2" + integrity sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A== + ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" @@ -480,6 +485,14 @@ callsites@^3.0.0: resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +cfb@~1.2.1: + version "1.2.2" + resolved "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz#94e687628c700e5155436dac05f74e08df23bc44" + integrity sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA== + dependencies: + adler-32 "~1.3.0" + crc-32 "~1.2.0" + chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" @@ -512,6 +525,11 @@ clipboard@^2.0.6: select "^1.1.2" tiny-emitter "^2.0.0" +codepage@~1.15.0: + version "1.15.0" + resolved "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz#2e00519024b39424ec66eeb3ec07227e692618ab" + integrity sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA== + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" @@ -536,6 +554,11 @@ concat-map@0.0.1: resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +crc-32@~1.2.0, crc-32@~1.2.1: + version "1.2.2" + resolved "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" @@ -597,7 +620,7 @@ echarts@^5.4.2: tslib "2.3.0" zrender "5.4.3" -element-plus@^2.5.0: +element-plus@^2.7.6, element-plus@^2.9.0: version "2.9.0" resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.0.tgz#76a16566ab6dbadb555a40704bde870a02c306bc" integrity sha512-ccOFXKsauo2dtokAr4OX7gZsb7TuAoVxA2zGRZo5o2yyDDBLBaZxOoFQPoxITSLcHbBfQuNDGK5Iag5hnyKkZA== @@ -795,6 +818,11 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-saver@^2.0.5: + version "2.0.5" + resolved "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" + integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" @@ -837,6 +865,11 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +frac@~1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b" + integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA== + fs-extra@^10.0.0: version "10.1.0" resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz" @@ -1433,6 +1466,13 @@ sourcemap-codec@^1.4.8: resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== +ssf@~0.11.2: + version "0.11.2" + resolved "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz#0b99698b237548d088fc43cdf2b70c1a7512c06c" + integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g== + dependencies: + frac "~1.1.2" + strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -1571,8 +1611,10 @@ vue-eslint-parser@^9.0.1, vue-eslint-parser@^9.1.1: dependencies: "@element-plus/icons-vue" "^2.1.0" axios "^1.3.5" + dayjs "^1.11.13" echarts "^5.4.2" - element-plus "^2.5.0" + element-plus "^2.7.6" + file-saver "^2.0.5" js-cookie "^3.0.1" mitt "^3.0.0" nprogress "^0.2.0" @@ -1584,8 +1626,9 @@ vue-eslint-parser@^9.0.1, vue-eslint-parser@^9.1.1: vue "^3.2.47" vue-clipboard3 "^2.0.0" vue-demi "^0.13.11" - vue-next-admin-template-js "file:C:/Users/Administrator/AppData/Local/Yarn/Cache/v6/npm-vue-next-admin-template-js-2.4.33-7ca98d43-7ddc-421a-a897-166f94ead9bb-1733975867024/node_modules/vue-next-admin-template-js" + vue-next-admin-template-js "file:C:/Users/Administrator/AppData/Local/Yarn/Cache/v6/npm-vue-next-admin-template-js-2.4.33-d6f20349-ce84-4f4c-b83e-27e36d4b1985-1733992643913/node_modules/vue-next-admin-template-js" vue-router "^4.1.6" + xlsx "^0.18.5" vue-router@^4.1.6: version "4.1.6" @@ -1612,16 +1655,39 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wmf@~1.0.1: + version "1.0.2" + resolved "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz#7d19d621071a08c2bdc6b7e688a9c435298cc2da" + integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw== + word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +word@~0.3.0: + version "0.3.0" + resolved "https://registry.npmmirror.com/word/-/word-0.3.0.tgz#8542157e4f8e849f4a363a288992d47612db9961" + integrity sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA== + wrappy@1: version "1.0.2" resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +xlsx@^0.18.5: + version "0.18.5" + resolved "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz#16711b9113c848076b8a177022799ad356eba7d0" + integrity sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ== + dependencies: + adler-32 "~1.3.0" + cfb "~1.2.1" + codepage "~1.15.0" + crc-32 "~1.2.1" + ssf "~0.11.2" + wmf "~1.0.1" + word "~0.3.0" + xml-name-validator@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz"