Files
medical-mall/pages/mall/admin/maintain/api/account.uvue

339 lines
12 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="admin-page">
<view class="admin-sections">
<!-- 提示栏 -->
<view class="alert-warning">
<text class="alert-content">获取访问 Token 的接口:\n请求 URL/outapi/access_token 请求方式POST 请求参数appid和appsecret 返回数据access_token访问令牌 exp_time令牌过期时间 auth_info授权信息\n使用获取到的 Token 访问对外接口:\n在 HTTP 请求头中添加 Authorization 字段 字段值为 Bearer access_token(注意 Bearer 后有一个空格)</text>
</view>
<!-- 操作栏 -->
<view class="action-bar header-actions">
<button class="btn primary" @click="addAccount">添加账号</button>
</view>
<!-- 表格内容 -->
<view class="admin-card content-card">
<view class="table-container list-table">
<view class="table-header">
<view class="col col-id"><text>编号</text></view>
<view class="col col-account"><text>账号</text></view>
<view class="col col-desc"><text>描述</text></view>
<view class="col col-add-time"><text>添加时间</text></view>
<view class="col col-last-time"><text>最后登录时间</text></view>
<view class="col col-last-ip"><text>最后登录ip</text></view>
<view class="col col-status"><text>状态</text></view>
<view class="col col-action"><text>操作</text></view>
</view>
<view class="table-body">
<view v-for="item in pagedList" :key="item.id" class="table-row">
<view class="col col-id"><text>{{ item.id }}</text></view>
<view class="col col-account"><text>{{ item.account }}</text></view>
<view class="col col-desc"><text>{{ item.desc }}</text></view>
<view class="col col-add-time"><text>{{ item.addTime }}</text></view>
<view class="col col-last-time"><text>{{ item.lastTime }}</text></view>
<view class="col col-last-ip"><text>{{ item.lastIp }}</text></view>
<view class="col col-status">
<view :class="['status-tag', item.status ? 'active' : 'inactive']" @click="toggleStatus(item)">
<text class="tag-text">{{ item.status ? '开启' : '关闭' }}</text>
<view class="tag-dot"></view>
</view>
</view>
<view class="col col-action">
<text class="action-btn" @click="setConfig(item)">设置</text>
<text class="action-btn divider">|</text>
<text class="action-btn" @click="editItem(item)">编辑</text>
<text class="action-btn divider">|</text>
<text class="action-btn danger" @click="deleteItem(item)">删除</text>
</view>
</view>
</view>
</view>
<CommonPagination
v-if="true"
:total="total"
:loading="false"
:currentPage="currentPage"
:pageSize="pageSize"
:pageSizeOptionLabels="pageSizeOptionLabels"
:pageSizeIndex="pageSizeIndex"
:visiblePages="visiblePages"
:totalPage="totalPage"
:jumpPageInput="jumpPageInput"
@page-size-change="handlePageSizeChange"
@page-change="handlePageChange"
@update:jumpPageInput="(val: string) => { jumpPageInput.value = val }"
@jump-page="handleJumpPage"
/>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { ref, computed } from 'vue'
import CommonPagination from '@/components/CommonPagination/CommonPagination.uvue'
// ========== MOCK DATA START ==========
// TODO: 接真实接口时替换此处 dataList 为 fetchApiAccountList() 调用
const dataList = ref([
{ id: 9, account: 'ceshi', desc: 'ceshi', addTime: '2024-09-05 11:16:07', lastTime: '暂无', lastIp: '', status: true },
{ id: 10, account: 'tuoluojiang', desc: '', addTime: '2024-09-09 10:12:54', lastTime: '2024-09-10 19:15:01', lastIp: '124.221.49.234', status: true },
{ id: 11, account: 'shop_api_01', desc: '商城对外接口', addTime: '2024-10-01 09:00:00', lastTime: '2024-10-15 14:22:11', lastIp: '10.0.0.1', status: true },
{ id: 12, account: 'erp_sync', desc: 'ERP同步接口', addTime: '2024-10-05 10:30:00', lastTime: '2024-10-20 08:10:00', lastIp: '192.168.1.100', status: true },
{ id: 13, account: 'wms_api', desc: '仓储系统接口', addTime: '2024-10-08 14:00:00', lastTime: '暂无', lastIp: '', status: false },
{ id: 14, account: 'oms_push', desc: '订单推送接口', addTime: '2024-10-10 11:20:00', lastTime: '2024-11-01 09:30:00', lastIp: '172.16.0.50', status: true },
{ id: 15, account: 'report_api', desc: '报表数据接口', addTime: '2024-10-12 15:45:00', lastTime: '2024-11-05 17:00:00', lastIp: '10.10.10.1', status: true },
{ id: 16, account: 'crm_sync', desc: 'CRM数据同步', addTime: '2024-10-15 09:00:00', lastTime: '暂无', lastIp: '', status: false },
{ id: 17, account: 'bi_export', desc: 'BI数据导出', addTime: '2024-10-18 10:00:00', lastTime: '2024-11-10 08:20:00', lastIp: '192.168.2.200', status: true },
{ id: 18, account: 'logistics_api', desc: '物流回调接口', addTime: '2024-10-20 14:30:00', lastTime: '2024-11-08 12:00:00', lastIp: '10.0.0.88', status: true },
{ id: 19, account: 'sms_gateway', desc: '短信网关接口', addTime: '2024-10-22 16:00:00', lastTime: '2024-11-12 09:45:00', lastIp: '203.0.113.5', status: true },
{ id: 20, account: 'pay_notify', desc: '支付回调接口', addTime: '2024-10-25 09:30:00', lastTime: '2024-11-15 11:00:00', lastIp: '47.100.200.1', status: true },
{ id: 21, account: 'stock_alert', desc: '库存预警接口', addTime: '2024-10-28 11:00:00', lastTime: '暂无', lastIp: '', status: false },
{ id: 22, account: 'audit_log', desc: '审计日志接口', addTime: '2024-11-01 10:00:00', lastTime: '2024-11-16 14:30:00', lastIp: '10.20.30.40', status: true },
{ id: 23, account: 'open_api_v2', desc: '对外开放接口v2', addTime: '2024-11-05 09:00:00', lastTime: '2024-11-17 10:10:00', lastIp: '120.55.66.77', status: true },
{ id: 24, account: 'internal_bot', desc: '内部机器人接口', addTime: '2024-11-08 13:15:00', lastTime: '2024-11-18 08:00:00', lastIp: '10.0.1.99', status: true },
{ id: 25, account: 'data_clean', desc: '数据清洗任务接口', addTime: '2024-11-10 15:00:00', lastTime: '暂无', lastIp: '', status: false },
{ id: 26, account: 'search_sync', desc: '搜索索引同步', addTime: '2024-11-12 10:30:00', lastTime: '2024-11-19 09:00:00', lastIp: '10.30.40.50', status: true },
{ id: 27, account: 'push_gateway', desc: '消息推送縯道', addTime: '2024-11-15 09:45:00', lastTime: '2024-11-20 11:30:00', lastIp: '47.200.100.5', status: true },
{ id: 28, account: 'cdn_purge', desc: 'CDN刷新接口', addTime: '2024-11-18 14:00:00', lastTime: '2024-11-21 13:00:00', lastIp: '1.2.3.4', status: true }
])
// ========== MOCK DATA END ==========
// ========== PAGINATION STATE ==========
const currentPage = ref(1)
const pageSize = ref(15)
const jumpPageInput = ref('')
const pageSizeOptions = [10, 15, 20, 30, 50]
const pageSizeOptionLabels = computed(() => pageSizeOptions.map((n: number) => `${n}条/页`))
const pageSizeIndex = computed(() => { const idx = pageSizeOptions.indexOf(pageSize.value); return idx >= 0 ? idx : 0 })
const total = computed(() => dataList.value.length)
const totalPage = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))
const pagedList = computed(() => {
const start = (currentPage.value - 1) * pageSize.value
return dataList.value.slice(start, start + pageSize.value)
})
const visiblePages = computed((): number[] => {
const t = totalPage.value; const cur = currentPage.value
if (t <= 7) return Array.from({ length: t }, (_: any, i: number) => i + 1)
if (cur <= 4) return [1, 2, 3, 4, 5, -1, t]
if (cur >= t - 3) return [1, -1, t - 4, t - 3, t - 2, t - 1, t]
return [1, -1, cur - 1, cur, cur + 1, -1, t]
})
const handlePageChange = (p: number) => { currentPage.value = p }
const handlePageSizeChange = (e: any) => {
const idx = Number(e.detail.value)
pageSize.value = pageSizeOptions[idx] ?? pageSizeOptions[0]
currentPage.value = 1
}
const handleJumpPage = () => {
const p = parseInt(jumpPageInput.value)
if (!isNaN(p) && p >= 1 && p <= totalPage.value) currentPage.value = p
}
// ========== END PAGINATION STATE ==========
function addAccount() {
uni.showToast({ title: '添加账号', icon: 'none' })
}
function toggleStatus(item: any) {
item.status = !item.status
}
function setConfig(item: any) {
uni.showToast({ title: '参数设置: ' + item.account, icon: 'none' })
}
function editItem(item: any) {
uni.showToast({ title: '编辑: ' + item.account, icon: 'none' })
}
function deleteItem(item: any) {
uni.showModal({
title: '提示',
content: '确定要删除此账号吗?',
success: (res) => {
if (res.confirm) {
uni.showToast({ title: '删除成功' })
}
}
})
}
</script>
<style scoped lang="scss">
.admin-page {
/* 使用 Layout 的背景和内边距 */
min-height: 100vh;
}
.alert-warning {
background-color: #fff7e6;
border: 1px solid #ffe7ba;
padding: 16px 20px;
border-radius: 4px;
margin-bottom: 24px;
}
.alert-content {
color: #fa8c16;
font-size: 14px;
line-height: 1.8;
white-space: pre-wrap;
}
.action-bar {
margin-bottom: 20px;
}
.admin-card {
background-color: #fff;
border-radius: 4px;
padding: 0;
overflow: hidden;
}
.btn {
height: 32px;
padding: 0 16px;
border-radius: 4px;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: none;
}
.btn.primary {
background-color: #1890ff;
color: #fff;
}
.table-container {
width: 100%;
}
.table-header {
display: flex;
flex-direction: row;
background-color: #fafafa;
border-bottom: 1px solid #f0f0f0;
}
.table-row {
display: flex;
flex-direction: row;
border-bottom: 1px solid #f0f0f0;
}
.col {
padding: 16px;
display: flex;
align-items: center;
font-size: 14px;
color: #333;
}
.col-id { width: 80px; }
.col-account { width: 120px; }
.col-desc { flex: 1; }
.col-add-time { width: 180px; }
.col-last-time { width: 180px; }
.col-last-ip { width: 150px; }
.col-status { width: 100px; justify-content: center; }
.col-action { width: 200px; justify-content: flex-end; display: flex; flex-direction: row; }
.status-tag {
width: 60px;
height: 24px;
border-radius: 12px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 0 8px;
cursor: pointer;
}
.status-tag.active {
background-color: #1890ff;
color: #fff;
}
.status-tag.inactive {
background-color: #d9d9d9;
color: #fff;
}
.tag-text {
font-size: 12px;
}
.tag-dot {
width: 8px;
height: 8px;
background-color: #fff;
border-radius: 50%;
}
.action-btn {
color: #1890ff;
cursor: pointer;
}
.action-btn.danger {
color: #ff4d4f;
}
.action-btn.divider {
margin: 0 8px;
color: #e8e8e8;
}
.pagination {
padding: 16px 24px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
gap: 16px;
}
.page-info {
font-size: 14px;
color: #666;
}
.page-btns {
display: flex;
flex-direction: row;
gap: 8px;
}
.p-btn {
width: 32px;
height: 32px;
border: 1px solid #d9d9d9;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
color: #666;
cursor: pointer;
}
.p-btn.active {
background-color: #fff;
border-color: #1890ff;
color: #1890ff;
}
.p-btn.disabled {
color: #bfbfbf;
cursor: not-allowed;
}
</style>