xiongzhu 2 ani în urmă
părinte
comite
779eccdf8a
3 a modificat fișierele cu 191 adăugiri și 0 ștergeri
  1. 1 0
      package.json
  2. 152 0
      src/views/PromptView.vue
  3. 38 0
      yarn.lock

+ 1 - 0
package.json

@@ -20,6 +20,7 @@
     "resolve-url": "^0.2.1",
     "socket.io-client": "^4.7.2",
     "vue": "^3.2.47",
+    "vue-json-viewer": "3",
     "vue-router": "^4.1.6"
   },
   "devDependencies": {

+ 152 - 0
src/views/PromptView.vue

@@ -12,10 +12,35 @@
                 <ElInput v-model="item.template" type="textarea" :autosize="{ min: 20 }"></ElInput>
                 <div class="mt-4">
                     <ElButton @click="save(i)" :loading="loading" type="primary">保存</ElButton>
+                    <ElButton @click="test(i)" :loading="loading">测试</ElButton>
                     <ElButton @click="restore(i)" :disabled="loading">恢复默认</ElButton>
                 </div>
             </el-tab-pane>
         </el-tabs>
+        <br />
+        <br />
+        <div class="ml-32 flex text-sm text-neutral-600 dark:text-neutral-400">
+            <div class="">
+                可用变量:<br />
+                days: 运行天数<br />
+                charactors: 角色列表<br />
+                total: 总人数<br />
+                alive: 存活人数<br />
+                dead: 死亡人数<br />
+                minHp: 最低生命值<br />
+                maxHp: 最高生命值<br />
+                avgHp: 平均生命值<br /><br />
+                语法示例:
+                <code class="bg-neutral-300 dark:bg-neutral-700 px-2 py-1 rounded-sm"
+                    >&lt;% return alive > 5 ? '加入战斗情节' : '' %&gt;</code
+                ><br />
+                <br />
+            </div>
+            <div class="pl-8">
+                测试变量:<br />
+                <json-viewer :value="testVarsFinal" :expand-depth="1" copyable boxed sort></json-viewer>
+            </div>
+        </div>
     </div>
 </template>
 <script setup>
@@ -24,6 +49,8 @@ import { onMounted, ref, watch } from 'vue'
 import { ElMessage } from 'element-plus'
 import { Plus, Trash } from '@vicons/tabler'
 import { ElMessageBox } from 'element-plus'
+import JsonViewer from 'vue-json-viewer'
+import {} from '@vicons/tabler'
 const activeName = ref('')
 const prompts = ref([])
 const types = ref([])
@@ -61,6 +88,9 @@ onMounted(() => {
 })
 const loading = ref(false)
 async function save(i) {
+    if (!test(i, false)) {
+        return
+    }
     try {
         loading.value = true
         await http.put('/prompt', prompts.value[i])
@@ -102,4 +132,126 @@ async function delType() {
         ElMessage.error(error.message)
     }
 }
+const testVars = {
+    days: 4,
+    charactors: [
+        {
+            name: '约翰',
+            gender: '男',
+            age: '35',
+            occupation: '侦探',
+            personality: '1号',
+            background: '前警探,以侦破神秘犯罪而闻名',
+            hp: 0,
+            joinAt: '2023-10-10T16:00:00.000Z',
+            survival: 0,
+            dead: true,
+            avatar: 'https://nebuai.oss-cn-hangzhou.aliyuncs.com/image/20231012/7laitqdb.png',
+            deadAt: '2023-10-15T16:00:00.000Z'
+        },
+        {
+            name: '艾米丽',
+            gender: '女',
+            age: '28',
+            occupation: '记者',
+            personality: '好奇心重',
+            background: '调查性记者,专注于揭露黑暗的秘密。',
+            hp: 0,
+            joinAt: '2023-10-10T16:00:00.000Z',
+            survival: 0,
+            dead: true,
+            avatar: 'https://nebuai.oss-cn-hangzhou.aliyuncs.com/image/20231012/dgg7bxc6.png',
+            deadAt: '2023-10-14T16:00:00.000Z'
+        },
+        {
+            name: '威廉',
+            gender: '女',
+            age: '45',
+            occupation: '律师',
+            personality: '聪明的',
+            background: '非常成功的辩护律师,以为自己的客户获得无罪声誉而闻名。',
+            hp: 10,
+            joinAt: '2023-10-10T16:00:00.000Z',
+            survival: 0,
+            dead: false,
+            avatar: 'https://nebuai.oss-cn-hangzhou.aliyuncs.com/image/20231012/slxskike.png'
+        },
+        {
+            name: '伊莎贝拉',
+            gender: '女',
+            age: '30',
+            occupation: '法医',
+            personality: '善于分析',
+            background: '具有DNA分析专业知识的法医科学家,解决了许多冷案。',
+            hp: 0,
+            joinAt: '2023-10-10T16:00:00.000Z',
+            survival: 0,
+            dead: true,
+            avatar: 'https://nebuai.oss-cn-hangzhou.aliyuncs.com/image/20231012/oqqliuus.png',
+            deadAt: '2023-10-14T16:00:00.000Z'
+        },
+        {
+            name: '亚历山大',
+            gender: '男',
+            age: '40',
+            occupation: '心理学家',
+            personality: '富有洞察力的',
+            background: '著名心理学家,专长是犯罪心理分析。',
+            hp: 10,
+            joinAt: '2023-10-10T16:00:00.000Z',
+            survival: 0,
+            dead: false,
+            avatar: 'https://nebuai.oss-cn-hangzhou.aliyuncs.com/image/20231012/hqflwm6u.png'
+        }
+    ]
+}
+function evalPrompt(vars, template) {
+    vars.total = vars.charactors.length
+    vars.alive = vars.charactors.filter((i) => !i.dead).length
+    vars.dead = vars.charactors.filter((i) => i.dead).length
+    const hps = vars.charactors.filter((i) => i.hp > 0).map((i) => i.hp)
+    vars.minHp = hps.length > 0 ? Math.min(...hps) : 0
+    vars.maxHp = hps.length > 0 ? Math.max(...hps) : 0
+    vars.avgHp = hps.length > 0 ? hps.reduce((a, b) => a + b) / hps.length : 0
+    const reg = /<%([^%]*(?:%(?!>)[^%]*)*)%>/
+    while (reg.test(template)) {
+        template = template.replace(reg, function (match, $1) {
+            var func = new Function('days', 'charactors', 'total', 'alive', 'dead', 'minHp', 'maxHp', 'avgHp', $1)
+            return func(
+                vars.days,
+                vars.charactors,
+                vars.total,
+                vars.alive,
+                vars.dead,
+                vars.minHp,
+                vars.maxHp,
+                vars.avgHp
+            )
+        })
+    }
+    return {
+        template,
+        vars
+    }
+}
+const testVarsFinal = evalPrompt(testVars, '<% return alive > 5 ? "加入战斗情节" : "" %>').vars
+function test(i, showResult = true) {
+    try {
+        const result = evalPrompt(testVars, prompts.value[i].template)
+        if (showResult) {
+            ElMessageBox.alert(`<p class="whitespace-pre-wrap">${result.template}</p>`, `测试结果`, {
+                dangerouslyUseHTMLString: true,
+                customStyle: { maxWidth: '800px' }
+            })
+        }
+        return true
+    } catch (error) {
+        console.log(error)
+        ElMessageBox.alert(`<p class="text-red-500">${error.message}</p>`, '测试失败', {
+            type: 'error',
+            dangerouslyUseHTMLString: true
+        })
+    }
+    return false
+}
 </script>

+ 38 - 0
yarn.lock

@@ -640,6 +640,15 @@ chokidar@^3.5.3:
   optionalDependencies:
     fsevents "~2.3.2"
 
+clipboard@^2.0.4:
+  version "2.0.11"
+  resolved "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz#62180360b97dd668b6b3a84ec226975762a70be5"
+  integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==
+  dependencies:
+    good-listener "^1.2.2"
+    select "^1.1.2"
+    tiny-emitter "^2.0.0"
+
 color-convert@^2.0.1:
   version "2.0.1"
   resolved "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
@@ -729,6 +738,11 @@ delayed-stream@~1.0.0:
   resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
   integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
 
+delegate@^3.1.2:
+  version "3.2.0"
+  resolved "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
+  integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
+
 didyoumean@^1.2.2:
   version "1.2.2"
   resolved "https://registry.npmmirror.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
@@ -1126,6 +1140,13 @@ globals@^13.19.0:
   dependencies:
     type-fest "^0.20.2"
 
+good-listener@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
+  integrity sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==
+  dependencies:
+    delegate "^3.1.2"
+
 graceful-fs@^4.1.2:
   version "4.2.11"
   resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
@@ -1804,6 +1825,11 @@ scule@^1.0.0:
   resolved "https://registry.npmmirror.com/scule/-/scule-1.0.0.tgz#895e6f4ba887e78d8b9b4111e23ae84fef82376d"
   integrity sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==
 
+select@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.npmmirror.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
+  integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==
+
 semver@^5.6.0:
   version "5.7.1"
   resolved "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
@@ -1963,6 +1989,11 @@ thenify-all@^1.0.0:
   dependencies:
     any-promise "^1.0.0"
 
+tiny-emitter@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
+  integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
+
 to-regex-range@^5.0.1:
   version "5.0.1"
   resolved "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
@@ -2102,6 +2133,13 @@ vue-eslint-parser@^9.0.1:
     lodash "^4.17.21"
     semver "^7.3.6"
 
+vue-json-viewer@3:
+  version "3.0.4"
+  resolved "https://registry.npmmirror.com/vue-json-viewer/-/vue-json-viewer-3.0.4.tgz#c1d65515e57d4036defbbc18fa942d7fd5fb9a8b"
+  integrity sha512-pnC080rTub6YjccthVSNQod2z9Sl5IUUq46srXtn6rxwhW8QM4rlYn+CTSLFKXWfw+N3xv77Cioxw7B4XUKIbQ==
+  dependencies:
+    clipboard "^2.0.4"
+
 vue-router@^4.1.6:
   version "4.1.6"
   resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz#b70303737e12b4814578d21d68d21618469375a1"