detail.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. <template>
  2. <CzrDialog
  3. :show="show"
  4. :title="titleCpt"
  5. @onClose="$emit('update:show', false)"
  6. @onSubmit="onSubmit"
  7. width="62.5rem"
  8. height="auto"
  9. max-height="90%"
  10. :loading="state.loading"
  11. >
  12. <div class="bm-form">
  13. <CzrForm ref="ref_form" :form-view="isViewCpt" layout="y">
  14. <CzrFormColumn
  15. required
  16. :span="24"
  17. label="应用名称"
  18. v-model:param="state.form.name"
  19. />
  20. <CzrFormColumn
  21. required
  22. :span="24"
  23. v-model:param="state.form.type"
  24. link="radio"
  25. :options="DictionaryStore.appTypes"
  26. :disabled="transfer.mode !== 'add'"
  27. >
  28. <template #label>
  29. 应用类型
  30. <el-tooltip
  31. content="简介:选择模型即可使用<br/>高级:需配置应用工作流才可使用"
  32. :raw-content="true"
  33. placement="top"
  34. >
  35. <SvgIcon name="czr_tip" size="14" class="ml-2" />
  36. </el-tooltip>
  37. </template>
  38. </CzrFormColumn>
  39. <CzrFormColumn
  40. :span="24"
  41. label="应用介绍"
  42. v-model:param="state.form.description"
  43. type="textarea"
  44. :rows="4"
  45. />
  46. <CzrFormColumn
  47. required
  48. :span="24"
  49. label="图标"
  50. v-model:param="state.icon"
  51. link="upload"
  52. type="img"
  53. uploadLayout="card"
  54. :limit="1"
  55. :delRule="(file) => true"
  56. />
  57. <template v-if="state.form.status == 1">
  58. <CzrFormColumn
  59. :span="24"
  60. label="公开访问URL"
  61. v-model:param="state.form.url1"
  62. :readonly="true"
  63. >
  64. <template #label>
  65. 公开访问URL
  66. <div class="ml-auto" @click.capture.stop="onSwitchUrl">
  67. <a-switch v-model:checked="state.form.enabled1" size="small" />
  68. </div>
  69. </template>
  70. <template #suffix>
  71. <CopyDocument
  72. class="w-4 cursor-pointer"
  73. @click="onCopy(state.form.url1)"
  74. />
  75. </template>
  76. </CzrFormColumn>
  77. <CzrFormColumn
  78. :span="24"
  79. label="后端访问API"
  80. v-model:param="state.form.url2"
  81. :readonly="true"
  82. >
  83. <template #label>
  84. 公开访问URL
  85. <div class="ml-auto" @click.capture.stop="onSwitchApi">
  86. <a-switch v-model:checked="state.form.enabled2" size="small" />
  87. </div>
  88. </template>
  89. <template #suffix>
  90. <CopyDocument
  91. class="w-4 cursor-pointer"
  92. @click="onCopy(state.form.url2)"
  93. />
  94. </template>
  95. </CzrFormColumn>
  96. <div class="__czr-title_1 mb-2">
  97. API密钥
  98. <CzrButton title="新增" type="add" class="ml-auto" @click="onAdd" />
  99. </div>
  100. <div class="max-h-[300px] w-full">
  101. <CzrTable
  102. v-loading="state.query.loading"
  103. :data="state.query.result.data"
  104. :head="state.query.head"
  105. :no-foot="true"
  106. :full="true"
  107. >
  108. <template #caozuo-column-value="{ scope }">
  109. <div class="__czr-table-operations">
  110. <CzrButton
  111. type="table"
  112. title="复制"
  113. @click="onCopy(scope.row.key)"
  114. />
  115. <CzrButton
  116. type="table"
  117. title="编辑"
  118. @click="onEdit(scope.row)"
  119. />
  120. <CzrButton type="table-del" @click="onDel(scope.row)" />
  121. </div>
  122. </template>
  123. </CzrTable>
  124. </div>
  125. </template>
  126. </CzrForm>
  127. </div>
  128. <apiKey
  129. v-model:show="state.apiKey.show"
  130. :transfer="state.apiKey.transfer"
  131. @refresh="onApi"
  132. />
  133. </CzrDialog>
  134. </template>
  135. <script setup lang="ts">
  136. import {
  137. computed,
  138. getCurrentInstance,
  139. nextTick,
  140. reactive,
  141. ref,
  142. watch,
  143. } from 'vue'
  144. import { ElMessage, ElMessageBox } from 'element-plus'
  145. import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
  146. import { useRouter } from 'vue-router'
  147. import { CopyDocument } from '@element-plus/icons-vue'
  148. import { copy } from '@/utils/czr-util'
  149. import apiKey from './api-key.vue'
  150. import { appAdd, appCopy, appDetail, appEdit } from '@/api/modules/app'
  151. const router = useRouter()
  152. const AppStore = useAppStore()
  153. const DictionaryStore = useDictionaryStore()
  154. const DialogStore = useDialogStore()
  155. const emit = defineEmits(['update:show', 'refresh'])
  156. const { proxy } = getCurrentInstance()
  157. const props = defineProps({
  158. show: { default: false },
  159. transfer: <any>{},
  160. })
  161. const state: any = reactive({
  162. loading: false,
  163. form: {},
  164. icon: [],
  165. query: {
  166. loading: false,
  167. head: [
  168. { value: 'p1', label: '密钥', show: true },
  169. {
  170. value: 'createTime',
  171. label: '创建时间',
  172. show: true,
  173. width: 180,
  174. datetime: true,
  175. },
  176. {
  177. value: 'updateTime',
  178. label: '最后使用',
  179. show: true,
  180. width: 180,
  181. },
  182. {
  183. value: 'p1',
  184. label: '备注',
  185. show: true,
  186. },
  187. {
  188. value: 'caozuo',
  189. label: '操作',
  190. show: true,
  191. width: 200,
  192. fixed: 'right',
  193. popover: false,
  194. },
  195. ],
  196. result: {
  197. data: [],
  198. },
  199. },
  200. apiKey: {
  201. show: false,
  202. transfer: {},
  203. },
  204. })
  205. const ref_form = ref()
  206. const titleCpt = computed(() => {
  207. let t = '应用'
  208. switch (props.transfer.mode) {
  209. case 'add':
  210. t = '新增' + t
  211. break
  212. case 'copy':
  213. t = '创建' + t + '副本'
  214. break
  215. case 'edit':
  216. t = '编辑' + t
  217. break
  218. case 'view':
  219. t = '查看' + t
  220. break
  221. }
  222. return t
  223. })
  224. const isViewCpt = computed(() => props.transfer?.mode === 'view')
  225. watch(
  226. () => props.show,
  227. (n) => {
  228. if (n) {
  229. initDictionary()
  230. state.form = {}
  231. state.icon = []
  232. if (props.transfer.mode !== 'add') {
  233. initData()
  234. }
  235. onApi()
  236. nextTick(() => {
  237. ref_form.value.reset()
  238. })
  239. }
  240. },
  241. )
  242. const initData = () => {
  243. state.loading = true
  244. appDetail(props.transfer.id)
  245. .then(({ data }: any) => {
  246. if (data.icon) {
  247. state.icon = [{ url: data.icon, name: data.icon }]
  248. }
  249. if (props.transfer.mode === 'copy') {
  250. state.form = {
  251. name: data.name,
  252. type: data.type,
  253. description: data.description,
  254. }
  255. } else {
  256. state.form = data
  257. }
  258. })
  259. .catch(() => {})
  260. .finally(() => {
  261. state.loading = false
  262. })
  263. }
  264. const onSubmit = () => {
  265. ref_form.value
  266. .submit()
  267. .then(() => {
  268. DialogStore.confirm({
  269. content: `请确认是否提交?`,
  270. onSubmit: () => {
  271. state.loading = true
  272. state.form.icon = state.icon[0].url
  273. if (props.transfer.mode === 'add') {
  274. appAdd(state.form)
  275. .then(() => {
  276. ElMessage.success(`${titleCpt.value}成功!`)
  277. emit('update:show', false)
  278. emit('refresh')
  279. })
  280. .catch(() => {})
  281. .finally(() => {
  282. state.loading = false
  283. })
  284. } else if (props.transfer.mode === 'edit') {
  285. appEdit(state.form)
  286. .then(() => {
  287. ElMessage.success(`${titleCpt.value}成功!`)
  288. emit('update:show', false)
  289. emit('refresh')
  290. })
  291. .catch(() => {})
  292. .finally(() => {
  293. state.loading = false
  294. })
  295. } else if (props.transfer.mode === 'copy') {
  296. appCopy(props.transfer.id, state.form)
  297. .then(() => {
  298. ElMessage.success(`${titleCpt.value}成功!`)
  299. emit('update:show', false)
  300. emit('refresh')
  301. })
  302. .catch(() => {})
  303. .finally(() => {
  304. state.loading = false
  305. })
  306. }
  307. },
  308. })
  309. })
  310. .catch((e) => {
  311. ElMessage({
  312. message: e[0].message,
  313. grouping: true,
  314. type: 'warning',
  315. })
  316. })
  317. }
  318. const onCopy = (str) => {
  319. copy(str)
  320. ElMessage.success('复制成功!')
  321. }
  322. const onSwitchUrl = () => {
  323. if (state.form.enabled1) {
  324. DialogStore.confirm({
  325. title: '停用确认',
  326. content: `请确认是否停用公开访问URL?`,
  327. onSubmit: () => {
  328. ElMessage.success('停用成功!')
  329. },
  330. onCancel: () => {},
  331. })
  332. } else {
  333. ElMessage.success('启用成功!')
  334. }
  335. }
  336. const onSwitchApi = () => {
  337. if (state.form.enabled2) {
  338. DialogStore.confirm({
  339. title: '停用确认',
  340. content: `请确认是否停用后端访问API?`,
  341. onSubmit: () => {
  342. ElMessage.success('停用成功!')
  343. },
  344. onCancel: () => {},
  345. })
  346. } else {
  347. ElMessage.success('启用成功!')
  348. }
  349. }
  350. const onAdd = () => {
  351. state.apiKey.transfer = {
  352. mode: 'add',
  353. }
  354. state.apiKey.show = true
  355. }
  356. const onEdit = (row) => {
  357. state.apiKey.transfer = {
  358. mode: 'edit',
  359. id: row.id,
  360. }
  361. state.apiKey.show = true
  362. }
  363. const onDel = (row) => {
  364. DialogStore.confirm({
  365. title: '删除确认',
  366. content: `请确认是否删除密钥?`,
  367. onSubmit: () => {
  368. ElMessage.success('删除成功!')
  369. },
  370. onCancel: () => {},
  371. })
  372. }
  373. const onApi = () => {
  374. state.query.result.data = [{}, {}, {}]
  375. }
  376. const initDictionary = () => {}
  377. </script>
  378. <style lang="scss" scoped></style>