feat(web): load real data in dashboard and list pages

This commit is contained in:
2026-07-07 15:34:35 +08:00
parent d0e9f5fb42
commit 9a1565dd8d
6 changed files with 207 additions and 17 deletions

View File

@@ -11,12 +11,25 @@
<el-form-item label="渠道"> <el-form-item label="渠道">
<el-input v-model="form.channelType" placeholder="wecom" /> <el-input v-model="form.channelType" placeholder="wecom" />
</el-form-item> </el-form-item>
<el-form-item label="所属主体">
<el-select v-model="form.subjectId" placeholder="选择主体">
<el-option
v-for="s in subjects"
:key="s.id"
:label="s.subjectName"
:value="s.id"
/>
</el-select>
</el-form-item>
<el-form-item label="账号ID"> <el-form-item label="账号ID">
<el-input v-model="form.accountId" placeholder="账号唯一标识" /> <el-input v-model="form.accountId" placeholder="账号唯一标识" />
</el-form-item> </el-form-item>
<el-form-item label="名称"> <el-form-item label="名称">
<el-input v-model="form.accountName" placeholder="名称" /> <el-input v-model="form.accountName" placeholder="名称" />
</el-form-item> </el-form-item>
<el-form-item label="会话存档">
<el-switch v-model="form.sessionArchiveEnabled" />
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleCreate">创建</el-button> <el-button type="primary" @click="handleCreate">创建</el-button>
</el-form-item> </el-form-item>
@@ -35,18 +48,39 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue' import { onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { createChannelAccount } from '@/api/channel' import { createChannelAccount, listChannelAccounts, listChannelSubjects } from '@/api/channel'
const form = reactive({ const form = reactive({
accountType: 1, accountType: 1,
channelType: 'wecom', channelType: 'wecom',
subjectId: undefined as number | undefined,
accountId: '', accountId: '',
accountName: '', accountName: '',
sessionArchiveEnabled: false,
}) })
const accounts = ref<any[]>([]) const accounts = ref<any[]>([])
const subjects = ref<any[]>([])
async function loadAccounts() {
try {
const res: any = await listChannelAccounts()
accounts.value = res.data || []
} catch (e: any) {
ElMessage.error(e.message)
}
}
async function loadSubjects() {
try {
const res: any = await listChannelSubjects()
subjects.value = res.data || []
} catch (e: any) {
ElMessage.error(e.message)
}
}
async function handleCreate() { async function handleCreate() {
try { try {
@@ -57,4 +91,9 @@ async function handleCreate() {
ElMessage.error(e.message) ElMessage.error(e.message)
} }
} }
onMounted(() => {
loadAccounts()
loadSubjects()
})
</script> </script>

View File

@@ -14,6 +14,15 @@
<el-form-item label="主体名称"> <el-form-item label="主体名称">
<el-input v-model="form.subjectName" placeholder="主体名称" /> <el-input v-model="form.subjectName" placeholder="主体名称" />
</el-form-item> </el-form-item>
<el-form-item label="CorpID">
<el-input v-model="form.corpId" placeholder="CorpID" />
</el-form-item>
<el-form-item label="AgentID">
<el-input v-model="form.agentId" placeholder="AgentID" />
</el-form-item>
<el-form-item label="AgentSecret">
<el-input v-model="form.agentSecret" placeholder="AgentSecret" />
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleCreate">创建</el-button> <el-button type="primary" @click="handleCreate">创建</el-button>
</el-form-item> </el-form-item>
@@ -31,19 +40,30 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue' import { onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { createChannelSubject } from '@/api/channel' import { createChannelSubject, listChannelSubjects } from '@/api/channel'
const form = reactive({ const form = reactive({
channelType: 'wecom', channelType: 'wecom',
subjectCode: '', subjectCode: '',
subjectName: '', subjectName: '',
corpId: '', corpId: '',
agentId: '',
agentSecret: '',
}) })
const subjects = ref<any[]>([]) const subjects = ref<any[]>([])
async function loadSubjects() {
try {
const res: any = await listChannelSubjects()
subjects.value = res.data || []
} catch (e: any) {
ElMessage.error(e.message)
}
}
async function handleCreate() { async function handleCreate() {
try { try {
const res: any = await createChannelSubject(form) const res: any = await createChannelSubject(form)
@@ -53,4 +73,6 @@ async function handleCreate() {
ElMessage.error(e.message) ElMessage.error(e.message)
} }
} }
onMounted(loadSubjects)
</script> </script>

View File

@@ -16,6 +16,16 @@
<el-form-item label="名称"> <el-form-item label="名称">
<el-input v-model="form.conversationName" placeholder="群名称" /> <el-input v-model="form.conversationName" placeholder="群名称" />
</el-form-item> </el-form-item>
<el-form-item label="负责人">
<el-select v-model="form.ownerAccountId" placeholder="选择负责人账号">
<el-option
v-for="a in accounts"
:key="a.id"
:label="a.accountName"
:value="a.id"
/>
</el-select>
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleCreate">创建</el-button> <el-button type="primary" @click="handleCreate">创建</el-button>
</el-form-item> </el-form-item>
@@ -28,23 +38,86 @@
<el-table-column prop="channelConversationId" label="渠道会话ID" /> <el-table-column prop="channelConversationId" label="渠道会话ID" />
<el-table-column prop="conversationName" label="名称" /> <el-table-column prop="conversationName" label="名称" />
<el-table-column prop="status" label="状态" /> <el-table-column prop="status" label="状态" />
<el-table-column label="操作" width="120">
<template #default="{ row }">
<el-button link type="primary" @click="openBind(row)">绑定账号</el-button>
</template>
</el-table-column>
</el-table> </el-table>
<el-dialog v-model="bindVisible" title="绑定账号" width="500px">
<el-form :model="bindForm" label-width="100px">
<el-form-item label="账号">
<el-select v-model="bindForm.accountId" placeholder="选择账号">
<el-option
v-for="a in accounts"
:key="a.id"
:label="a.accountName"
:value="a.id"
/>
</el-select>
</el-form-item>
<el-form-item label="绑定类型">
<el-select v-model="bindForm.bindingType" placeholder="选择绑定类型">
<el-option label="发送主号" :value="1" />
<el-option label="发送备用号" :value="2" />
<el-option label="接收主号" :value="3" />
<el-option label="接收备用号" :value="4" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="bindVisible = false">取消</el-button>
<el-button type="primary" @click="handleBind">确认</el-button>
</template>
</el-dialog>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue' import { onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { createConversation } from '@/api/channel' import {
bindConversationAccount,
createConversation,
listChannelAccounts,
listConversations,
} from '@/api/channel'
const form = reactive({ const form = reactive({
conversationType: 2, conversationType: 2,
channelType: 'wecom', channelType: 'wecom',
channelConversationId: '', channelConversationId: '',
conversationName: '', conversationName: '',
ownerAccountId: undefined as number | undefined,
}) })
const conversations = ref<any[]>([]) const conversations = ref<any[]>([])
const accounts = ref<any[]>([])
const bindVisible = ref(false)
const currentConversationId = ref<number | undefined>()
const bindForm = reactive({
accountId: undefined as number | undefined,
bindingType: 1,
})
async function loadConversations() {
try {
const res: any = await listConversations()
conversations.value = res.data || []
} catch (e: any) {
ElMessage.error(e.message)
}
}
async function loadAccounts() {
try {
const res: any = await listChannelAccounts()
accounts.value = res.data || []
} catch (e: any) {
ElMessage.error(e.message)
}
}
async function handleCreate() { async function handleCreate() {
try { try {
@@ -55,4 +128,28 @@ async function handleCreate() {
ElMessage.error(e.message) ElMessage.error(e.message)
} }
} }
function openBind(row: any) {
currentConversationId.value = row.id
bindForm.accountId = undefined
bindForm.bindingType = 1
bindVisible.value = true
}
async function handleBind() {
if (!currentConversationId.value) return
try {
await bindConversationAccount(currentConversationId.value, bindForm)
ElMessage.success('绑定成功')
bindVisible.value = false
await loadConversations()
} catch (e: any) {
ElMessage.error(e.message)
}
}
onMounted(() => {
loadConversations()
loadAccounts()
})
</script> </script>

View File

@@ -2,13 +2,13 @@
<div> <div>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="6"> <el-col :span="6">
<el-statistic title="渠道主体" :value="stats.subjects" /> <el-statistic title="渠道主体" :value="stats.subjectCount" />
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-statistic title="渠道账号" :value="stats.accounts" /> <el-statistic title="渠道账号" :value="stats.accountCount" />
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-statistic title="会话/群聊" :value="stats.conversations" /> <el-statistic title="会话/群聊" :value="stats.conversationCount" />
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-statistic title="今日发送" :value="stats.sentToday" /> <el-statistic title="今日发送" :value="stats.sentToday" />
@@ -25,14 +25,27 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from 'vue' import { onMounted, reactive } from 'vue'
import { ElMessage } from 'element-plus'
import { getDashboardStats } from '@/api/dashboard'
const stats = reactive({ const stats = reactive({
subjects: 0, subjectCount: 0,
accounts: 0, accountCount: 0,
conversations: 0, conversationCount: 0,
sentToday: 0, sentToday: 0,
}) })
async function loadStats() {
try {
const res: any = await getDashboardStats()
Object.assign(stats, res.data || {})
} catch (e: any) {
ElMessage.error(e.message)
}
}
onMounted(loadStats)
</script> </script>
<style scoped> <style scoped>

View File

@@ -35,9 +35,9 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue' import { onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { createPerson } from '@/api/crm' import { createPerson, listPersons } from '@/api/crm'
const form = reactive({ const form = reactive({
personCode: '', personCode: '',
@@ -48,6 +48,15 @@ const form = reactive({
const persons = ref<any[]>([]) const persons = ref<any[]>([])
async function loadPersons() {
try {
const res: any = await listPersons()
persons.value = res.data || []
} catch (e: any) {
ElMessage.error(e.message)
}
}
async function handleCreate() { async function handleCreate() {
try { try {
const res: any = await createPerson(form) const res: any = await createPerson(form)
@@ -57,4 +66,6 @@ async function handleCreate() {
ElMessage.error(e.message) ElMessage.error(e.message)
} }
} }
onMounted(loadPersons)
</script> </script>

View File

@@ -4,8 +4,16 @@
<el-form-item label="标签名"> <el-form-item label="标签名">
<el-input v-model="form.tagName" placeholder="标签名" /> <el-input v-model="form.tagName" placeholder="标签名" />
</el-form-item> </el-form-item>
<el-form-item label="父标签ID"> <el-form-item label="父标签">
<el-input-number v-model="form.parentId" :min="0" /> <el-select v-model="form.parentId" placeholder="选择父标签">
<el-option label="无" :value="0" />
<el-option
v-for="t in tags"
:key="t.id"
:label="t.tagName"
:value="t.id"
/>
</el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleCreate">创建</el-button> <el-button type="primary" @click="handleCreate">创建</el-button>