data-source-config.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <template>
  2. <div class="data-source-config admin-page">
  3. <el-card>
  4. <div slot="header" class="admin-page-header">
  5. <span class="admin-page-title">健康数据源配置</span>
  6. <el-input v-model="keyword" placeholder="搜索数据源..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
  7. <div class="admin-page-actions">
  8. <el-button type="primary" size="small" @click="handleCreate">+ 添加数据源</el-button>
  9. </div>
  10. </div>
  11. <div class="table-scroll-wrap-sm">
  12. <div style="overflow:auto;max-height:calc(100vh - 300px);">
  13. <el-table style="max-height:calc(100vh - 300px);" :data="records" stripe v-loading="loading">
  14. <el-table-column prop="id" label="ID" width="60"></el-table-column>
  15. <el-table-column prop="memberId" label="成员ID" width="80"></el-table-column>
  16. <el-table-column prop="sourceType" label="类型" width="100">
  17. <template slot-scope="scope">
  18. <el-tag size="mini">{{ scope.row.sourceType }}</el-tag>
  19. </template>
  20. </el-table-column>
  21. <el-table-column prop="dimensionCodes" label="维度" width="150" show-overflow-tooltip></el-table-column>
  22. <el-table-column prop="confidence" label="置信度" width="80">
  23. <template slot-scope="scope">{{ scope.row.confidence }}</template>
  24. </el-table-column>
  25. <el-table-column prop="fileUrl" label="文件URL" min-width="200" show-overflow-tooltip>
  26. <template slot-scope="scope">
  27. <a v-if="scope.row.fileUrl" :href="scope.row.fileUrl" target="_blank" style="color:#409EFF;font-size:12px;">查看文件</a>
  28. <span v-else style="color:#999">-</span>
  29. </template>
  30. </el-table-column>
  31. <el-table-column prop="createdAt" label="创建时间" width="160">
  32. <template slot-scope="scope">{{ formatDate(scope.row.createdAt) }}</template>
  33. </el-table-column>
  34. <el-table-column label="操作" width="200" fixed="right">
  35. <template slot-scope="{ row }">
  36. <el-button size="mini" type="primary" @click="handleEdit(row)">编辑</el-button>
  37. <el-dropdown trigger="hover" @command="(cmd) => handleActionCmd(row, cmd)">
  38. <el-button size="mini">
  39. 更多<i class="el-icon-arrow-down el-icon--right"></i>
  40. </el-button>
  41. <el-dropdown-menu slot="dropdown">
  42. <el-dropdown-item command="delete" icon="el-icon-delete">删除</el-dropdown-item>
  43. </el-dropdown-menu>
  44. </el-dropdown>
  45. </template>
  46. </el-table-column>
  47. </el-table></div>
  48. </div>
  49. <el-pagination
  50. v-if="total > 0"
  51. class="pagination-wrap"
  52. :total="total"
  53. style="margin-top:16px;text-align:right"
  54. :total="total"
  55. :page.sync="page"
  56. :limit.sync="size"
  57. @current-change="fetchRecords"
  58. layout="total, prev, pager, next"
  59. />
  60. </el-card>
  61. <el-dialog :visible.sync="dialogVisible" :title="isEdit ? '编辑数据源' : '添加数据源'" width="550px">
  62. <el-form :model="form" label-width="100px">
  63. <el-form-item label="成员ID" required>
  64. <el-input-number v-model="form.memberId" :min="1" style="width:100%"/>
  65. </el-form-item>
  66. <el-form-item label="来源类型" required>
  67. <el-select v-model="form.sourceType" placeholder="选择类型" style="width:100%">
  68. <el-option label="REPORT" value="REPORT"></el-option>
  69. <el-option label="PHOTO" value="PHOTO"></el-option>
  70. <el-option label="VOICE" value="VOICE"></el-option>
  71. <el-option label="MANUAL" value="MANUAL"></el-option>
  72. </el-select>
  73. </el-form-item>
  74. <el-form-item label="维度编码">
  75. <el-input v-model="form.dimensionCodes" placeholder="如: growth,sleep,vision"/>
  76. </el-form-item>
  77. <el-form-item label="置信度">
  78. <el-input-number v-model="form.confidence" :min="0" :max="1" :precision="2" style="width:100%"/>
  79. </el-form-item>
  80. <el-form-item label="解析结果">
  81. <el-input type="textarea" v-model="form.parsedResult" :rows="3" placeholder="JSON格式"/>
  82. </el-form-item>
  83. <el-form-item label="文件URL">
  84. <el-input v-model="form.fileUrl" placeholder="https://..."/>
  85. </el-form-item>
  86. </el-form>
  87. <div slot="footer">
  88. <el-button @click="dialogVisible = false">取消</el-button>
  89. <el-button type="primary" @click="handleSubmit" :loading="submitting">保存</el-button>
  90. </div>
  91. </el-dialog>
  92. </div>
  93. </template>
  94. <script>
  95. export default {
  96. name: 'DataSourceConfig',
  97. data() {
  98. return {
  99. loading: false,
  100. submitting: false,
  101. records: [],
  102. total: 0,
  103. page: 1,
  104. size: 20,
  105. dialogVisible: false,
  106. isEdit: false,
  107. form: this.emptyForm(),
  108. keyword: ''
  109. }
  110. },
  111. mounted() {
  112. this.fetchRecords()
  113. },
  114. methods: {
  115. handleSearch() {
  116. this.page = 1
  117. this.fetchRecords()
  118. },
  119. emptyForm() {
  120. return {
  121. id: null,
  122. memberId: null,
  123. sourceType: 'MANUAL',
  124. dimensionCodes: '',
  125. parsedResult: '',
  126. fileUrl: '',
  127. confidence: null
  128. }
  129. },
  130. formatDate(d) {
  131. if (!d) return '-'
  132. return new Date(d).toLocaleString()
  133. },
  134. fetchRecords() {
  135. this.loading = true
  136. this.$axios.post('/api/admin/dimension/data-source/list', null, { params: { page: this.page, size: this.size, keyword: this.keyword || undefined } })
  137. .then(res => {
  138. if (res.data.code === 200) {
  139. this.records = res.data.data.records || []
  140. this.total = res.data.data.total || 0
  141. }
  142. }).catch(() => {}).finally(() => { this.loading = false })
  143. },
  144. handleCreate() {
  145. this.form = this.emptyForm()
  146. this.isEdit = false
  147. this.dialogVisible = true
  148. },
  149. handleEdit(row) {
  150. this.form = { ...row }
  151. this.isEdit = true
  152. this.dialogVisible = true
  153. },
  154. handleSubmit() {
  155. this.submitting = true
  156. this.$axios.post('/api/admin/dimension/data-source/save', this.form).then(res => {
  157. if (res.data.code === 200) {
  158. this.dialogVisible = false
  159. this.fetchRecords()
  160. this.$message.success('保存成功')
  161. } else {
  162. this.$message.error(res.data.message || '保存失败')
  163. }
  164. }).catch(() => { this.$message.error('保存失败') }).finally(() => { this.submitting = false })
  165. },
  166. handleDelete(row) {
  167. this.$confirm('确认删除此数据源?', '提示', { type: 'warning' }).then(() => {
  168. this.$axios.post('/api/admin/dimension/data-source/delete', row.id).then(res => {
  169. if (res.data.code === 200) {
  170. this.fetchRecords()
  171. this.$message.success('删除成功')
  172. } else {
  173. this.$message.error(res.data.message || '删除失败')
  174. }
  175. })
  176. }).catch(() => {})
  177. },
  178. handleActionCmd(row, cmd) {
  179. switch (cmd) {
  180. case 'delete':
  181. this.handleDelete(row)
  182. break
  183. }
  184. }
  185. }
  186. }
  187. </script>