yb 3 gün önce
ebeveyn
işleme
b5a97c0c43

+ 91 - 0
.cursorignore

@@ -0,0 +1,91 @@
+# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
+
+# ============================================
+# 构建产物和依赖
+# ============================================
+node_modules/
+dist/
+dist-dev/
+dist-ssr/
+out-tsc/
+coverage/
+tmp/
+
+# ============================================
+# 锁文件和包管理
+# ============================================
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
+
+# ============================================
+# 日志文件
+# ============================================
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+# ============================================
+# 自动生成的文件
+# ============================================
+types/auto-imports.d.ts
+types/components.d.ts
+*.local
+
+# ============================================
+# 大型二进制文件
+# ============================================
+*.wasm
+*.zip
+*.tar.gz
+
+# ============================================
+# 测试和覆盖率
+# ============================================
+/cypress/videos/
+/cypress/screenshots/
+coverage/
+
+# ============================================
+# CI/CD 和部署脚本(可选,如果不需要 AI 理解这些)
+# ============================================
+jenkins/
+Jenkinsfile
+*.sh
+
+# ============================================
+# 编辑器配置
+# ============================================
+.vscode/*
+!.vscode/extensions.json
+.idea/
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+# ============================================
+# 环境变量和敏感文件
+# ============================================
+.env
+.env.local
+.env.*.local
+
+# ============================================
+# 缓存目录
+# ============================================
+.cache/
+.wrangler/
+.DS_Store
+
+# ============================================
+# AI 工具自身文件
+# ============================================
+.cursor/
+.cursorrules*
+.claude/
+.crush/

+ 112 - 0
.cz-config.js

@@ -0,0 +1,112 @@
+module.exports = {
+  // type 类型(定义之后,可通过上下键选择)
+  types: [
+    {
+      value: 'feat',
+      name: 'feat:     新增功能'
+    },
+    {
+      value: 'fix',
+      name: 'fix:      修复 bug'
+    },
+    {
+      value: 'docs',
+      name: 'docs:     文档变更'
+    },
+    {
+      value: 'style',
+      name: 'style:    代码格式(不影响功能,例如空格、分号等格式修正)'
+    },
+    {
+      value: 'refactor',
+      name: 'refactor:    代码重构(不包括 bug 修复、功能新增)'
+    },
+    {
+      value: 'perf',
+      name: 'perf:     性能优化'
+    },
+    {
+      value: 'test',
+      name: 'test:     添加、修改测试用例'
+    },
+    {
+      value: 'build',
+      name: 'build:    构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)'
+    },
+    {
+      value: 'ci',
+      name: 'ci:       修改 CI 配置、脚本'
+    },
+    {
+      value: 'chore',
+      name: 'chore:    对构建过程或辅助工具和库的更改(不影响源文件、测试用例)'
+    },
+    {
+      value: 'revert',
+      name: 'revert:   回滚 commit'
+    }
+  ],
+
+  // scope 类型(定义之后,可通过上下键选择)
+  scopes: [
+    ['components', '组件相关'],
+    ['hooks', 'hook 相关'],
+    ['utils', 'utils 相关'],
+    ['element-plus', '对 element-plus 的调整'],
+    ['styles', '样式相关'],
+    ['deps', '项目依赖'],
+    ['auth', '对 auth 修改'],
+    ['other', '其他修改'],
+    // 如果选择 custom,后面会让你再输入一个自定义的 scope。也可以不设置此项,把后面的 allowCustomScopes 设置为 true
+    ['custom', '以上都不是?我要自定义']
+  ].map(([value, description]) => {
+    return {
+      value,
+      name: `${value.padEnd(30)} (${description})`
+    }
+  }),
+
+  // 是否允许自定义填写 scope,在 scope 选择的时候,会有 empty 和 custom 可以选择。
+  // allowCustomScopes: true,
+
+  // allowTicketNumber: false,
+  // isTicketNumberRequired: false,
+  // ticketNumberPrefix: 'TICKET-',
+  // ticketNumberRegExp: '\\d{1,5}',
+
+  // 针对每一个 type 去定义对应的 scopes,例如 fix
+  /*
+  scopeOverrides: {
+    fix: [
+      { name: 'merge' },
+      { name: 'style' },
+      { name: 'e2eTest' },
+      { name: 'unitTest' }
+    ]
+  },
+  */
+
+  // 交互提示信息
+  messages: {
+    type: '确保本次提交遵循 Angular 规范!\n选择你要提交的类型:',
+    scope: '\n选择一个 scope(可选):',
+    // 选择 scope: custom 时会出下面的提示
+    customScope: '请输入自定义的 scope:',
+    subject: '填写简短精炼的变更描述:\n',
+    body: '填写更加详细的变更描述(可选)。使用 "|" 换行:\n',
+    breaking: '列举非兼容性重大的变更(可选):\n',
+    footer: '列举出所有变更的 ISSUES CLOSED(可选)。 例如: #31, #34:\n',
+    confirmCommit: '确认提交?'
+  },
+
+  // 设置只有 type 选择了 feat 或 fix,才询问 breaking message
+  allowBreakingChanges: ['feat', 'fix'],
+
+  // 跳过要询问的步骤
+  // skipQuestions: ['body', 'footer'],
+
+  subjectLimit: 100, // subject 限制长度
+  breaklineChar: '|' // 换行符,支持 body 和 footer
+  // footerPrefix : 'ISSUES CLOSED:'
+  // askForBreakingChangeFirst : true,
+}

+ 4 - 4
i18next-scanner.config.cjs

@@ -9,10 +9,10 @@ const typescriptTransform = require('i18next-scanner-typescript')
 
 module.exports = {
   input: [
-    'src/**/*.{js,jsx,ts,tsx,vue}',
-    // 排除不需要扫描的目录
-    '!src/locales/**',
-    '!**/node_modules/**'
+    'src/**/*.{js,jsx,ts,tsx,vue}', //  扫描 js、jsx、ts,tsx, vue 文件
+    '!test/**/*.spec.{js,ts}', // 排除测试文件
+    '!src/locales/**', // 排除 locales 文件夹
+    '!**/node_modules/**' // 排除 node_modules
   ],
   output: './',
   options: {

+ 8 - 0
index.html

@@ -9,5 +9,13 @@
   <body>
     <div id="app"></div>
     <script type="module" src="/src/main.ts"></script>
+    <!-- 加解密-->
+    <script src="wasm_exec.js"></script>
+    <script>
+      const go = new Go()
+      WebAssembly.instantiateStreaming(fetch('./mimlib.wasm'), go.importObject).then((result) => {
+        go.run(result.instance)
+      })
+    </script>
   </body>
 </html>

+ 10 - 0
package.json

@@ -40,6 +40,7 @@
     "@vueuse/core": "^14.1.0",
     "axios": "^1.4.0",
     "codemirror": "^6.0.2",
+    "cz-customizable": "^7.5.1",
     "date-fns": "^4.1.0",
     "date-fns-tz": "^3.2.0",
     "dayjs": "^1.11.19",
@@ -73,11 +74,15 @@
     "@vitest/ui": "^4.0.16",
     "@vue/test-utils": "^2.0.0-rc.4",
     "@vue/tsconfig": "^0.4.0",
+    "@vue/eslint-config-prettier": "^7.1.0",
+    "@vue/eslint-config-typescript": "^11.0.3",
     "eslint": "^8.57.1",
     "eslint-config-airbnb-base": "^14.2.1",
     "eslint-config-prettier": "^8.1.0",
     "eslint-plugin-import": "^2.22.1",
+    "eslint-plugin-jest": "^28.11.0",
     "eslint-plugin-prettier": "^3.3.1",
+    "eslint-plugin-unused-imports": "^4.1.4",
     "eslint-plugin-vue": "^9.11.0",
     "happy-dom": "^20.0.11",
     "husky": "^6.0.0",
@@ -93,5 +98,10 @@
     "vite-plugin-vue-devtools": "^7.7.0",
     "vitest": "^4.0.16",
     "vue-tsc": "2.1.10"
+  },
+  "config": {
+    "commitizen": {
+      "path": "./node_modules/cz-customizable"
+    }
   }
 }

Dosya farkı çok büyük olduğundan ihmal edildi
+ 462 - 0
pnpm-lock.yaml


BIN
public/mimlib.wasm


+ 44 - 0
public/robots.txt

@@ -0,0 +1,44 @@
+# Robots.txt for tk-super-admin
+# Prevent all web crawlers from accessing the site
+
+User-agent: *
+Disallow: /
+Crawl-delay: 86400
+
+# Block specific bots
+User-agent: Googlebot
+Disallow: /
+
+User-agent: Bingbot
+Disallow: /
+
+User-agent: Slurp
+Disallow: /
+
+User-agent: DuckDuckBot
+Disallow: /
+
+User-agent: Baiduspider
+Disallow: /
+
+User-agent: YandexBot
+Disallow: /
+
+# Block social media bots
+User-agent: facebookexternalhit
+Disallow: /
+
+User-agent: Twitterbot
+Disallow: /
+
+User-agent: LinkedInBot
+Disallow: /
+
+User-agent: WhatsApp
+Disallow: /
+
+User-agent: TelegramBot
+Disallow: /
+
+# No sitemap
+Sitemap:

+ 609 - 0
public/wasm_exec.js

@@ -0,0 +1,609 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// This file has been modified for use by the TinyGo compiler.
+
+;(() => {
+  // Map multiple JavaScript environments to a single common API,
+  // preferring web standards over Node.js API.
+  //
+  // Environments considered:
+  // - Browsers
+  // - Node.js
+  // - Electron
+  // - Parcel
+
+  if (typeof global !== 'undefined') {
+    // global already exists
+  } else if (typeof window !== 'undefined') {
+    window.global = window
+  } else if (typeof self !== 'undefined') {
+    self.global = self
+  } else {
+    throw new Error('cannot export Go (neither global, window nor self is defined)')
+  }
+
+  if (!global.require && typeof require !== 'undefined') {
+    global.require = require
+  }
+
+  if (!global.fs && global.require) {
+    global.fs = require('fs')
+  }
+
+  const enosys = () => {
+    const err = new Error('not implemented')
+    err.code = 'ENOSYS'
+    return err
+  }
+
+  if (!global.fs) {
+    let outputBuf = ''
+    global.fs = {
+      constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
+      writeSync(fd, buf) {
+        outputBuf += decoder.decode(buf)
+        const nl = outputBuf.lastIndexOf('\n')
+        if (nl != -1) {
+          console.log(outputBuf.substr(0, nl))
+          outputBuf = outputBuf.substr(nl + 1)
+        }
+        return buf.length
+      },
+      write(fd, buf, offset, length, position, callback) {
+        if (offset !== 0 || length !== buf.length || position !== null) {
+          callback(enosys())
+          return
+        }
+        const n = this.writeSync(fd, buf)
+        callback(null, n)
+      },
+      chmod(path, mode, callback) {
+        callback(enosys())
+      },
+      chown(path, uid, gid, callback) {
+        callback(enosys())
+      },
+      close(fd, callback) {
+        callback(enosys())
+      },
+      fchmod(fd, mode, callback) {
+        callback(enosys())
+      },
+      fchown(fd, uid, gid, callback) {
+        callback(enosys())
+      },
+      fstat(fd, callback) {
+        callback(enosys())
+      },
+      fsync(fd, callback) {
+        callback(null)
+      },
+      ftruncate(fd, length, callback) {
+        callback(enosys())
+      },
+      lchown(path, uid, gid, callback) {
+        callback(enosys())
+      },
+      link(path, link, callback) {
+        callback(enosys())
+      },
+      lstat(path, callback) {
+        callback(enosys())
+      },
+      mkdir(path, perm, callback) {
+        callback(enosys())
+      },
+      open(path, flags, mode, callback) {
+        callback(enosys())
+      },
+      read(fd, buffer, offset, length, position, callback) {
+        callback(enosys())
+      },
+      readdir(path, callback) {
+        callback(enosys())
+      },
+      readlink(path, callback) {
+        callback(enosys())
+      },
+      rename(from, to, callback) {
+        callback(enosys())
+      },
+      rmdir(path, callback) {
+        callback(enosys())
+      },
+      stat(path, callback) {
+        callback(enosys())
+      },
+      symlink(path, link, callback) {
+        callback(enosys())
+      },
+      truncate(path, length, callback) {
+        callback(enosys())
+      },
+      unlink(path, callback) {
+        callback(enosys())
+      },
+      utimes(path, atime, mtime, callback) {
+        callback(enosys())
+      }
+    }
+  }
+
+  if (!global.process) {
+    global.process = {
+      getuid() {
+        return -1
+      },
+      getgid() {
+        return -1
+      },
+      geteuid() {
+        return -1
+      },
+      getegid() {
+        return -1
+      },
+      getgroups() {
+        throw enosys()
+      },
+      pid: -1,
+      ppid: -1,
+      umask() {
+        throw enosys()
+      },
+      cwd() {
+        throw enosys()
+      },
+      chdir() {
+        throw enosys()
+      }
+    }
+  }
+
+  if (!global.crypto) {
+    const nodeCrypto = require('crypto')
+    global.crypto = {
+      getRandomValues(b) {
+        nodeCrypto.randomFillSync(b)
+      }
+    }
+  }
+
+  if (!global.performance) {
+    global.performance = {
+      now() {
+        const [sec, nsec] = process.hrtime()
+        return sec * 1000 + nsec / 1000000
+      }
+    }
+  }
+
+  if (!global.TextEncoder) {
+    global.TextEncoder = require('util').TextEncoder
+  }
+
+  if (!global.TextDecoder) {
+    global.TextDecoder = require('util').TextDecoder
+  }
+
+  // End of polyfills for common API.
+
+  const encoder = new TextEncoder('utf-8')
+  const decoder = new TextDecoder('utf-8')
+  var logLine = []
+
+  global.Go = class {
+    constructor() {
+      this._callbackTimeouts = new Map()
+      this._nextCallbackTimeoutID = 1
+
+      const mem = () => {
+        // The buffer may change when requesting more memory.
+        return new DataView(this._inst.exports.memory.buffer)
+      }
+
+      const setInt64 = (addr, v) => {
+        mem().setUint32(addr + 0, v, true)
+        mem().setUint32(addr + 4, Math.floor(v / 4294967296), true)
+      }
+
+      const getInt64 = (addr) => {
+        const low = mem().getUint32(addr + 0, true)
+        const high = mem().getInt32(addr + 4, true)
+        return low + high * 4294967296
+      }
+
+      const loadValue = (addr) => {
+        const f = mem().getFloat64(addr, true)
+        if (f === 0) {
+          return undefined
+        }
+        if (!isNaN(f)) {
+          return f
+        }
+
+        const id = mem().getUint32(addr, true)
+        return this._values[id]
+      }
+
+      const storeValue = (addr, v) => {
+        const nanHead = 0x7ff80000
+
+        if (typeof v === 'number') {
+          if (isNaN(v)) {
+            mem().setUint32(addr + 4, nanHead, true)
+            mem().setUint32(addr, 0, true)
+            return
+          }
+          if (v === 0) {
+            mem().setUint32(addr + 4, nanHead, true)
+            mem().setUint32(addr, 1, true)
+            return
+          }
+          mem().setFloat64(addr, v, true)
+          return
+        }
+
+        switch (v) {
+          case undefined:
+            mem().setFloat64(addr, 0, true)
+            return
+          case null:
+            mem().setUint32(addr + 4, nanHead, true)
+            mem().setUint32(addr, 2, true)
+            return
+          case true:
+            mem().setUint32(addr + 4, nanHead, true)
+            mem().setUint32(addr, 3, true)
+            return
+          case false:
+            mem().setUint32(addr + 4, nanHead, true)
+            mem().setUint32(addr, 4, true)
+            return
+        }
+
+        let id = this._ids.get(v)
+        if (id === undefined) {
+          id = this._idPool.pop()
+          if (id === undefined) {
+            id = this._values.length
+          }
+          this._values[id] = v
+          this._goRefCounts[id] = 0
+          this._ids.set(v, id)
+        }
+        this._goRefCounts[id]++
+        let typeFlag = 1
+        switch (typeof v) {
+          case 'string':
+            typeFlag = 2
+            break
+          case 'symbol':
+            typeFlag = 3
+            break
+          case 'function':
+            typeFlag = 4
+            break
+        }
+        mem().setUint32(addr + 4, nanHead | typeFlag, true)
+        mem().setUint32(addr, id, true)
+      }
+
+      const loadSlice = (array, len, cap) => {
+        return new Uint8Array(this._inst.exports.memory.buffer, array, len)
+      }
+
+      const loadSliceOfValues = (array, len, cap) => {
+        const a = new Array(len)
+        for (let i = 0; i < len; i++) {
+          a[i] = loadValue(array + i * 8)
+        }
+        return a
+      }
+
+      const loadString = (ptr, len) => {
+        return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len))
+      }
+
+      const timeOrigin = Date.now() - performance.now()
+      this.importObject = {
+        wasi_snapshot_preview1: {
+          // https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write
+          fd_write: function (fd, iovs_ptr, iovs_len, nwritten_ptr) {
+            let nwritten = 0
+            if (fd == 1) {
+              for (let iovs_i = 0; iovs_i < iovs_len; iovs_i++) {
+                let iov_ptr = iovs_ptr + iovs_i * 8 // assuming wasm32
+                let ptr = mem().getUint32(iov_ptr + 0, true)
+                let len = mem().getUint32(iov_ptr + 4, true)
+                nwritten += len
+                for (let i = 0; i < len; i++) {
+                  let c = mem().getUint8(ptr + i)
+                  if (c == 13) {
+                    // CR
+                    // ignore
+                  } else if (c == 10) {
+                    // LF
+                    // write line
+                    let line = decoder.decode(new Uint8Array(logLine))
+                    logLine = []
+                    console.log(line)
+                  } else {
+                    logLine.push(c)
+                  }
+                }
+              }
+            } else {
+              console.error('invalid file descriptor:', fd)
+            }
+            mem().setUint32(nwritten_ptr, nwritten, true)
+            return 0
+          },
+          fd_close: () => 0, // dummy
+          fd_fdstat_get: () => 0, // dummy
+          fd_seek: () => 0, // dummy
+          proc_exit: (code) => {
+            if (global.process) {
+              // Node.js
+              process.exit(code)
+            } else {
+              // Can't exit in a browser.
+              throw 'trying to exit with code ' + code
+            }
+          },
+          random_get: (bufPtr, bufLen) => {
+            crypto.getRandomValues(loadSlice(bufPtr, bufLen))
+            return 0
+          }
+        },
+        env: {
+          // func ticks() float64
+          'runtime.ticks': () => {
+            return timeOrigin + performance.now()
+          },
+
+          // func sleepTicks(timeout float64)
+          'runtime.sleepTicks': (timeout) => {
+            // Do not sleep, only reactivate scheduler after the given timeout.
+            setTimeout(this._inst.exports.go_scheduler, timeout)
+          },
+
+          // func finalizeRef(v ref)
+          'syscall/js.finalizeRef': (v_addr) => {
+            // Note: TinyGo does not support finalizers so this is only called
+            // for one specific case, by js.go:jsString.
+            const id = mem().getUint32(v_addr, true)
+            this._goRefCounts[id]--
+            if (this._goRefCounts[id] === 0) {
+              const v = this._values[id]
+              this._values[id] = null
+              this._ids.delete(v)
+              this._idPool.push(id)
+            }
+          },
+
+          // func stringVal(value string) ref
+          'syscall/js.stringVal': (ret_ptr, value_ptr, value_len) => {
+            const s = loadString(value_ptr, value_len)
+            storeValue(ret_ptr, s)
+          },
+
+          // func valueGet(v ref, p string) ref
+          'syscall/js.valueGet': (retval, v_addr, p_ptr, p_len) => {
+            let prop = loadString(p_ptr, p_len)
+            let value = loadValue(v_addr)
+            let result = Reflect.get(value, prop)
+            storeValue(retval, result)
+          },
+
+          // func valueSet(v ref, p string, x ref)
+          'syscall/js.valueSet': (v_addr, p_ptr, p_len, x_addr) => {
+            const v = loadValue(v_addr)
+            const p = loadString(p_ptr, p_len)
+            const x = loadValue(x_addr)
+            Reflect.set(v, p, x)
+          },
+
+          // func valueDelete(v ref, p string)
+          'syscall/js.valueDelete': (v_addr, p_ptr, p_len) => {
+            const v = loadValue(v_addr)
+            const p = loadString(p_ptr, p_len)
+            Reflect.deleteProperty(v, p)
+          },
+
+          // func valueIndex(v ref, i int) ref
+          'syscall/js.valueIndex': (ret_addr, v_addr, i) => {
+            storeValue(ret_addr, Reflect.get(loadValue(v_addr), i))
+          },
+
+          // valueSetIndex(v ref, i int, x ref)
+          'syscall/js.valueSetIndex': (v_addr, i, x_addr) => {
+            Reflect.set(loadValue(v_addr), i, loadValue(x_addr))
+          },
+
+          // func valueCall(v ref, m string, args []ref) (ref, bool)
+          'syscall/js.valueCall': (ret_addr, v_addr, m_ptr, m_len, args_ptr, args_len, args_cap) => {
+            const v = loadValue(v_addr)
+            const name = loadString(m_ptr, m_len)
+            const args = loadSliceOfValues(args_ptr, args_len, args_cap)
+            try {
+              const m = Reflect.get(v, name)
+              storeValue(ret_addr, Reflect.apply(m, v, args))
+              mem().setUint8(ret_addr + 8, 1)
+            } catch (err) {
+              storeValue(ret_addr, err)
+              mem().setUint8(ret_addr + 8, 0)
+            }
+          },
+
+          // func valueInvoke(v ref, args []ref) (ref, bool)
+          'syscall/js.valueInvoke': (ret_addr, v_addr, args_ptr, args_len, args_cap) => {
+            try {
+              const v = loadValue(v_addr)
+              const args = loadSliceOfValues(args_ptr, args_len, args_cap)
+              storeValue(ret_addr, Reflect.apply(v, undefined, args))
+              mem().setUint8(ret_addr + 8, 1)
+            } catch (err) {
+              storeValue(ret_addr, err)
+              mem().setUint8(ret_addr + 8, 0)
+            }
+          },
+
+          // func valueNew(v ref, args []ref) (ref, bool)
+          'syscall/js.valueNew': (ret_addr, v_addr, args_ptr, args_len, args_cap) => {
+            const v = loadValue(v_addr)
+            const args = loadSliceOfValues(args_ptr, args_len, args_cap)
+            try {
+              storeValue(ret_addr, Reflect.construct(v, args))
+              mem().setUint8(ret_addr + 8, 1)
+            } catch (err) {
+              storeValue(ret_addr, err)
+              mem().setUint8(ret_addr + 8, 0)
+            }
+          },
+
+          // func valueLength(v ref) int
+          'syscall/js.valueLength': (v_addr) => {
+            return loadValue(v_addr).length
+          },
+
+          // valuePrepareString(v ref) (ref, int)
+          'syscall/js.valuePrepareString': (ret_addr, v_addr) => {
+            const s = String(loadValue(v_addr))
+            const str = encoder.encode(s)
+            storeValue(ret_addr, str)
+            setInt64(ret_addr + 8, str.length)
+          },
+
+          // valueLoadString(v ref, b []byte)
+          'syscall/js.valueLoadString': (v_addr, slice_ptr, slice_len, slice_cap) => {
+            const str = loadValue(v_addr)
+            loadSlice(slice_ptr, slice_len, slice_cap).set(str)
+          },
+
+          // func valueInstanceOf(v ref, t ref) bool
+          'syscall/js.valueInstanceOf': (v_addr, t_addr) => {
+            return loadValue(v_addr) instanceof loadValue(t_addr)
+          },
+
+          // func copyBytesToGo(dst []byte, src ref) (int, bool)
+          'syscall/js.copyBytesToGo': (ret_addr, dest_addr, dest_len, dest_cap, source_addr) => {
+            let num_bytes_copied_addr = ret_addr
+            let returned_status_addr = ret_addr + 4 // Address of returned boolean status variable
+
+            const dst = loadSlice(dest_addr, dest_len)
+            const src = loadValue(source_addr)
+            if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
+              mem().setUint8(returned_status_addr, 0) // Return "not ok" status
+              return
+            }
+            const toCopy = src.subarray(0, dst.length)
+            dst.set(toCopy)
+            setInt64(num_bytes_copied_addr, toCopy.length)
+            mem().setUint8(returned_status_addr, 1) // Return "ok" status
+          },
+
+          // copyBytesToJS(dst ref, src []byte) (int, bool)
+          // Originally copied from upstream Go project, then modified:
+          //   https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416
+          'syscall/js.copyBytesToJS': (ret_addr, dest_addr, source_addr, source_len, source_cap) => {
+            let num_bytes_copied_addr = ret_addr
+            let returned_status_addr = ret_addr + 4 // Address of returned boolean status variable
+
+            const dst = loadValue(dest_addr)
+            const src = loadSlice(source_addr, source_len)
+            if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
+              mem().setUint8(returned_status_addr, 0) // Return "not ok" status
+              return
+            }
+            const toCopy = src.subarray(0, dst.length)
+            dst.set(toCopy)
+            setInt64(num_bytes_copied_addr, toCopy.length)
+            mem().setUint8(returned_status_addr, 1) // Return "ok" status
+          }
+        }
+      }
+    }
+
+    async run(instance) {
+      this._inst = instance
+      this._values = [
+        // JS values that Go currently has references to, indexed by reference id
+        NaN,
+        0,
+        null,
+        true,
+        false,
+        global,
+        this
+      ]
+      this._goRefCounts = [] // number of references that Go has to a JS value, indexed by reference id
+      this._ids = new Map() // mapping from JS values to reference ids
+      this._idPool = [] // unused ids that have been garbage collected
+      this.exited = false // whether the Go program has exited
+
+      const mem = new DataView(this._inst.exports.memory.buffer)
+
+      while (true) {
+        const callbackPromise = new Promise((resolve) => {
+          this._resolveCallbackPromise = () => {
+            if (this.exited) {
+              throw new Error('bad callback: Go program has already exited')
+            }
+            setTimeout(resolve, 0) // make sure it is asynchronous
+          }
+        })
+        this._inst.exports._start()
+        if (this.exited) {
+          break
+        }
+        await callbackPromise
+      }
+    }
+
+    _resume() {
+      if (this.exited) {
+        throw new Error('Go program has already exited')
+      }
+      this._inst.exports.resume()
+      if (this.exited) {
+        this._resolveExitPromise()
+      }
+    }
+
+    _makeFuncWrapper(id) {
+      const go = this
+      return function () {
+        const event = { id: id, this: this, args: arguments }
+        go._pendingEvent = event
+        go._resume()
+        return event.result
+      }
+    }
+  }
+
+  if (
+    global.require &&
+    global.require.main === module &&
+    global.process &&
+    global.process.versions &&
+    !global.process.versions.electron
+  ) {
+    if (process.argv.length != 3) {
+      console.error('usage: go_js_wasm_exec [wasm binary] [arguments]')
+      process.exit(1)
+    }
+
+    const go = new Go()
+    WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject)
+      .then((result) => {
+        return go.run(result.instance)
+      })
+      .catch((err) => {
+        console.error(err)
+        process.exit(1)
+      })
+  }
+})()

+ 8 - 8
src/views/camera-vendor/index.vue

@@ -29,16 +29,16 @@
           </el-select>
         </el-form-item>
         <el-form-item>
-          <el-button type="primary" :icon="Search" data-id="btn-search" @click="handleSearch">
+          <el-button type="primary" data-id="btn-search" @click="handleSearch">
             {{ t('查询') }}
           </el-button>
           <el-button :icon="RefreshRight" data-id="btn-reset" @click="handleReset">{{ t('重置') }}</el-button>
-          <el-button type="primary" :icon="Plus" data-id="btn-add-vendor" @click="handleAdd">
+          <el-button type="primary" data-id="btn-add-vendor" @click="handleAdd">
             {{ t('新增') }}
           </el-button>
-          <el-button type="success" :icon="Setting" data-id="btn-init" @click="handleInit">
+          <!-- <el-button type="success" :icon="Setting" data-id="btn-init" @click="handleInit">
             {{ t('初始化默认数据') }}
-          </el-button>
+          </el-button> -->
         </el-form-item>
       </el-form>
     </div>
@@ -114,18 +114,17 @@
         </el-table-column>
         <el-table-column :label="t('操作')" min-width="90" align="center" fixed="right">
           <template #default="{ row }">
-            <el-button type="primary" link :icon="Edit" :data-id="`btn-edit-${row.code}`" @click="handleEdit(row)">
-              {{ t('编辑') }}
+            <el-button type="primary" link :data-id="`btn-edit-${row.code}`" @click="handleEdit(row)">
+              <Icon icon="mdi:note-edit-outline" width="20" height="20" />
             </el-button>
             <el-button
               type="danger"
               link
-              :icon="Delete"
               :disabled="deleteLoading"
               :data-id="`btn-delete-${row.code}`"
               @click="handleDelete(row)"
             >
-              {{ t('删除') }}
+              <Icon icon="mdi:delete" width="20" height="20" />
             </el-button>
           </template>
         </el-table-column>
@@ -242,6 +241,7 @@ import { ref, reactive, onMounted, computed } from 'vue'
 import { ElMessage, ElMessageBox, type FormInstance, type FormRules, type TableInstance } from 'element-plus'
 import { Plus, Edit, Delete, Search, RefreshRight, Setting } from '@element-plus/icons-vue'
 import dayjs from 'dayjs'
+import { Icon } from '@iconify/vue'
 import { useI18n } from 'vue-i18n'
 import {
   listCameraVendors,

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor