index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <template>
  2. <div class="flex h-full w-full flex-col">
  3. <div
  4. class="__hover flex items-center text-sm text-[var(--czr-main-color)]"
  5. @click="toBack"
  6. >
  7. <SvgIcon
  8. name="czr_arrow"
  9. rotate="180"
  10. size="13"
  11. :active="true"
  12. class="mr-1"
  13. />应用中心
  14. </div>
  15. <div class="bm-main-box mt-4">
  16. <div class="mb-4 flex items-center">
  17. <img
  18. src="@/assets/images/app-default-logo.png"
  19. class="mr-[var(--czr-gap)] h-[3.25rem] w-[3.25rem]"
  20. />
  21. <div>
  22. <div class="flex items-center">
  23. <div class="text-[20px] font-bold">应用名称</div>
  24. <div
  25. class="ml-1 rounded-2xl bg-gradient-to-r from-[#C3E3FC] to-[#86C4FF] px-3 py-1 text-xs text-[#0876FF]"
  26. >
  27. 简洁
  28. </div>
  29. <div
  30. class="ml-1 rounded-xs bg-[#5AD8A6] px-2.5 py-1 text-xs text-white"
  31. >
  32. 已发布
  33. </div>
  34. </div>
  35. <div class="mt-2 text-sm text-[#6F7889]">(用户名称)</div>
  36. </div>
  37. <CzrButton
  38. :type="state.tab == 1 ? 'primary' : 'normal'"
  39. title="分析"
  40. class="ml-auto"
  41. @click="state.tab = 1"
  42. />
  43. <CzrButton
  44. :type="state.tab == 2 ? 'primary' : 'normal'"
  45. title="日志"
  46. class="ml-4"
  47. @click="state.tab = 2"
  48. />
  49. </div>
  50. <template v-if="state.tab == 1"></template>
  51. <template v-else-if="state.tab == 2">
  52. <CzrDialogDrag
  53. v-model:show="state.logs.showFilter"
  54. title="高级查询"
  55. :show-submit="false"
  56. :show-close="false"
  57. class="w-[500px]"
  58. :layout="{ mouse: true }"
  59. >
  60. <div>
  61. <CzrForm>
  62. <CzrFormColumn
  63. :span="24"
  64. label="消息ID"
  65. v-model:param="state.logs.texts.p1"
  66. placeholder="输入内容以查询"
  67. />
  68. <CzrFormColumn
  69. :span="24"
  70. label="会话ID"
  71. v-model:param="state.logs.texts.p2"
  72. placeholder="输入内容以查询"
  73. />
  74. <CzrFormColumn
  75. :span="24"
  76. label="用户ID"
  77. v-model:param="state.logs.texts.p3"
  78. placeholder="输入内容以查询"
  79. />
  80. <CzrFormColumn
  81. :span="24"
  82. label="意图识别"
  83. v-model:param="state.logs.texts.p4"
  84. placeholder="输入内容以查询"
  85. />
  86. <CzrFormColumn
  87. :span="24"
  88. label="输入"
  89. v-model:param="state.logs.texts.p5"
  90. placeholder="输入内容以查询"
  91. />
  92. <CzrFormColumn
  93. :span="24"
  94. label="输出"
  95. v-model:param="state.logs.texts.p6"
  96. placeholder="输入内容以查询"
  97. />
  98. <CzrFormColumn
  99. :span="13"
  100. label="输入token"
  101. v-model:param="state.logs.texts.p7"
  102. link="number"
  103. placeholder="token数量"
  104. />
  105. <CzrFormColumn
  106. :span="11"
  107. label="到"
  108. label-width="40px"
  109. v-model:param="state.logs.texts.p8"
  110. link="number"
  111. placeholder="token数量"
  112. />
  113. <CzrFormColumn
  114. :span="13"
  115. label="输出token"
  116. v-model:param="state.logs.texts.p9"
  117. link="number"
  118. placeholder="token数量"
  119. />
  120. <CzrFormColumn
  121. :span="11"
  122. label="到"
  123. label-width="40px"
  124. v-model:param="state.logs.texts.p10"
  125. link="number"
  126. placeholder="token数量"
  127. />
  128. <CzrFormColumn
  129. :span="13"
  130. label="整体耗时(ms)"
  131. v-model:param="state.logs.texts.p11"
  132. link="number"
  133. placeholder="输入耗时"
  134. />
  135. <CzrFormColumn
  136. :span="11"
  137. label="到"
  138. label-width="40px"
  139. v-model:param="state.logs.texts.p12"
  140. link="number"
  141. placeholder="输入耗时"
  142. />
  143. </CzrForm>
  144. </div>
  145. </CzrDialogDrag>
  146. <div class="log flex-1">
  147. <CzrContent
  148. v-model:tableHead="state.logs.query.head"
  149. @handleReset="onReset"
  150. @handleSearch="onSearch"
  151. >
  152. <template #tableTitle>
  153. <div class="flex flex-1 gap-2">
  154. <CzrFormColumn
  155. class="__czr-table-form-column"
  156. width="10%"
  157. label-width="0px"
  158. v-model:param="state.logs.query.form.dateType"
  159. link="select"
  160. :options="[
  161. { label: '近7天', value: 1 },
  162. { label: '近30天', value: 2 },
  163. { label: '近90天', value: 3 },
  164. { label: '近180天', value: 4 },
  165. ]"
  166. placeholder="应用状态"
  167. />
  168. <CzrFormColumn
  169. class="__czr-table-form-column"
  170. width="10%"
  171. label-width="0px"
  172. v-model:param="state.logs.query.form.p1"
  173. link="select"
  174. :options="[]"
  175. placeholder="反馈"
  176. />
  177. <CzrFormColumn
  178. class="__czr-table-form-column"
  179. width="10%"
  180. label-width="0px"
  181. v-model:param="state.logs.query.form.p1"
  182. link="select"
  183. :options="[]"
  184. placeholder="回答效果"
  185. />
  186. <CzrFormColumn
  187. class="__czr-table-form-column"
  188. width="10%"
  189. label-width="0px"
  190. v-model:param="state.logs.query.form.p1"
  191. link="select"
  192. :options="[]"
  193. placeholder="渠道"
  194. />
  195. <CzrFormColumn
  196. class="__czr-table-form-column"
  197. width="24%"
  198. label-width="0px"
  199. v-model:param="state.logs.query.form.p2"
  200. link="datetime"
  201. type="datetimerange"
  202. placeholder="请求时间"
  203. />
  204. <CzrFormColumn
  205. class="__czr-table-form-column"
  206. width="15%"
  207. label-width="0px"
  208. v-model:param="state.logs.texts.keyword"
  209. placeholder="输入关键词以检索"
  210. :prefix-icon="Search"
  211. />
  212. </div>
  213. </template>
  214. <template #buttons>
  215. <div
  216. class="__hover flex h-9 w-9 items-center justify-center rounded-sm bg-[var(--czr-main-color)]"
  217. @click="state.logs.showFilter = true"
  218. >
  219. <SvgIcon name="filter" color="#ffffff" />
  220. </div>
  221. </template>
  222. <template #table>
  223. <CzrTable
  224. v-loading="state.logs.query.loading"
  225. :data="state.logs.query.result.data"
  226. :head="state.logs.query.head"
  227. :total="state.logs.query.result.total"
  228. :page="state.logs.query.page.pageNum"
  229. :pageSize="state.logs.query.page.pageSize"
  230. @handlePage="onPage"
  231. v-model:selected="state.logs.query.selected"
  232. >
  233. </CzrTable>
  234. </template>
  235. </CzrContent>
  236. </div>
  237. </template>
  238. </div>
  239. </div>
  240. </template>
  241. <script setup lang="ts">
  242. import {
  243. computed,
  244. getCurrentInstance,
  245. inject,
  246. onMounted,
  247. reactive,
  248. ref,
  249. watch,
  250. } from 'vue'
  251. import { useRoute, useRouter } from 'vue-router'
  252. import { ElMessage } from 'element-plus'
  253. import lineChart from './line-chart.vue'
  254. import pieChart from './pie-chart.vue'
  255. import { pluginDetail } from '@/api/modules/model'
  256. import { useDictionaryStore } from '@/stores'
  257. import { YMDHms } from '@/utils/czr-util'
  258. import { debounce } from 'lodash'
  259. import { documentGetDocumentsByPage } from '@/api/modules/knowledge/document'
  260. import { Search } from '@element-plus/icons-vue'
  261. import CzrDialogDrag from '@/components/czr-ui/CzrDialogDrag.vue'
  262. import CzrContent from '@/components/czr-ui/CzrContent.vue'
  263. const DictionaryStore = useDictionaryStore()
  264. const route = useRoute()
  265. const router = useRouter()
  266. const emit = defineEmits([])
  267. const props = defineProps({})
  268. const { proxy }: any = getCurrentInstance()
  269. const state: any = reactive({
  270. ID: route.params.id,
  271. tab: 2,
  272. detail: {},
  273. analysis: {},
  274. logs: {
  275. texts: {},
  276. query: {
  277. init: false,
  278. loading: false,
  279. head: [
  280. { value: 'p1', label: '消息ID', show: false },
  281. { value: 'p1', label: '会话ID', show: false },
  282. { value: 'p1', label: '用户ID', show: false },
  283. { value: 'p1', label: '意图识别', show: true },
  284. { value: 'p1', label: '输入', show: true },
  285. { value: 'p1', label: '输出', show: true },
  286. { value: 'p1', label: '输入token', show: true },
  287. { value: 'p1', label: '输出token', show: true },
  288. { value: 'p1', label: '请求时间', show: true },
  289. { value: 'p1', label: '整体耗时', show: true },
  290. { value: 'p1', label: '反馈', show: true },
  291. { value: 'p1', label: '回答效果', show: true },
  292. { value: 'p1', label: '渠道', show: true },
  293. {
  294. value: 'caozuo',
  295. label: '操作',
  296. show: true,
  297. width: 100,
  298. fixed: 'right',
  299. popover: false,
  300. },
  301. ],
  302. page: {
  303. pageNum: 1,
  304. pageSize: 20,
  305. },
  306. form: {},
  307. formReal: {},
  308. result: {
  309. total: 0,
  310. data: [],
  311. },
  312. selected: [],
  313. },
  314. showFilter: false,
  315. },
  316. })
  317. const initDetail = () => {
  318. if (state.ID) {
  319. state.detail = {}
  320. // pluginDetail(state.ID)
  321. // .then(({ data }: any) => {
  322. // state.detail = data
  323. // })
  324. // .catch(() => {})
  325. // .finally(() => {})
  326. initStatistic()
  327. } else {
  328. router.push({ name: 'd446bfb3-4605-477f-a0f4-b7a0a1aa78fe' })
  329. }
  330. }
  331. const toBack = () => {
  332. router.push({
  333. name: 'd446bfb3-4605-477f-a0f4-b7a0a1aa78fe',
  334. })
  335. }
  336. const initStatistic = () => {
  337. // state.statistic.table.query.loading = true
  338. // setTimeout(() => {
  339. // const arr: any = []
  340. // for (let i = 1; i <= 100; i++) {
  341. // arr.push({
  342. // id: i + '',
  343. // p1: '文件' + i + '.md',
  344. // })
  345. // }
  346. // state.statistic.table.query.result.data = arr
  347. // // setTimeout(() => {
  348. // // state.query.selected = [arr[1], arr[5]]
  349. // // })
  350. // state.statistic.table.query.loading = false
  351. // }, 1000)
  352. }
  353. const setTexts = debounce((obj) => {
  354. Object.entries(obj).forEach(([k, v]) => {
  355. state.logs.query.form[k] = v
  356. })
  357. }, 1000)
  358. watch(
  359. () => state.logs.texts,
  360. (n) => {
  361. setTexts(n)
  362. },
  363. { deep: true },
  364. )
  365. watch(
  366. () => state.logs.query.form,
  367. (n) => {
  368. if (state.logs.query.init) {
  369. onSearch()
  370. }
  371. },
  372. { deep: true },
  373. )
  374. const onPage = (pageNum, pageSize) => {
  375. setTimeout(() => {
  376. state.logs.query.init = true
  377. }, 100)
  378. state.logs.query.page = {
  379. pageNum: pageNum,
  380. pageSize: pageSize,
  381. }
  382. const params = {
  383. page: state.logs.query.page.pageNum,
  384. size: state.logs.query.page.pageSize,
  385. }
  386. // 添加表单参数
  387. for (const [k, v] of Object.entries(state.logs.query.formReal)) {
  388. if (proxy.$czrUtil.isValue(v)) {
  389. params[k] = v
  390. }
  391. }
  392. console.log(params)
  393. // state.logs.query.loading = true
  394. // documentGetDocumentsByPage(params)
  395. // .then(({ data }: any) => {
  396. // state.logs.query.result.total = data.totalElements
  397. // state.logs.query.result.data = data.content
  398. // })
  399. // .catch(() => {})
  400. // .finally(() => {
  401. // state.logs.query.loading = false
  402. // })
  403. }
  404. const onSearch = () => {
  405. state.logs.query.selected = []
  406. state.logs.query.formReal = JSON.parse(JSON.stringify(state.logs.query.form))
  407. onPage(1, state.logs.query.page.pageSize)
  408. }
  409. const onReset = () => {
  410. state.logs.query.page = {
  411. pageNum: 1,
  412. pageSize: 20,
  413. }
  414. state.logs.query.form = {
  415. dateType: 1,
  416. }
  417. state.logs.texts = {}
  418. state.logs.query.init = false
  419. onSearch()
  420. }
  421. onMounted(() => {
  422. initDictionary()
  423. initDetail()
  424. onReset()
  425. })
  426. const initDictionary = () => {
  427. // DictionaryStore.initModelProvides()
  428. // DictionaryStore.initModelTypes()
  429. }
  430. </script>
  431. <style lang="scss" scoped>
  432. :deep(.log) {
  433. .cc-bottom {
  434. padding: 0;
  435. }
  436. }
  437. </style>